Гид по технологиям

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

• 7 min read • DevOps • Обновлено 18 Nov 2025
rsync в GitLab CI: развёртывание по SSH
rsync в GitLab CI: развёртывание по SSH

Графика с логотипом GitLab — стилизованная голова лисы

Коротко: покажу, как использовать rsync внутри Docker‑окружения GitLab CI для безопасного развёртывания по SSH. Вы получите готовые примеры .gitlab-ci.yml, инструкции по добавлению SSH‑ключа и known_hosts, чеклисты безопасности и готовые сниппеты для Alpine и Debian образов.

Быстрые ссылки

  • Pipeline Executors
  • Getting Ready
  • Adding Your Pipeline File
  • Installing SSH and rsync
  • Managing Host Verification
  • Further Improvements
  • Summary

rsync — популярная утилита для синхронизации файлов, оптимизированная по трафику. Частое применение — развёртывание готовой сборки сайта на удалённый production‑сервер. В этой статье мы объединяем гибкость rsync с автоматизацией GitLab CI, чтобы безопасно и предсказуемо доставлять артефакты на удалённый хост.

Pipeline Executors

GitLab CI поддерживает несколько типов исполнителей (executors), которые определяют окружение для выполнения job’ов.

  • shell — выполняет задачи на хосте раннера напрямую. Достоинство: доступ ко всем установленным в системе командам, в том числе rsync, без дополнительных шагов. Недостаток: слабая изоляция и риск загрязнения хоста.

  • docker — создаёт новый контейнер для каждой job’ы. Плюсы: чистое окружение, предсказуемость и повторяемость. Минус: официальный образ, например ubuntu:latest или alpine:latest, часто не содержит rsync и ssh по умолчанию, поэтому придётся добавить зависимости в скрипт.

Мы предполагаем, что вы используете Docker‑based GitLab Runner. Если у вас shell‑runner и rsync уже установлен на хосте, многие шаги можно упростить.

Getting Ready

Требования перед началом:

  • Доступ в репозиторий проекта в GitLab.
  • Docker‑раннер или shell‑раннер с правами на выполнение необходимых команд.
  • SSH‑ключи: сгенерированная пара публичного/приватного ключей, публичный ключ добавлен в ~/.ssh/authorized_keys на целевом сервере.

Генерация ключей (на вашей машине):

ssh-keygen -t rsa

Скопируйте публичный ключ на сервер или используйте ssh-copy-id, если он доступен:

ssh-copy-id user@example.com

Приватный ключ нужно поместить как защищённую переменную в настройки GitLab CI. На локальной машине можно показать приватный ключ в буфер обмена, например (Linux с xclip):

cat ~/.ssh/id_rsa | xclip -selection c

В GitLab: Settings → CI/CD → Variables. Нажмите Add variable, введите ключ SSH_PRIVATE_KEY и вставьте значение приватного ключа целиком, включая строки -----BEGIN/-----END.

Скриншот добавления переменной GitLab CI

Убедитесь, что флажок «Protect variable»/«Masked» выставлен в соответствии с вашей политикой безопасности.

Adding Your Pipeline File

GitLab CI использует файл .gitlab-ci.yml в корне репозитория. Простейший пример job’ы, который попытается выполнить rsync, но упадёт на чистом Alpine образе, выглядит так:

deploy:
  stage: deploy
  image: alpine:latest
  script:
    - rsync -atv --delete --progress ./ user@example.com:/var/www/html

Эта конфигурация синхронизирует рабочую директорию репозитория в /var/www/html на сервере example.com под пользователем user. На деле rsync отсутствует в базовом Alpine, поэтому pipeline завершится с ошибкой.

Installing SSH and rsync

Лучше добавить OpenSSH и rsync в контейнер. Alpine подойдёт, потому что он лёгкий, а установка занимает мало места и времени. Пример расширенной секции before_script:

deploy:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk update && apk add --no-cache openssh-client rsync
    - mkdir -p ~/.ssh
    - 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 --no-cache openssh-client rsync — устанавливает необходимые пакеты в контейнере.
  • mkdir -p ~/.ssh — создаёт директорию для ключей и known_hosts.
  • ssh-agent и ssh-add — добавляют приватный ключ в агент для аутентификации.
  • tr -d '\r' — удаляет возможные символы CRLF, которые могут сломать формат ключа при копировании из Windows.

