~/wiki / zapusk-i-khosting / github-actions-auto-deploy-vps-ssh-guide

Автоматический деплой на VPS через GitHub Actions — пошаговый гайд

◷ 9 мин чтения 31.05.2026

Основной чат

Чат для вайбкодеров: новости, гайды, поиск исполнителей, маркетплейс и разбор реальных кейсов.

$ cd раздел/ $ join vibe dev

Вы написали код, ИИ помог, всё работает локально. Пора выкатить на сервер. Открываете терминал, подключаетесь по SSH, тянете git pull, перезапускаете процесс... и это нужно делать каждый раз. При каждом фиксе. При каждом обновлении.

Это не рабочий процесс — это ручной труд, который съедает время и рано или поздно приводит к ошибкам.

CI/CD (Continuous Integration / Continuous Deployment) — это когда сервер обновляется сам, как только вы делаете git push. Никаких SSH вручную, никакого «подождите, я задеплою». Запушил в main — через минуту новая версия живёт в проде.

В этом гайде — как настроить именно это: автодеплой на VPS через GitHub Actions и SSH, с нуля до рабочего пайплайна.

Что происходит «под капотом»

Когда вы настраиваете CI/CD с GitHub Actions, схема выглядит так:

code
Вы делаете git push в main
        ↓
GitHub замечает push
        ↓
GitHub Actions запускает runner (виртуальную машину)
        ↓
Runner подключается к вашему серверу по SSH
        ↓
На сервере выполняются команды: git pull, npm install, перезапуск
        ↓
Новая версия приложения работает в проде

Весь этот процесс — автоматически, за 30–90 секунд, каждый раз одинаково.

Что нужно перед началом

  • Репозиторий на GitHub с вашим проектом.
  • VPS с Ubuntu 22.04+ (подходит любой: Hetzner, DigitalOcean, Timeweb, REG.RU).
  • Пользователь на сервере с правом запускать ваше приложение.
  • Базовые знания SSH (уметь подключиться к серверу).

Шаг 1. Создать SSH-ключ для GitHub Actions

GitHub Actions будет подключаться к серверу как отдельный пользователь. Для этого нужна своя пара SSH-ключей — не та, которую вы используете лично.

На своём компьютере (не на сервере!) генерируем пару ключей:

bash копировать
ssh-keygen -t ed25519 -C "github-actions-deploy" -f ~/.ssh/github_actions_deploy

Команда создаёт два файла:

  • ~/.ssh/github_actions_deployприватный ключ (уйдёт в GitHub Secrets)
  • ~/.ssh/github_actions_deploy.pubпубличный ключ (уйдёт на сервер)

Шаг 2. Добавить публичный ключ на сервер

Подключитесь к серверу и добавьте публичный ключ в список авторизованных:

bash копировать
# На сервере: добавить публичный ключ
echo "ВСТАВЬТЕ_СОДЕРЖИМОЕ_ФАЙЛА_.pub" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Содержимое файла github_actions_deploy.pub — одна длинная строка, которая начинается с ssh-ed25519. Скопируйте её целиком.

Проверьте, что подключение работает:

bash копировать
# На своём компьютере
ssh -i ~/.ssh/github_actions_deploy user@ваш-сервер-ip

Если подключились — ключи настроены правильно.

Шаг 3. Добавить секреты в GitHub

Перейдите в репозиторий на GitHub: Settings → Secrets and variables → Actions → New repository secret.

Добавьте три секрета:

Имя секрета Значение
SSH_PRIVATE_KEY Содержимое файла github_actions_deploy (приватный ключ, целиком)
SSH_HOST IP-адрес или домен вашего сервера
SSH_USER Имя пользователя на сервере (например, ubuntu или deploy)

Эти значения GitHub зашифрует и никогда не покажет в логах — даже если кто-то получит доступ к репозиторию, секреты останутся закрытыми.

Шаг 4. Создать workflow-файл

В корне репозитория создайте папку и файл:

code
.github/
└── workflows/
    └── deploy.yml

Вот базовый workflow, который работает для большинства проектов:

yaml копировать
name: Deploy to VPS

on:
  push:
    branches:
      - main  # запускается только при пуше в main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/my-project      # путь к проекту на сервере
            git pull origin main        # тянем последние изменения
            npm install --production    # ставим зависимости
            pm2 restart my-project      # перезапускаем процесс

Замените /var/www/my-project на реальный путь к проекту на сервере, а my-project в pm2 restart — на имя вашего pm2-процесса.

Закоммитьте файл и запушьте в main. GitHub Actions запустится автоматически.

Смотреть, как деплой проходит

Откройте вкладку Actions в репозитории на GitHub. Там видно каждый запуск: какой шаг выполняется сейчас, логи каждой команды, итоговый статус (✓ или ✗).

Если что-то пошло не так — красный крестик, кликаете, видите точную строку с ошибкой. Не нужно гадать.

