Git & Tự Động Deploy Trên VPS - Git Workflow Cho Team, Webhook Auto Deploy 2026
Push code lên GitHub → VPS tự động pull code mới về → website tự cập nhật. Không cần SSH vào server mỗi lần deploy. Đây là Git workflow chuẩn cho mọi developer 2026. Bài viết hướng dẫn từ cài Git, tạo SSH key, đến setup webhook auto deploy hoàn chỉnh trên VPS TrumVPS.
1. Cài Git Trên VPS
sudo apt update && sudo apt install git -y
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
2. Clone Repository Về VPS
cd /var/www
git clone https://github.com/your-username/your-repo.git yourdomain.com
# Hoặc nếu là private repo:
git clone git@github.com:your-username/your-repo.git yourdomain.com
3. Tạo SSH Key Cho Deploy Tự Động
ssh-keygen -t ed25519 -C "deploy@yourdomain.com" -f ~/.ssh/deploy_key
cat ~/.ssh/deploy_key.pub # Copy key này vào GitHub → Settings → Deploy Keys
4. Script Deploy Tự Động
nano /home/ubuntu/deploy.sh
#!/bin/bash
cd /var/www/yourdomain.com
git pull origin main
# Laravel:
# composer install --no-dev --optimize-autoloader
# php artisan migrate --force
# php artisan config:cache
echo "$(date): Deployed" >> /var/log/deploy.log
chmod +x /home/ubuntu/deploy.sh
5. Webhook Tự Động Deploy Khi Push GitHub
Dùng webhook.php đơn giản để GitHub gọi khi có push:
nano /var/www/yourdomain.com/webhook.php
<?php
$secret = 'YOUR_WEBHOOK_SECRET';
$sig = 'sha1=' . hash_hmac('sha1', file_get_contents('php://input'), $secret);
if (hash_equals($sig, $_SERVER['HTTP_X_HUB_SIGNATURE'] ?? '')) {
shell_exec('/home/ubuntu/deploy.sh > /dev/null 2>&1 &');
echo 'OK';
} else {
http_response_code(403);
echo 'Invalid';
}
Vào GitHub repo → Settings → Webhooks → Add: https://yourdomain.com/webhook.php, Content type: application/json, Secret: giống secret trong code.
6. Git Workflow Cho Team (Branch Strategy)
- main: Production — chỉ merge từ develop qua Pull Request
- develop: Staging — code mới test ở đây
- feature/*: Mỗi tính năng một branch
- hotfix/*: Sửa lỗi khẩn cấp trên production
Mỗi developer làm việc trên branch feature riêng → tạo Pull Request → review → merge vào develop → test → merge vào main → auto deploy lên VPS production. Chuyên nghiệp, không đụng hàng, có thể rollback bất cứ lúc nào.
7. CI/CD Pipeline với GitHub Actions
GitHub Actions là cách chuyên nghiệp nhất để tự động test + deploy. Tạo file .github/workflows/deploy.yml trong repository:
name: Deploy to VPS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
script: |
cd /var/www/yourdomain.com
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
sudo systemctl reload php8.2-fpm
Ưu điểm của GitHub Actions: Không cần webhook.php, không cần mở port public cho webhook. Bảo mật hơn vì dùng SSH key lưu trong GitHub Secrets. Có thể thêm bước test (PHPUnit, Laravel Pest) trước khi deploy. Nếu test fail → deploy bị hủy tự động.
8. CI/CD với GitLab CI
Nếu dùng GitLab (tự host hoặc cloud), tạo .gitlab-ci.yml:
deploy:
stage: deploy
only:
- main
before_script:
- 'which ssh-agent || (apt-get update -y && apt-get install openssh-client -y)'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
- ssh-keyscan $VPS_HOST >> ~/.ssh/known_hosts
script:
- ssh $VPS_USER@$VPS_HOST "cd /var/www/app && git pull origin main && sudo systemctl reload php8.2-fpm"
GitLab CI có ưu thế về private registry (Container Registry), merge request review tự động, và khả năng tự host GitLab Runner trên chính VPS.
9. Triển Khai Deploy Với Docker
Thay vì deploy code trực tiếp, bạn có thể đóng gói ứng dụng vào Docker image và deploy container:
# Dockerfile
FROM php:8.2-fpm
WORKDIR /var/www/app
COPY . .
RUN composer install --no-dev --optimize-autoloader
EXPOSE 9000
CMD ["php-fpm"]
# docker-compose.yml
version: '3.8'
services:
app:
build: .
container_name: myapp
restart: always
volumes:
- ./storage:/var/www/app/storage
networks:
- app-network
nginx:
image: nginx:alpine
container_name: myapp-nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
networks:
app-network:
driver: bridge
Script deploy với Docker:
#!/bin/bash
cd /var/www/app
git pull origin main
docker compose down
docker compose up -d --build
docker image prune -f # Dọn dẹp image cũ
echo "$(date): Docker Deployed" >> /var/log/deploy.log
10. Zero-Downtime Deploy
Deploy thông thường có thể gây downtime 1-5 giây khi restart service. Với zero-downtime deploy:
Strategy 1: Blue-Green Deployment
- Chạy 2 bản production song song: "blue" (live) và "green" (standby)
- Deploy lên green → test → switch Nginx upstream sang green → tắt blue
- Rollback dễ dàng: switch lại blue
Strategy 2: Symlink Swap (đơn giản nhất)
#!/bin/bash
# Zero-downtime deploy bằng symlink
RELEASE_DIR="/var/www/releases/$(date +%Y%m%d%H%M%S)"
CURRENT_DIR="/var/www/current"
# Clone vào thư mục mới
git clone git@github.com:user/repo.git $RELEASE_DIR
cd $RELEASE_DIR
composer install --no-dev --optimize-autoloader
# Atomic symlink swap (không downtime)
ln -sfn $RELEASE_DIR $CURRENT_DIR
sudo systemctl reload php8.2-fpm
# Keep last 5 releases, delete older
ls -dt /var/www/releases/* | tail -n +6 | xargs rm -rf
Symlink swap là atomic operation — Nginx chuyển sang code mới ngay lập tức không có khoảng trống.
11. Rollback Nhanh Khi Có Sự Cố
Dù test kỹ đến đâu, production vẫn có thể gặp lỗi. Chuẩn bị sẵn script rollback:
#!/bin/bash
# Rollback về commit trước đó
cd /var/www/yourdomain.com
git log --oneline -5 # Xem lịch sử
git revert HEAD --no-edit # Hoặc: git reset --hard COMMIT_HASH
git push origin main # Đẩy revert lên GitHub (trigger deploy lại)
# Hoặc deploy lại commit cũ:
# git checkout COMMIT_HASH
echo "$(date): ROLLBACK executed" >> /var/log/deploy.log
Best practice: Luôn giữ lại 3-5 bản release gần nhất. Test kỹ trên staging trước khi deploy production. Có monitoring (UptimeRobot, Grafana) để phát hiện lỗi sớm.
12. Troubleshooting Các Lỗi Deploy Thường Gặp
- Webhook không chạy: Kiểm tra GitHub Settings → Webhooks → Recent Deliveries để xem response code. Lỗi 403 → secret sai. Lỗi 500 → lỗi PHP trong webhook.php
- Permission denied (publickey): SSH key chưa được thêm vào GitHub Deploy Keys hoặc sai path. Kiểm tra:
ssh -T git@github.com - git pull bị conflict: Có người sửa file trực tiếp trên VPS. Giải pháp:
git fetch origin && git reset --hard origin/main(cẩn thận — mất thay đổi local) - Website vẫn hiển thị code cũ: Clear cache:
php artisan cache:clear(Laravel) hoặc restart PHP-FPM:sudo systemctl reload php8.2-fpm - Composer memory limit: Trên VPS RAM thấp (1GB):
COMPOSER_MEMORY_LIMIT=-1 composer installhoặc dùng swap
Câu Hỏi Thường Gặp (FAQ)
Có cần VPS mạnh để chạy CI/CD không?
Không. CI/CD chạy trên GitHub Actions/GitLab CI (cloud) nên không tốn tài nguyên VPS. VPS chỉ nhận lệnh deploy qua SSH — tốn chưa đến 1% CPU. VPS TrumVPS 40K chạy deploy tự động thoải mái.
Nên dùng webhook hay GitHub Actions?
GitHub Actions nếu bạn dùng GitHub và muốn chuyên nghiệp (có test, notification, log). Webhook PHP đơn giản hơn, nhẹ hơn, phù hợp project nhỏ hoặc GitLab/Gitea tự host.
Làm sao deploy nhiều website trên cùng VPS?
Tạo nhiều webhook (mỗi repo một webhook) hoặc dùng GitHub Actions matrix deploy. Mỗi website có deploy script riêng, trỏ đến thư mục riêng trong /var/www/.
Deploy tự động có rủi ro bảo mật không?
Có nếu setup sai. Luôn: (1) Dùng secret token mạnh (32+ ký tự), (2) Giới hạn IP webhook nếu có thể, (3) Không log secret ra file, (4) Dùng SSH key riêng cho deploy (không trùng key cá nhân), (5) Hạn chế quyền của user deploy.