Альтернативный образ: Debian/Ubuntu

Если вы предпочитаете Debian/Ubuntu как базу, используйте официальный образ и установите пакеты через apt:

deploy-debian:
  stage: deploy
  image: debian:stable-slim
  before_script:
    - apt-get update && apt-get install -y openssh-client rsync ca-certificates
    - mkdir -p ~/.ssh
    - eval "$(ssh-agent -s)"
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  script:
    - rsync -az --delete ./ user@example.com:/var/www/html

Используйте -a/-z флаги rsync в зависимости от требований: -a (архивный режим) сохраняет права и симлинки, -z включает сжатие при пересылке.

Managing Host Verification

SSH по умолчанию запрашивает подтверждение ключа сервера при первом подключении — в CI это невозможно ответить интерактивно. Есть два подхода:

  1. Отключить строгую проверку хоста (несмотря на риск).
  2. Добавить known_hosts заранее как защищённую переменную — предпочтительный безопасный вариант.

Пример (небезопасный) — отключение проверки хоста:

- echo "Host *\n  StrictHostKeyChecking no\n  UserKnownHostsFile=/dev/null" >> ~/.ssh/config

Этот метод упрощает подключение, но делает вас уязвимыми к MITM‑атакам — не рекомендуем для production.

Безопасный вариант — добавить строку из вашего ~/.ssh/known_hosts в переменные GitLab как SSH_HOST_KEY, затем в pipeline:

  before_script:
    - mkdir -p ~/.ssh
    - echo "$SSH_HOST_KEY" > ~/.ssh/known_hosts

Чтобы получить строку known_hosts локально, выполните на своей машине:

ssh-keyscan -t rsa example.com

или подключитесь к серверу один раз и скопируйте соответствующую строку из ~/.ssh/known_hosts.

Скриншот добавления значения переменной в GitLab

Полный пример .gitlab-ci.yml — готовый к использованию

Ниже пример CI‑конфига с переменными для удобства и безопасными шагами:

stages:
  - build
  - deploy

variables:
  TARGET_USER: "user"
  TARGET_HOST: "example.com"
  TARGET_DIR: "/var/www/html"

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 ./ "$TARGET_USER"@"$TARGET_HOST":"$TARGET_DIR"
  only:
    - main

Ключевые моменты:

  • Переменные TARGET_USER, TARGET_HOST, TARGET_DIR выносятся в раздел variables для простоты изменения и безопасности.
  • only: - main ограничивает выполнение деплоя веткой main (можно заменить на protected branches или тэги).

Further Improvements

Рекомендации для повышения надёжности и повторяемости:

  • Собирайте кастомный Docker‑образ с уже установленными rsync и ssh, публикуйте его в приватном реестре. Так вы ускорите pipeline и уменьшите количество команд в before_script.
  • Разделяйте стадии: сначала создавайте артефакт (build), затем в stage deploy используйте только нужные артефакты, минимизируя размер данных.
  • Используйте проверки целостности: перед релизом выполняйте быструю проверку контрольных сумм (например, sha256sum) и сохраняйте их в артефакте.
  • Настройте SLI/SLO для пайплайнов: время выполнения деплоя и его успешность.
  • Логируйте вывод rsync в отдельный артефакт для последующего анализа (особенно при проблемах с синхронизацией).

Безопасность и лучшие практики

  • Храните приватный ключ как защищённую/защищённую и защищённую переменную (protected/masked) в GitLab.
  • Минимизируйте привилегии ключа: используйте отдельного пользователя на сервере с ограниченными правами; применяйте command= и from= в authorized_keys, если нужно.
  • Ограничьте доступ по IP, если возможно (firewall, cloud security groups).
  • Используйте проверку known_hosts вместо отключения StrictHostKeyChecking.
  • Рассмотрите использование более безопасного ключа (ed25519) вместо устаревшего rsa.

