rsync в GitLab CI: развёртывание через SSH

- Кратко: интегрируйте rsync в Docker‑запуск GitLab CI, добавив openssh-client и rsync в образ, передав приватный ключ через защищённую переменную и занеся хост в known_hosts. Это даёт быстрые инкрементные развёртывания без больших Docker-образов.
- Важное: храните приватный ключ как защищённую CI‑переменную, ограничьте его права на целевом сервере и предпочитайте known_hosts вместо отключения проверки хоста.
Быстрые ссылки
- Pipeline Executors
- Подготовка
- Добавление файла pipeline
- Установка SSH и rsync
- Управление проверкой хоста
- Дальнейшие улучшения
- Плейбук: шаги для развёртывания
- Критерии приёмки
- Безопасность и соответствие
- Часто задаваемые вопросы
- Резюме
rsync — популярная утилита синхронизации файлов, использующая дельта‑алгоритм для минимизации потребления трафика. Частое применение — развёртывание собранного сайта на удалённый production‑сервер. Ниже объяснено, как сочетать гибкость rsync с автоматизацией GitLab CI.
Pipeline Executors
GitLab CI поддерживает несколько типов исполнителей (executors). Они определяют среду выполнения задач.
shell- shell — исполнитель по умолчанию, выполняет команды прямо на хосте. Удобен, если на runner уже установлен rsync и ssh.
- Преимущество: можно использовать любые команды хоста без допнастроек.
- Недостаток: слабая изоляция, риск загрязнения хоста.
Лучшей практикой обычно является использование
docker- docker — создаёт чистый контейнер для каждой CI‑задачи. Изоляция лучше, работа безопаснее для хоста.
- Минус: минимальные базовые образы часто не содержат rsync и ssh.
Ниже показано, как добавить rsync в Docker‑задачу. Предполагается, что у вас есть Docker‑runner и проект в GitLab.
Подготовка
Нужна пара SSH‑ключей, если вы будете подключаться к удалённому хосту по SSH. Создать пару можно так:
ssh-keygen -t rsaСкопируйте публичный ключ на сервер (в зависимости от сервера используйте ssh-copy-id или вручную добавить в ~/.ssh/authorized_keys).
Содержимое приватного ключа загрузите в буфер обмена и затем — в CI‑переменную проекта:
cat ~/.ssh/id_rsa | xclip -selection cВ GitLab: Settings → CI/CD → Variables. Создайте переменную, например SSH_PRIVATE_KEY, и вставьте весь приватный ключ включая строки —–BEGIN RSA PRIVATE KEY—– и —–END RSA PRIVATE KEY—–. Установите флажки “Protected” и “Masked” при необходимости.