Готовые шаблоны под разные стеки

Node.js / Express

yaml копировать
script: |
  cd /var/www/my-project
  git pull origin main
  npm install --production
  pm2 restart my-project

Next.js

yaml копировать
script: |
  cd /var/www/my-project
  git pull origin main
  npm install
  npm run build
  pm2 restart my-project

Python / Telegram-бот

yaml копировать
script: |
  cd /home/ubuntu/my-bot
  git pull origin main
  source venv/bin/activate
  pip install -r requirements.txt
  systemctl restart my-bot.service

Docker Compose

yaml копировать
script: |
  cd /var/www/my-project
  git pull origin main
  docker compose pull
  docker compose up -d --build

Деплой только при успешных тестах

Если у вас есть тесты — запускайте деплой только когда они прошли. Это гарантирует, что сломанный код не попадёт на сервер:

yaml копировать
name: Test and Deploy

on:
  push:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install
      - run: npm test          # если тесты упали — деплой не запустится

  deploy:
    needs: test                # ждёт успешного завершения job'а test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/my-project
            git pull origin main
            npm install --production
            pm2 restart my-project

Деплой с уведомлением в Telegram

Хотите получать сообщение, когда деплой завершился — успешно или с ошибкой? Добавьте шаг в конец workflow:

yaml копировать
      - name: Notify Telegram
        if: always()  # отправляет и при успехе, и при ошибке
        uses: appleboy/telegram-action@master
        with:
          to: ${{ secrets.TELEGRAM_CHAT_ID }}
          token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          message: |
            Деплой: ${{ job.status }}
            Репозиторий: ${{ github.repository }}
            Ветка: ${{ github.ref_name }}
            Коммит: ${{ github.event.head_commit.message }}

Добавьте секреты TELEGRAM_BOT_TOKEN и TELEGRAM_CHAT_ID в GitHub Secrets — и после каждого деплоя будете получать отчёт в Telegram.

Отдельный пользователь для деплоя (правильно)

Подключаться как root для деплоя — плохая практика. Правильный подход: создать отдельного пользователя deploy с минимальными правами.

bash копировать
# На сервере
sudo useradd -m -s /bin/bash deploy

# Дать права на перезапуск нужных сервисов через sudo без пароля
echo "deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart my-app" \
  | sudo tee /etc/sudoers.d/deploy-restart

# Дать права на папку проекта
sudo chown -R deploy:deploy /var/www/my-project

После этого в секрете SSH_USER указывайте deploy, а не root.

Что делать, если деплой упал

Ошибка «Permission denied (publickey)»

Проблема с SSH-ключом. Проверьте:

  • В секрете SSH_PRIVATE_KEY — содержимое приватного ключа целиком (включая строки -----BEGIN...----- и -----END...-----).
  • Публичный ключ добавлен в ~/.ssh/authorized_keys на сервере.
  • Права на файл: chmod 600 ~/.ssh/authorized_keys.

Ошибка «Host key verification failed»

GitHub Actions не знает fingerprint вашего сервера. Добавьте параметр в ssh-action:

yaml копировать
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          host_key_algorithms: +ssh-rsa  # или уберите строго если Ubuntu 22+

Или добавьте отдельный секрет SSH_HOST_KEY с fingerprint сервера (получить: ssh-keyscan ваш-сервер-ip).

Деплой прошёл, но сайт не обновился

Скорее всего pm2/systemd не перезапустился. Проверьте имя процесса:

bash копировать
pm2 list              # имена всех процессов pm2
systemctl list-units  # имена всех systemd-сервисов

Связь с другими статьями

Это базовый пайплайн — он закрывает 90% задач вайбкодера. Когда проект вырастет и вам понадобится деплой без единой секунды простоя и мгновенный откат — смотрите CI/CD для вайбкодинга: деплой без простоя и откат за 1 минуту, где разобрана Blue-Green стратегия поверх Docker.

Итог

Автодеплой через GitHub Actions — это инвестиция 30 минут один раз, которая экономит время при каждом следующем релизе. После настройки ваш рабочий цикл выглядит так:

code
написал код → git push → через минуту проект в проде

Больше не нужно помнить порядок команд, подключаться к серверу вручную или переживать, что забыли npm install. Actions делает это за вас — каждый раз одинаково.

Минимальный чеклист для первого деплоя:

  1. Сгенерировать SSH-ключ: ssh-keygen -t ed25519 -f ~/.ssh/github_actions_deploy
  2. Публичный ключ → в ~/.ssh/authorized_keys на сервере
  3. Приватный ключ, хост, пользователь → в GitHub Secrets
  4. Создать .github/workflows/deploy.yml с нужным шаблоном
  5. Запушить в main → открыть вкладку Actions → смотреть как работает
$ cd ../ ← назад к Запуск и хостинг