Troubleshooting — распространённые проблемы и их решения

  • Ошибка Permission denied (publickey): проверьте, что приватный ключ корректно добавлен в GitLab и что публичный ключ в authorized_keys совпадает.
  • Ошибка с форматом ключа: используйте tr -d '\r' при чтении переменной, чтобы убрать CRLF.
  • Rsync завершает работу с ошибкой прав: проверьте права на целевой директории и пользователя, под которым выполняется rsync.
  • Производительность низкая: включите -z для сжатия, оптимизируйте exclude (исключайте node_modules, .git и т. п.).

Playbook для безопасного деплоя (шаги)

  1. На локальной машине сгенерируйте ключи: ssh-keygen -t ed25519.
  2. Добавьте публичный ключ в /home/deploy/.ssh/authorized_keys на целевом сервере.
  3. В GitLab Settings → CI/CD → Variables добавьте SSH_PRIVATE_KEY (masked, protected) и SSH_HOST_KEY (masked).
  4. Добавьте .gitlab-ci.yml с приведённой выше конфигурацией и переменными.
  5. Протестируйте деплой в staging‑ветке на отдельном сервере.
  6. После успешного теста включите запуск только для protected ветки main или тэгов релиза.

Критерии приёмки

  • Pipeline успешно завершает job деплоя без интерактивных подсказок.
  • Файлы в целевой директории совпадают с ожидаемыми (проверка checksum или директории).
  • Приватный ключ хранится как защищённая переменная; known_hosts добавлен заранее.

Примеры exclude/rsync‑шаблонов

Если не нужно копировать временные или локальные каталоги, добавьте файл .rsync-filter или флаг --exclude:

rsync -az --delete --progress --exclude 'node_modules' --exclude '.git' ./ user@example.com:/var/www/html

Файл .rsync-filter (пример):

- node_modules/
- .git/
- tmp/

Snippet: создание собственного Docker образа с rsync и ssh

Dockerfile для образа, который можно использовать как image в .gitlab-ci.yml:

FROM alpine:latest
RUN apk update && apk add --no-cache openssh-client rsync ca-certificates
ENTRYPOINT ["/bin/sh", "-lc"]

Соберите и загрузите образ в реестр, затем указывайте его в конфиге:

image: registry.example.com/ci-images/alpine-rsync:latest

Это ускорит время запуска job’ов и упростит содержание before_script.

Mini‑методология: как подойти к деплою через rsync

  1. Минимизируйте права доступа и используйте отдельного пользователя deploy.
  2. Храните секреты в CI переменных, не в репозитории.
  3. Используйте known_hosts для проверки подлинности сервера.
  4. Тестируйте на staging перед production.
  5. Логируйте и сохраняйте артефакты логов для диагностики.

Глоссарий (1‑строчные определения)

  • rsync: утилита для эффективной синхронизации файлов между локальным и удалённым узлом.
  • GitLab Runner: процесс, выполняющий CI job’ы для проекта.
  • SSH agent: менеджер приватных ключей для аутентификации по SSH.
  • known_hosts: файл, содержащий публичные ключи серверов для проверки подлинности.

Decision flow (Mermaid)

flowchart TD
  A[Есть Docker Runner?] -->|Да| B[Добавить rsync и ssh в before_script]
  A -->|Нет| C[Проверить, установлен ли rsync на хосте]
  B --> D{Добавлен known_hosts?}
  D -->|Да| E[Добавить SSH_PRIVATE_KEY как переменную]
  D -->|Нет| F[Добавить SSH_HOST_KEY в GitLab Variables]
  C --> G[Использовать shell runner или встроенный rsync]
  E --> H[Запустить pipeline]
  F --> H
  G --> H

Summary

Использование rsync в GitLab CI даёт быстрый и надёжный способ развёртывания файлов по SSH, но требует ручной настройки окружения в Docker‑job’ах: установки openssh-client и rsync, добавления приватного ключа в CI‑переменные и регистрации known_hosts. Оптимальный путь — выносить часто используемые зависимости в свой Docker‑образ, выносить параметры (хост, путь, пользователь) в переменные, и следовать практикам безопасности при хранении ключей.

Вам доступны варианты: быстрое, но рискованное отключение проверки хоста, либо безопасный метод с добавлением known_hosts. Для production рекомендуется второй.

Важно

  • Никогда не храните приватный ключ в репозитории.
  • Тестируйте деплой в staging перед production.

Дополнительные ресурсы и чеклисты размещены выше в статье.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро