К основному содержимому

Git деплой на хостинг и VPS: автоматизация через hooks

Хостинг и cPanel · 15.03.2026 · 6 мин чтения
Иллюстрация к статье «Git деплой на хостинг и VPS: автоматизация через hooks»

Вместо ручного FTP при каждом изменении — настройте git push для автоматического деплоя. Занимает 15 минут, экономит часы работы.

Деплой на VPS через Git bare repo

# На VPS: создать bare репозиторий
mkdir -p /var/repo/mysite.git
cd /var/repo/mysite.git
git init --bare

# Создать хук post-receive
nano hooks/post-receive
#!/bin/bash
GIT_WORK_TREE=/var/www/mysite git checkout -f main
echo "Deployed to /var/www/mysite"
chmod +x hooks/post-receive
# На локальном компьютере:
git remote add production user@server-ip:/var/repo/mysite.git
git push production main

Деплой на cPanel хостинг через Git

cPanel → Файлы → Git™ Version Control:

  1. Create → укажите путь к репозиторию (public_html)
  2. Укажите URL GitHub/GitLab репозитория
  3. Нажмите Update from Remote для ручного деплоя

GitHub Actions: полный автодеплой

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/mysite
            git pull origin main
            composer install --no-dev
            php artisan migrate --force
✅ Храните SSH-ключ, IP и пароли в GitHub Secrets (Settings → Secrets → Actions). Никогда не коммитьте .env файлы.

Частые ошибки при Git-деплое

Ниже — сообщения, с которыми реально сталкиваются при первой настройке bare-репозитория и хуков, и что за ними стоит.

Permission denied (publickey).
fatal: Could not read from remote repository.

bash: hooks/post-receive: Permission denied

remote: error: hook declined to update refs/heads/main
error: failed to push some refs to 'server-ip:/var/repo/mysite.git'

fatal: 'production' does not appear to be a git repository
СообщениеПричинаРешение
Permission denied (publickey)SSH-ключ клиента не добавлен на сервере или используется не тот ключПроверить ssh -T user@server-ip -i путь_к_ключу, добавить публичный ключ в ~/.ssh/authorized_keys
hooks/post-receive: Permission deniedХук не помечен исполняемым файлом — пропущен chmod +xВыполнить chmod +x hooks/post-receive и проверить первую строку файла (#!/bin/bash)
hook declined to update refs / failed to push some refsСам хук завершился с ненулевым кодом — например, git checkout -f упал из-за прав на рабочей директорииЗапустить хук вручную: bash hooks/post-receive, исправить владельца и права на /var/www/mysite
fatal: 'production' does not appear to be a git repositoryНеверный URL remote или опечатка в пути к bare-репозиториюСверить git remote -v с реальным путём на сервере — каталог должен заканчиваться на .git

Сравнение способов деплоя

СпособНужен SSHСкорость деплояКогда применять
Bare repo + post-receive hookДа, ключевой доступ обязателенМгновенно после git pushVPS с полным доступом, свой пайплайн без сторонних сервисов
cPanel Git Version ControlНе обязателен, работает через веб-интерфейсВручную по кнопке Update from RemoteShared-хостинг, разработчик без SSH-доступа
GitHub ActionsДа, для шага подключения по SSH к серверуАвтоматически при push в main, 1–3 минутыКоманда, нужны тесты и сборка перед выкладкой

Когда Git-деплой не подходит

  • Сайт хранит пользовательские файлы (медиатеку, загрузки) прямо в рабочей директории репозитория — git checkout -f при деплое может задеть их без аккуратного .gitignore
  • Нужен zero-downtime деплой с мгновенным откатом — простой checkout -f не даёт атомарной подмены версии, для этого нужна схема с релизами и симлинком на текущий каталог
  • На хостинге нет ни SSH, ни раздела Git Version Control в панели — тогда остаётся только обычная загрузка по FTP
  • В репозитории регулярно меняются тяжёлые бинарные файлы (видео, дампы БД) — Git плохо справляется с ними без Git LFS, а LFS доступен не на каждом сервере

Как проверить, что деплой прошёл успешно

# На сервере: сравнить текущий коммит с тем, что запушили локально
cd /var/repo/mysite.git && git log -1 --oneline

# В рабочей директории: время изменения файлов должно быть свежим
stat -c '%y' /var/www/mysite/index.php

# Сайт отвечает без ошибки 500
curl -I https://yourdomain.com/
  1. Сравните хеш коммита в bare-репозитории с тем, что было запушено локально — они обязаны совпадать
  2. Проверьте время изменения файлов в рабочей директории через stat — оно должно обновиться в момент деплоя
  3. Откройте сайт через curl -I: если хук отработал, но composer install упал, файлы обновятся, а сайт всё равно сломается
  4. В GitHub Actions проверьте вкладку Actions — последний workflow run должен быть зелёным, даже если git push прошёл без ошибок

Настройку доступа по ключам вместо пароля для самого сервера разбирает статья SSH-доступ на shared-хостинге, а автоматизацию побочных задач после деплоя — материал про cron-задачи в cPanel.

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

Как настроить деплой без простоя и с быстрым откатом, если git checkout -f не атомарен?

Простой checkout -f подменяет файлы прямо в рабочей директории, и сайт на секунду видит неполный набор файлов. Для надёжности код разворачивают в отдельную папку для каждого релиза и держат симлинк на текущую версию: хук собирает новый релиз, проверяет его и переключает симлинк одной операцией. Откат — просто симлинк на предыдущую папку.

Что произойдёт с файлами, изменёнными вручную прямо на сервере, при следующем git push?

Хук выполняет git checkout -f, а это значит принудительную перезапись отслеживаемых файлов версией из коммита — любая ручная правка конфига или кода прямо на сервере исчезнет без предупреждения при следующем деплое. Пользовательские загрузки и медиатеку это не трогает, только если они не отслеживаются репозиторием и описаны в .gitignore.

Как откатиться к предыдущей версии сайта, если новый деплой сломал работу?

На VPS с bare-репозиторием достаточно переключиться на нужный коммит в рабочей директории командой git checkout и заново выполнить шаги хука вручную — composer install и миграции при необходимости. В cPanel проще указать в Git Version Control предыдущий коммит и снова нажать обновление из удалённого репозитория. Для мгновенного отката полезна схема релизов с симлинком.

Стоит ли переходить на GitHub Actions, если уже настроен git push через bare-репозиторий?

Bare-репозиторий с хуком быстрее и проще для одиночного разработчика — деплой происходит сразу после push без ожидания внешнего сервиса. GitHub Actions оправдан, когда перед выкладкой нужны сборка, тесты или шаг composer install с проверкой результата: пайплайн остановит деплой при ошибке сборки, тогда как простой хук применит код в любом случае.

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке