До основного вмісту

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 із перевіркою результату: пайплайн зупинить деплой при помилці збірки, тоді як простий хук застосує код у будь-якому разі.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці