Triển khai Next.js trên VPS Ubuntu: Quy trình chuẩn, dễ áp dụng cho dự án thật
Triển khai Next.js lên VPS Ubuntu nghe đơn giản: git pull, npm run build, npm start. Nhưng dự án thật hiếm khi chỉ vậy. Bạn cần Node đúng phiên bản, process manager, reverse proxy, SSL, env, log, deploy lại không downtime, rollback khi lỗi.
Bài viết này đưa ra quy trình thực chiến: đủ chuẩn cho production, dễ áp dụng cho team nhỏ, startup, freelance project, SaaS MVP.
1. Kiến trúc triển khai đề xuất
Mô hình phổ biến:
User → Domain → Nginx → Next.js app → DB/APITrong đó:
– Ubuntu VPS: server chính. – Nginx: reverse proxy, xử lý domain, SSL, gzip, cache cơ bản. – Next.js app: chạy qua Node.js. – PM2: giữ app sống, tự restart khi crash. – Git: lấy source code. – Certbot: cấp SSL miễn phí từ Let’s Encrypt.
Ưu điểm:
– Dễ cài. – Dễ debug. – Không phụ thuộc nền tảng cloud đắt tiền. – Phù hợp dự án thật: landing, dashboard, app nội bộ, e-commerce nhỏ, SaaS MVP.
2. Chuẩn bị VPS Ubuntu
Nên chọn:
– Ubuntu 22.04 LTS hoặc 24.04 LTS. – RAM tối thiểu 1GB; khuyến nghị 2GB+. – CPU 1 core trở lên. – SSD. – Quyền SSH root hoặc user sudo.
Đăng nhập:
ssh root@YOUR_SERVER_IPCập nhật hệ thống:
apt update && apt upgrade -yCài công cụ cơ bản:
apt install -y curl git ufw nginxTạo user deploy, tránh chạy app bằng root:
adduser deploy
usermod -aG sudo deployChuyển sang user:
su - deploy3. Cài Node.js đúng cách
Không nên dùng Node.js mặc định từ apt vì thường cũ. Dùng nvm linh hoạt hơn.
Cài nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bashReload shell:
source ~/.bashrcCài Node LTS:
nvm install --lts
nvm use --lts
node -v
npm -vNếu dự án dùng phiên bản cụ thể, tạo file .nvmrc:
20Sau đó:
nvm install
nvm useĐiểm quan trọng: local, CI, VPS nên dùng cùng version Node → giảm lỗi build.
4. Clone source code lên server
Tạo thư mục app:
mkdir -p ~/apps
cd ~/appsClone repo:
git clone [email protected]:your-org/your-next-app.git
cd your-next-appNếu dùng GitHub private repo, cần cấu hình SSH key:
ssh-keygen -t ed25519 -C "deploy@server"
cat ~/.ssh/id_ed25519.pubCopy public key vào GitHub → Deploy keys hoặc SSH keys.
Test:
ssh -T [email protected]5. Cấu hình biến môi trường
Next.js thường dùng .env.production.
Ví dụ:
nano .env.productionNội dung mẫu:
NODE_ENV=production
NEXT_PUBLIC_SITE_URL=https://example.com
DATABASE_URL=postgresql://user:password@host:5432/db
NEXTAUTH_SECRET=your-secret
NEXTAUTH_URL=https://example.comLưu ý:
– Biến bắt đầu bằng NEXT_PUBLIC_ sẽ lộ ra client.
– Secret, token, DB URL không được dùng prefix này.
– Không commit .env.production lên Git.
Nên có file mẫu:
.env.exampleGiúp người khác biết cần cấu hình gì.
6. Cài dependency, build Next.js
Cài package:
npm installNếu dự án dùng lockfile, nên dùng:
npm ciBuild:
npm run buildChạy thử:
npm startMặc định Next.js chạy port 3000.
Kiểm tra:
curl http://localhost:3000Nếu có HTML trả về → app ổn.
7. Chạy app bằng PM2
Cài PM2 global:
npm install -g pm2Start app:
pm2 start npm --name "next-app" -- startKiểm tra:
pm2 status
pm2 logs next-appLưu process list:
pm2 saveTự chạy lại sau reboot:
pm2 startupPM2 sẽ in ra một command. Copy command đó, chạy lại.
Ví dụ:
sudo env PATH=$PATH:/home/deploy/.nvm/versions/node/v20.x.x/bin pm2 startup systemd -u deploy --hp /home/deploySau đó:
pm2 saveTừ giờ server reboot → app tự bật lại.
8. Cấu hình Nginx reverse proxy
Tạo config:
sudo nano /etc/nginx/sites-available/next-appNội dung:
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
Enable site:
sudo ln -s /etc/nginx/sites-available/next-app /etc/nginx/sites-enabled/Test config:
sudo nginx -tReload:
sudo systemctl reload nginxTrỏ DNS:
A example.com YOUR_SERVER_IP
A www.example.com YOUR_SERVER_IPSau DNS cập nhật, mở:
http://example.com9. Cài SSL HTTPS bằng Certbot
Cài Certbot:
sudo apt install -y certbot python3-certbot-nginxCấp SSL:
sudo certbot --nginx -d example.com -d www.example.comChọn redirect HTTP → HTTPS nếu được hỏi.
Test gia hạn:
sudo certbot renew --dry-runSau bước này:
https://example.com → Nginx → localhost:3000Production app nên luôn dùng HTTPS, nhất là khi có auth, cookie, payment, admin dashboard.
10. Firewall cơ bản
Bật UFW:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw statusKhông mở port 3000 ra internet nếu không cần. Next.js chỉ nên nghe local qua Nginx.
Nếu app đang expose public port:
example.com:3000→ không nên. Dùng reverse proxy thay thế.
11. Quy trình deploy mỗi lần cập nhật code
Một flow đơn giản:
cd ~/apps/your-next-app
git pull origin main
npm ci
npm run build
pm2 restart next-appCó thể tạo script:
nano deploy.shNội dung:
#!/bin/bash
set -e
cd ~/apps/your-next-app
git pull origin main
npm ci
npm run build
pm2 restart next-app
pm2 save
Cấp quyền:
chmod +x deploy.shChạy:
./deploy.shset -e giúp script dừng nếu có lỗi. Tránh restart app khi build fail.
12. Tối ưu cho dự án thật
Dùng standalone output
Trong next.config.js:
module.exports = {
output: 'standalone',
}Build xong, Next.js tạo bundle gọn hơn. Phù hợp deploy production, Docker, CI/CD.
Bật cache static qua Nginx
Có thể cache file _next/static:
location /_next/static/ {
proxy_pass http://localhost:3000;
expires 1y;
add_header Cache-Control "public, immutable";
}Static assets có hash → cache dài an toàn.
Log rõ ràng
Xem log app:
pm2 logs next-appLog Nginx:
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.logLog là nơi đầu tiên cần xem khi:
– Trang trắng. – 502 Bad Gateway. – Build lỗi. – Auth redirect sai. – API trả 500.
Kiểm soát memory
VPS nhỏ dễ hết RAM khi build. Kiểm tra:
free -h
htopNếu RAM 1GB, nên tạo swap:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileLưu vĩnh viễn:
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab13. Lỗi thường gặp
502 Bad Gateway
Nguyên nhân thường gặp:
– App chưa chạy. – Sai port. – PM2 crash. – Nginx proxy sai.
Kiểm tra:
pm2 status
pm2 logs next-app
curl http://localhost:3000
sudo nginx -tEnvironment variable không nhận
Sau khi sửa .env.production, cần build lại:
npm run build
pm2 restart next-appBiến NEXT_PUBLIC_ được bake vào bundle lúc build.
Domain redirect sai khi dùng NextAuth
Kiểm tra:
NEXTAUTH_URL=https://example.comSai URL → callback lỗi, login loop, cookie sai domain.
Build trên server quá chậm
Giải pháp:
– Tăng RAM/swap. – Build ở CI rồi upload artifact. – Dùng Docker image build sẵn. – Dùng server mạnh hơn.
14. Checklist production nhanh
Trước khi bàn giao:
– Domain trỏ đúng IP.
– HTTPS hoạt động.
– Nginx reverse proxy ổn.
– PM2 auto restart sau reboot.
– .env.production đầy đủ.
– Port 3000 không public.
– Log kiểm tra được.
– Deploy script có set -e.
– Backup DB nếu có dữ liệu thật.
– Monitoring tối thiểu: uptime check.
Có thể dùng UptimeRobot, Better Stack, Grafana Cloud hoặc cron đơn giản để ping endpoint health.
Kết luận
Triển khai Next.js trên VPS Ubuntu không khó nếu đi đúng quy trình: Node LTS → build production → PM2 → Nginx → SSL → firewall → deploy script. Đây là stack gọn, rẻ, dễ kiểm soát, đủ tốt cho nhiều dự án thật.
Khi app lớn hơn, bạn có thể nâng cấp dần: CI/CD, Docker, blue-green deploy, load balancer, object storage, managed database. Nhưng nền tảng vẫn vậy: server rõ ràng, config rõ ràng, log rõ ràng, rollback được.
Bắt đầu đơn giản. Chuẩn hóa sớm. Production sẽ bớt đau.
Bình luận (0)
Chưa có bình luận. Hãy là người đầu tiên!