После этого GitLab сможет инжектировать ключ в контейнер во время выполнения pipeline.
Добавление файла pipeline
GitLab CI использует файл .gitlab-ci.yml в корне репозитория. Пример минимальной задачи, которая будет пытаться выполнить rsync:
deploy:
stage: deploy
image: alpine:latest
script:
- rsync -atv --delete --progress ./ user@example.com:/var/www/htmlЭтот пример синхронизирует содержимое рабочей директории на сервер example.com в /var/www/html, но упадёт на этапе запуска, потому что в alpine:latest не установлен rsync и клиент SSH.
Установка SSH и rsync
Alpine — хороший выбор для контейнера благодаря маленькому размеру. Добавим пакеты openssh-client и rsync, затем запустим ssh‑агент и зарегистрируем приватный ключ из CI‑переменной.
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk update && apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
script:
- rsync -atv --delete --progress ./ user@example.com:/var/www/htmlПояснения:
- apk add устанавливает openssh-client и rsync.
- eval $(ssh-agent -s) запускает ssh‑агент.
- echo “$SSH_PRIVATE_KEY” | ssh-add - — добавляет приватный ключ в агент. Команда tr -d ‘\r’ полезна при переносе ключа между Windows и Unix.
Управление проверкой хоста
При первом подключении SSH интерактивно запросит подтверждение ключа хоста. CI‑среда не позволяет отвечать на такие запросы, поэтому есть два пути:
- Отключить строгую проверку ключа — быстро, но менее безопасно.
- echo "Host *\n StrictHostKeyChecking no\n UserKnownHostsFile=/dev/null" >> ~/.ssh/config- Предварительно зарегистрировать ключ хоста в known_hosts (рекомендуется).
- На локальной машине выполните:
ssh-keyscan -p 22 example.com- Скопируйте полученную строку и создайте CI‑переменную SSH_HOST_KEY. В pipeline добавьте:
- mkdir -p ~/.ssh
- echo "$SSH_HOST_KEY" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hostsИспользование known_hosts даёт гарантию, что вы подключаетесь к ожидаемому серверу и не отключает проверку, что повышает безопасность.
Полный пример .gitlab-ci.yml с переменными
variables:
DEPLOY_USER: "user"
DEPLOY_HOST: "example.com"
DEPLOY_DIR: "/var/www/html"
stages:
- deploy
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk update && apk add --no-cache openssh-client rsync
- mkdir -p ~/.ssh
- echo "$SSH_HOST_KEY" > ~/.ssh/known_hosts
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
script:
- rsync -az --delete --progress ./ "$DEPLOY_USER"@"$DEPLOY_HOST":"$DEPLOY_DIR"
only:
- mainРекомендуем вынести DEPLOY_* переменные в настроечные CI‑переменные проекта, чтобы не держать их в репозитории.
Дальнейшие улучшения и альтернативы
- Использовать специализированный Docker образ, в который уже включены rsync и ssh, чтобы уменьшить шаги установки в каждом pipeline.
- Построить stage “build image” в CI, который собирает образ с нужными утилитами и пушит его в private registry — ускоряет последующие pipelines.
- Рассмотреть артефакты GitLab (artifacts) и хранение билдов в контейнерном реестре/объектном хранилище, если развёртывание требует дополнительных шагов.
- Альтернатива rsync: scp (простой, но менее эффективен), lftp/mirror (для FTP), SFTP или специализированные инструменты развёртывания (Ansible, Capistrano).
Когда это не подходит (контрпримеры)
- Если у вас масштабируемая инфраструктура с балансировкой нагрузки и несколькими узлами — лучше использовать более управляемые механизмы (CI → артефакт → orchestration или периодический pull с каждой ноды).
- Если нужно гарантированное атомарное переключение на новый релиз (без промежуточных частично обновлённых файлов), используйте подход с развёртыванием в отдельную директорию и атомарным symlink‑переключением.
- Для сложных миграций баз данных и rollbacks rsync сам по себе недостаточен.
Плейбук: шаги для развёртывания (SOP)
- Локально: сгенерировать SSH‑ключи, проверить доступ к серверу.
- Локально: получить строку known_hosts через ssh-keyscan и сохранить.
- В GitLab: добавить CI‑переменные: SSH_PRIVATE_KEY (protected, masked), SSH_HOST_KEY (protected).
- Добавить .gitlab-ci.yml с установкой openssh-client и rsync.
- Настроить user с минимальными правами на сервере — ограничить команды через authorized_keys опции при необходимости.
- Прогнать pipeline на staging‑ветке.
- Проверить файлы на сервере, проверить логи rsync –progress.
- Перекатить изменения в main / production.
Роль‑ориентированные чеклисты
DevOps:
- Проверить runner (docker executor) и доступ к registry.
- Настроить секреты и права доступа в GitLab.
- Проверить настройки SSH на целевом сервере.
Разработчик:
- Убедиться, что сборка помещается в рабочую директорию.
- Протестировать локально команду rsync.
Системный администратор:
- Ограничить права ключа в authorized_keys (no-port-forwarding,no-X11-forwarding,command=”…” по необходимости).
- Проверить место на диске и права директорий назначения.
Критерии приёмки
- Pipeline успешно проходит на ветке deploy/main.
- Файлы на сервере совпадают с артефактом сборки (проверено checksum/списком файлов).
- Права и владельцы файлов установлены корректно.
- Нет предупреждений SSH о неподтверждённых ключах.
- Развёртывание откатывается/исправляется простым запуском предыдущей версии (описан rollback).
Откат (runbook/rollback)
- Если развёртывание нарушило работу, приостановите CI‑триггеры для main.
- Если у вас есть snapshot каталога (например, /var/www/html_prev), выполните rsync со старой копии:
rsync -az --delete /var/www/html_prev/ user@example.com:/var/www/html/- Альтернатива — восстановление из резервной копии или переключение симлинка на предыдущую папку release.
- Проанализировать логи rsync и системные логи сервера, восстановить данные, если нужно.
Безопасность и соответствие
- Храните SSH_PRIVATE_KEY как Protected и Masked переменные в GitLab.
- Ограничьте права ключа на сервере. Пример записи в ~/.ssh/authorized_keys:
from="CI_SERVER_IP_RANGE",no-pty,no-agent-forwarding,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ...- Не отключайте StrictHostKeyChecking в production. Вместо этого используйте SSH_HOST_KEY.
- Рассмотрите использование временных/эпhemeral ключей через секретные хранилища (HashiCorp Vault, AWS Secrets Manager) для повышения безопасности.
- Храните логи и аудит подключения отдельно, чтобы отслеживать доступ.
Шпаргалка: часто используемые флаги rsync
- -a — archive (рекурсивно, сохраняет права, симлинки и т.д.)
- -z — сжатие данных при передаче
- -v — verbose
- -t — сохранять время модификации
- –delete — удалять на целевом стороне файлы, отсутствующие в исходной директории
- –progress — показывать прогресс передачи
- –exclude=”node_modules” — исключить директорию
Пример: rsync -az –delete –exclude=”.git” ./ user@host:/var/www/html
Decision flow (выбор стратегии)
flowchart TD
A[Нужен быстрый простой деплой?] -->|Да| B[Использовать rsync в GitLab CI]
A -->|Нет, масштабируемая инфраструктура| C[Рассмотреть артефакты и orchestration]
B --> D{Docker runner?}
D -->|Да| E[Добавить openssh-client и rsync в before_script]
D -->|Нет, shell runner| F[Запустить напрямую, убедиться в безопасности хоста]
E --> G{Безопасность важна?}
G -->|Да| H[Использовать SSH_HOST_KEY и ограниченные ключи]
G -->|Нет| I[Можно временно отключить StrictHostKeyChecking]Часто задаваемые вопросы
Нужно ли ставить rsync в каждый pipeline‑контейнер?
Не обязательно: можно собрать собственный базовый образ с rsync/ssh и хранить его в registry, чтобы ускорять pipelines.
Можно ли использовать deploy key вместо пользовательского SSH‑ключа?
Да. Deploy key (ключ, добавленный в репозиторий или на сервер) — хорошая практика: создайте ключ с минимальными правами и используйте его только для доступа к папке deploy.
Как защитить приватный ключ в GitLab?
Отключите возможность отображать переменной (Mask) и сделайте её Protected, чтобы переменная была доступна только веткам/тегам с защитой.
Факто‑бокс: главные идеи
- rsync экономит трафик за счёт передачи только изменённых частей файлов.
- Docker‑runner даёт изоляцию, но требует явной установки зависимостей.
- Всегда предпочитайте known_hosts отключению StrictHostKeyChecking для production.
Шаблонные проверки и тесты приёмки
- Тест 1: Pipeline завершается с кодом 0 на ветке deploy.
- Тест 2: Файл index.html обновлён на целевом сервере, timestamp совпадает с локальным.
- Тест 3: В логах нет сообщений о неизвестном хосте.
Краткое резюме
Интеграция rsync в GitLab CI при помощи Docker‑исполнителя требует нескольких дополнительных шагов: установка openssh-client и rsync в контейнере, безопасная передача приватного ключа через CI‑переменную и регистрация ключа хоста в known_hosts. Это даёт быстрые и эффективные развёртывания, если применять базовые меры безопасности и организовать повторно используемый образ/стадию для подготовки среды.
Важно: для production используйте ограниченные ключи, храните секреты в защищённых переменных и тестируйте откаты заранее.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента