Cách tự động deploy Next.js lên VPS bằng GitHub Actions tiết kiệm thời gian
Deploy thủ công nghe có vẻ đơn giản: SSH vào VPS, git pull, npm install, npm run build, restart app. Nhưng sau vài lần sửa bug gấp, deploy lúc nửa đêm, quên build, sai branch, thiếu biến môi trường… bạn sẽ thấy thủ công → rủi ro.
Giải pháp: tự động deploy Next.js lên VPS bằng GitHub Actions. Mỗi khi push code lên branch chính, GitHub tự kết nối VPS, kéo code mới, build, restart ứng dụng. Kết quả: nhanh hơn, ít lỗi hơn, quy trình chuyên nghiệp hơn.
Bài này hướng dẫn setup thực tế: Next.js + VPS Ubuntu + GitHub Actions + PM2 + Nginx.
Tổng quan quy trình deploy tự động
Luồng cơ bản:
1. Dev push code lên GitHub. 2. GitHub Actions chạy workflow. 3. Workflow SSH vào VPS. 4. VPS pull code mới. 5. Cài dependency nếu cần. 6. Build Next.js. 7. Restart app bằng PM2. 8. Nginx reverse proxy request tới app.
Mô hình:
GitHub push
→ GitHub Actions
→ SSH VPS
→ git pull
→ npm install
→ npm run build
→ pm2 restart
→ app onlineƯu điểm:
– Tiết kiệm thời gian: deploy vài giây/phút. – Giảm lỗi thao tác tay. – Có lịch sử deploy trong GitHub Actions. – Dễ rollback nếu dùng Git tag/commit. – Phù hợp solo dev, team nhỏ, startup.
Chuẩn bị VPS cho Next.js
Giả sử VPS dùng Ubuntu 22.04.
SSH vào server:
ssh root@YOUR_SERVER_IPCập nhật hệ thống:
apt update && apt upgrade -yCài Node.js LTS:
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejsKiểm tra:
node -v
npm -vCài Git, Nginx, PM2:
apt install -y git nginx
npm install -g pm2PM2 giúp chạy Next.js nền, tự restart khi lỗi, tự khởi động lại sau reboot.
Clone source Next.js lên VPS
Tạo thư mục app:
mkdir -p /var/www
cd /var/wwwClone repo:
git clone [email protected]:USERNAME/REPO.git my-next-app
cd my-next-appNếu repo private, VPS cần SSH key có quyền đọc repo. Cách đơn giản:
ssh-keygen -t ed25519 -C "vps-deploy"
cat ~/.ssh/id_ed25519.pubCopy public key → GitHub repo → Settings → Deploy keys → Add deploy key.
Sau đó test:
ssh -T [email protected]Nếu ok, cài package:
npm ciBuild thử:
npm run buildChạy app:
npm startMặc định Next.js chạy port 3000.
Cấu hình PM2 chạy Next.js
Trong thư mục project, tạo file:
nano ecosystem.config.jsNội dung:
module.exports = {
apps: [
{
name: "my-next-app",
script: "npm",
args: "start",
cwd: "/var/www/my-next-app",
env: {
NODE_ENV: "production",
PORT: 3000
}
}
]
};Start bằng PM2:
pm2 start ecosystem.config.js
pm2 save
pm2 startupPM2 sẽ in command. Copy chạy command đó.
Kiểm tra:
pm2 list
pm2 logs my-next-appCấu hình Nginx reverse proxy
Tạo config:
nano /etc/nginx/sites-available/my-next-appVí dụ:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Kích hoạt:
ln -s /etc/nginx/sites-available/my-next-app /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginxNếu dùng domain thật, trỏ DNS A record về IP VPS.
Cài SSL miễn phí:
apt install -y certbot python3-certbot-nginx
certbot --nginx -d example.com -d www.example.comSSL xong → app có HTTPS.
Tạo SSH key cho GitHub Actions deploy vào VPS
Không nên dùng password SSH. Dùng SSH key riêng cho deploy.
Trên máy local hoặc VPS tạo key:
ssh-keygen -t ed25519 -C "github-actions-deploy"Bạn sẽ có:
id_ed25519
id_ed25519.pubThêm public key vào VPS:
cat id_ed25519.pub >> ~/.ssh/authorized_keysNếu dùng user riêng như deploy, thêm vào:
/home/deploy/.ssh/authorized_keysPrivate key sẽ lưu vào GitHub Secrets.
Vào GitHub repo:
Settings → Secrets and variables → Actions → New repository secretThêm:
– VPS_HOST: IP VPS hoặc domain
– VPS_USER: user SSH, ví dụ root hoặc deploy
– VPS_SSH_KEY: nội dung private key
– VPS_PORT: thường là 22
Lưu ý bảo mật:
– Không commit private key. – Không in secret ra log. – Nên dùng user deploy riêng thay vì root. – Chỉ cấp quyền đúng thư mục app.
Tạo GitHub Actions workflow
Trong repo, tạo file:
.github/workflows/deploy.ymlNội dung:
name: Deploy Next.js to VPS
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
port: ${{ secrets.VPS_PORT }}
script: |
cd /var/www/my-next-app
git fetch origin
git reset --hard origin/main
npm ci
npm run build
pm2 restart my-next-app
Giải thích nhanh:
– on.push.branches.main: chỉ deploy khi push lên main.
– appleboy/ssh-action: action SSH vào VPS.
– git reset --hard origin/main: đồng bộ server đúng code trên GitHub.
– npm ci: cài dependency ổn định theo package-lock.json.
– npm run build: build production.
– pm2 restart: reload app.
Push file này lên GitHub:
git add .github/workflows/deploy.yml
git commit -m "add deploy workflow"
git push origin mainVào tab Actions để xem log deploy.
Tối ưu workflow để deploy nhanh hơn
Deploy chuẩn chạy được. Nhưng có thể tối ưu.
Chỉ cài dependency khi package thay đổi
npm ci mỗi lần deploy có thể chậm. Tuy nhiên trên VPS, đơn giản nhất vẫn nên giữ npm ci để đảm bảo sạch. Nếu app lớn, cân nhắc:
npm install --omit=devNhưng Next.js cần devDependencies khi build, nên cần cẩn thận.
Dùng pnpm
Nếu dùng pnpm, tốc độ thường nhanh hơn:
npm install -g pnpm
pnpm install --frozen-lockfile
pnpm build
pm2 restart my-next-appWorkflow script:
script: |
cd /var/www/my-next-app
git fetch origin
git reset --hard origin/main
pnpm install --frozen-lockfile
pnpm build
pm2 restart my-next-appBuild trên GitHub hay VPS?
Có 2 cách:
Build trên VPS:– Dễ setup. – Không cần upload artifact. – VPS yếu → build chậm.
Build trên GitHub Actions:– Nhanh hơn nếu VPS nhỏ.
– Phức tạp hơn.
– Cần copy .next, public, package.json, lockfile lên server.
Với team nhỏ, build trên VPS → đủ tốt.
Xử lý biến môi trường
Next.js thường cần .env.production.
Không commit file .env lên GitHub. Tạo trực tiếp trên VPS:
nano /var/www/my-next-app/.env.productionVí dụ:
DATABASE_URL="..."
NEXTAUTH_SECRET="..."
NEXT_PUBLIC_API_URL="https://example.com"Sau khi sửa env:
npm run build
pm2 restart my-next-appLưu ý:
– Biến NEXT_PUBLIC_* sẽ được nhúng vào client bundle.
– Secret như DB password, token → không dùng prefix NEXT_PUBLIC_.
– Đổi env production → cần build lại.
Rollback khi deploy lỗi
Tự động deploy không có nghĩa bỏ qua rollback.
Cách nhanh:
cd /var/www/my-next-app
git log --oneline
git reset --hard COMMIT_ID
npm ci
npm run build
pm2 restart my-next-appCó thể thêm tag release:
git tag v1.0.0
git push origin v1.0.0Team lớn hơn nên dùng strategy:
– Deploy theo tag. – Giữ thư mục release. – Symlink current. – Health check trước khi switch traffic.
Nhưng với VPS nhỏ, rollback theo commit → thực tế, nhanh.
Lỗi thường gặp
Permission denied khi GitHub Actions SSH
Nguyên nhân:
– Sai private key.
– Public key chưa nằm trong authorized_keys.
– Sai user.
– Sai port SSH.
Kiểm tra:
ssh -i id_ed25519 user@server_ipGit pull yêu cầu password
Repo private nhưng VPS chưa có deploy key GitHub.
Fix:
ssh -T [email protected]Nếu lỗi → thêm public key VPS vào GitHub Deploy keys.
Build thành công nhưng web không đổi
Có thể PM2 chưa restart đúng app.
Kiểm tra:
pm2 list
pm2 restart my-next-app
pm2 logs my-next-appNginx 502 Bad Gateway
App Next.js chưa chạy hoặc sai port.
Kiểm tra:
curl http://127.0.0.1:3000
pm2 logs
nginx -tKết luận
Tự động deploy Next.js lên VPS bằng GitHub Actions giúp biến deploy từ thao tác thủ công dễ lỗi thành quy trình rõ ràng:
push code → GitHub Actions → VPS tự build/restart → website cập nhậtSetup ban đầu mất khoảng 30–60 phút, nhưng tiết kiệm rất nhiều thời gian về sau. Với một VPS nhỏ, PM2, Nginx, SSL, GitHub Actions, bạn đã có pipeline production đủ dùng cho blog, landing page, SaaS nhỏ, dashboard nội bộ.
Khuyến nghị thực tế:
– Dùng SSH key, không dùng password. – Lưu secret trong GitHub Secrets. – Dùng PM2 quản lý process. – Luôn có cách rollback. – Theo dõi log sau mỗi lần deploy.
Làm đúng một lần → deploy nhẹ đầu lâu dài.
Bình luận (0)
Chưa có bình luận. Hãy là người đầu tiên!