MAATRIX / Блог / CI/CD на VPS через GitHub Actions: self-hosted runner и rsync

CI/CD на VPS через GitHub Actions: self-hosted runner и rsync

Блог MAATRIX · 2026-07-07

GitHub Actions умеет собирать и выкатывать код прямо на ваш VPS. Разберём два рабочих подхода: self-hosted runner для сборки на сервере и лёгкий rsync-деплой по SSH с облачных раннеров.

Два подхода к деплою

['Есть два способа выкатывать код на VPS из GitHub Actions, и выбор зависит от того, где происходит сборка.', '
  • Self-hosted runner — агент GitHub на самом VPS. Сборка и тесты идут прямо на сервере, деплой сводится к перемещению файлов и рестарту сервиса. Удобно для тяжёлых сборок и приватных данных.
  • rsync/SSH с облачного раннера — сборка на бесплатных раннерах GitHub, а на VPS попадает только готовый артефакт. Ничего лишнего на сервере не крутится.
', 'Для стабильной сборки важен быстрый диск и предсказуемое CPU: на AMD EPYC + NVMe у MAATRIX self-hosted runner собирает проект заметно быстрее, чем на дешёвом OpenVZ с плавающей нагрузкой.']

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK и США. Оплата картой РФ и по СБП.

Арендовать VPS для CI/CD

Вариант 1: self-hosted runner

['В репозитории откройте Settings → Actions → Runners → New self-hosted runner, выберите Linux x64 и скопируйте команды. На VPS создайте отдельного пользователя и разверните агента.', '
adduser --disabled-password --gecos "" runner\nsu - runner\nmkdir actions-runner && cd actions-runner\ncurl -o actions-runner.tar.gz -L \\\n  https://github.com/actions/runner/releases/download/v2.319.1/actions-runner-linux-x64-2.319.1.tar.gz\ntar xzf actions-runner.tar.gz\n./config.sh --url https://github.com/USER/REPO --token <TOKEN>
', 'Токен из веб-интерфейса живёт около часа — если конфиг ругается на авторизацию, сгенерируйте новый. Дальше поставьте раннер как systemd-сервис, чтобы он поднимался после перезагрузки.', '
sudo ./svc.sh install runner\nsudo ./svc.sh start\nsudo ./svc.sh status
']

Workflow для self-hosted runner

['Файл .github/workflows/deploy.yml. Раннер уже на сервере, поэтому деплой — это git pull, установка зависимостей и рестарт.', '
name: deploy\non:\n  push:\n    branches: [ main ]\njobs:\n  deploy:\n    runs-on: self-hosted\n    steps:\n      - uses: actions/checkout@v4\n      - name: Build\n        run: |\n          npm ci\n          npm run build\n      - name: Restart service\n        run: sudo systemctl restart myapp
', 'Чтобы systemctl restart работал без пароля, добавьте пользователю точечное правило в sudoers через visudo -f /etc/sudoers.d/runner:', '
runner ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp
']

Вариант 2: rsync-деплой по SSH

['Сборка идёт на облачном раннере, на VPS уезжает только каталог dist. Сгенерируйте отдельный SSH-ключ для деплоя и положите публичную часть в ~/.ssh/authorized_keys на сервере, а приватную — в секреты репозитория (SSH_KEY, HOST, USER).', '
ssh-keygen -t ed25519 -C "gh-deploy" -f deploy_key -N ""
', '
name: deploy\non: { push: { branches: [ main ] } }\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - run: npm ci && npm run build\n      - name: rsync to VPS\n        run: |\n          mkdir -p ~/.ssh\n          echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_ed25519\n          chmod 600 ~/.ssh/id_ed25519\n          ssh-keyscan ${{ secrets.HOST }} >> ~/.ssh/known_hosts\n          rsync -az --delete ./dist/ \\\n            ${{ secrets.USER }}@${{ secrets.HOST }}:/var/www/app/
', 'Флаг --delete удаляет на сервере файлы, которых больше нет в сборке — так каталог всегда точно повторяет артефакт. Root-доступ на VPS MAATRIX позволяет сразу настроить права и пользователя деплоя без запросов в поддержку.', 'Отдельный совет: не деплойте под root. Заведите пользователя deploy с доступом только к каталогу приложения и точечным правом на рестарт сервиса. Так утечка деплой-ключа не даст злоумышленнику весь сервер, а лишь ограниченную роль. Ключ деплоя держите отдельным от вашего личного SSH-ключа и при компрометации меняйте только его.', 'После деплоя полезно дёрнуть уведомление в мессенджер — тогда команда сразу видит, какой коммит уехал в прод. В GitHub Actions это делается дополнительным шагом с curl на вебхук Telegram или Slack.']

Частые ошибки

['
  • Раннер offline после ребута — забыли svc.sh install, агент запускался только вручную.
  • Permission denied при рестарте — нет правила в sudoers или опечатка в имени сервиса.
  • Host key verification failed — не выполнили ssh-keyscan, ключ хоста неизвестен раннеру.
  • rsync снёс лишнее--delete с неверным путём назначения. Всегда указывайте конечный слэш в путях.
']

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK и США. Оплата картой РФ и по СБП.

Арендовать VPS для CI/CD

Частые вопросы

Self-hosted runner безопасен для публичного репозитория?

Нет. Для публичных репозиториев self-hosted runner опасен: чужой PR может выполнить код на вашем сервере. Используйте его только в приватных репозиториях.

Сколько ресурсов ест раннер в простое?

В простое агент почти не потребляет ресурсов — несколько десятков мегабайт RAM. Нагрузка появляется только на время сборки.

Можно ли деплоить без пересборки на сервере?

Да, вариант с rsync именно для этого: сборка на облачном раннере, на VPS уходит готовый артефакт.