Checklist hoàn chỉnh trước khi đưa website Next.js chạy trên VPS vào production
Đưa một website Next.js lên VPS production không chỉ là npm run build rồi chạy pm2 start. Production = môi trường thật, traffic thật, bot thật, lỗi thật, tiền thật. Một cấu hình thiếu HTTPS, env lộ, process chết không tự restart, log phình đầy disk, DB không backup → website có thể sập bất cứ lúc nào.
Checklist dưới đây giúp bạn rà soát toàn bộ trước khi “go live”: code, build, server, bảo mật, reverse proxy, SSL, monitoring, backup, performance.
1. Kiểm tra code trước khi build
Dependency → sạch
Chạy:
npm audit
npm outdatedFix lỗi bảo mật nghiêm trọng:
npm audit fixKhông update mù major version trước production. Test kỹ nếu nâng cấp framework, auth, ORM, payment SDK.
Lint/type → không lỗi
npm run lint
npm run type-checkNếu dùng TypeScript, tránh any bừa bãi ở phần auth, API, payment, DB. Lỗi type nhỏ → bug runtime lớn.
Env → đủ, đúng, không lộ
Kiểm tra .env.production:
NODE_ENV=production
NEXT_PUBLIC_SITE_URL=https://example.com
DATABASE_URL=...
AUTH_SECRET=...Nguyên tắc:
– Không commit .env
– Biến client chỉ dùng prefix NEXT_PUBLIC_
– Secret/API key chỉ ở server
– AUTH_SECRET, JWT_SECRET, webhook secret phải mạnh
– URL production khác staging/dev
Kiểm tra .gitignore:
.env
.env.*
!.env.example2. Build Next.js chuẩn production
Build local trước
npm run buildNếu lỗi ở VPS mới phát hiện → deploy chậm, downtime cao. Build local/CI trước.
Kiểm tra mode chạy
Next.js production thường chạy:
npm run startHoặc:
next startKhông dùng:
npm run devdev → chậm, memory cao, debug info, không phù hợp public internet.
Output mode → rõ
Nếu dùng Docker hoặc deploy tối ưu, cân nhắc:
// next.config.js
module.exports = {
output: 'standalone',
}Sau build, app nhẹ hơn, deploy dễ hơn. Nhưng phải test assets/static đúng.
3. VPS baseline: user, firewall, update
Không chạy bằng root
Tạo user deploy:
adduser deploy
usermod -aG sudo deploySSH bằng key, tắt password login nếu có thể.
Update OS
sudo apt update && sudo apt upgrade -yReboot nếu kernel update:
sudo rebootFirewall → chỉ mở cần thiết
Với UFW:
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw statusKhông expose port app như 3000 ra public nếu đã dùng Nginx. App chỉ nên listen 127.0.0.1:3000.
4. Node.js, package manager, process manager
Node version → khớp
Kiểm tra local:
node -vTrên VPS nên dùng cùng major version. Dùng nvm hoặc NodeSource. Ví dụ Node 20 LTS.
node -v
npm -vInstall dependency production
Nếu build trên VPS:
npm ci
npm run buildnpm ci → sạch, đúng lockfile. Tốt hơn npm install trong production.
PM2 → app sống lại khi crash
Cài PM2:
npm install -g pm2Start app:
pm2 start npm --name "next-app" -- start
pm2 save
pm2 startupKiểm tra:
pm2 status
pm2 logs next-appTối thiểu cần:
– auto restart – start on boot – log xem được – memory không tăng bất thường
Có thể set memory restart:
pm2 start npm --name "next-app" -- start --max-memory-restart 500M5. Nginx reverse proxy
Vì sao cần Nginx?
Nginx → nhận request public, terminate SSL, proxy về Next.js, serve static/cache tốt hơn, chặn request xấu cơ bản.
File config mẫu:
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 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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Enable:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxApp binding → local only
Chạy Next ở localhost:
HOSTNAME=127.0.0.1 PORT=3000 npm run startNếu bind 0.0.0.0, đảm bảo firewall không mở port 3000.
6. SSL/HTTPS bắt buộc
Dùng Certbot:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.comTest renew:
sudo certbot renew --dry-runHTTPS không chỉ để “đẹp”. Nó ảnh hưởng:
– login/session
– cookie Secure
– SEO
– browser trust
– payment/webhook
– API security
Bật redirect HTTP → HTTPS. Certbot thường tự cấu hình.
7. Security headers, cookie, CORS
Header bảo mật
Trong next.config.js:
const securityHeaders = [
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
]
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: securityHeaders,
},
]
},
}
Cân nhắc CSP nếu app ổn định. CSP sai → vỡ script, analytics, payment widget.
Cookie/session
Production cookie nên có:
– httpOnly
– secure
– sameSite
– path/domain đúng
– maxAge hợp lý
Nếu dùng NextAuth/Auth.js:
– NEXTAUTH_URL/AUTH_URL đúng domain HTTPS
– AUTH_SECRET mạnh
– callback URL trong Google/GitHub/Facebook khớp production
CORS
Không dùng:
origin: '*'với credential. Chỉ allow domain cần thiết.
8. Database, migration, backup
Migration → có kế hoạch
Trước deploy:
npx prisma migrate deployKhông dùng migrate dev trên production.
Checklist DB:
– connection string production đúng – user DB không có quyền quá rộng nếu không cần – index đủ cho query chính – migration đã test staging – rollback plan có
Backup → không optional
Tối thiểu:
– backup DB hằng ngày – giữ nhiều phiên bản – test restore định kỳ – backup ngoài VPS
Ví dụ PostgreSQL:
pg_dump "$DATABASE_URL" > backup.sqlBackup chưa từng restore = chưa chắc dùng được.
9. Logging, monitoring, alert
Log app
PM2 logs:
pm2 logs next-appCấu hình log rotate:
pm2 install pm2-logrotateNếu không rotate → disk đầy → app chết.
Monitor tài nguyên
Kiểm tra:
htop
df -h
free -mTheo dõi:
– CPU spike – RAM leak – disk usage – response time – error rate – 5xx từ Nginx – DB connection count
Dùng Uptime Kuma, Better Stack, Grafana, Sentry tùy quy mô.
Error tracking
Cài Sentry hoặc tương đương. Production không thể dựa vào user báo lỗi qua chat.
10. Performance: cache, image, bundle
Image optimization
Nếu dùng next/image, kiểm tra domain:
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'cdn.example.com',
},
],
},
}Ảnh lớn → LCP xấu. Dùng CDN/object storage nếu nhiều media.
Bundle size
Phân tích:
npm install @next/bundle-analyzerLoại bỏ lib nặng ở client. Chart/editor/date lib thường làm bundle phình.
Cache headers
Static assets của Next thường có hash → cache dài được. Với API/data dynamic, set cache rõ. Không cache nhầm dữ liệu user.
11. Deploy workflow an toàn
Không sửa trực tiếp trên VPS
Luồng tốt:
1. Code → Git 2. CI test/build 3. Deploy VPS 4. Run migration 5. Restart app 6. Health check 7. Rollback nếu fail
Deploy tay vẫn được, nhưng phải script hóa:
git pull
npm ci
npm run build
pm2 restart next-appZero/low downtime
PM2 reload:
pm2 reload next-appVới app nhỏ, restart vài giây có thể chấp nhận. Với app có traffic thật, cần health check, blue-green, Docker, hoặc load balancer.
12. Kiểm thử cuối trước khi mở traffic
Checklist nhanh:
– Domain trỏ đúng IP
– HTTPS xanh
– HTTP redirect HTTPS
– www/non-www thống nhất
– login/logout OK
– form gửi được
– upload OK
– payment/webhook OK
– email production gửi được
– sitemap/robots đúng
– metadata/social preview đúng
– 404/500 page ổn
– mobile responsive
– Lighthouse đủ tốt
– backup chạy
– monitoring báo được
– reboot VPS app tự chạy lại
Test reboot thật:
sudo rebootSau đó kiểm tra:
pm2 status
sudo systemctl status nginxKết luận
Production không phải một lệnh deploy. Production là hệ thống: code ổn, env đúng, server khóa, HTTPS bật, process tự phục hồi, DB có backup, log có kiểm soát, monitoring có cảnh báo.
Nếu website Next.js của bạn chạy trên VPS, hãy xem checklist này như “cửa kiểm soát cuối”. Làm đủ ngay từ đầu → ít sự cố, dễ debug, dễ mở rộng. Bỏ qua vài mục nhỏ → có thể trả giá bằng downtime, mất dữ liệu, hoặc lộ secret.
Trước khi public link cho khách hàng/người dùng: build sạch, deploy có script, reboot test, backup test, monitoring bật. Khi đó, bạn không chỉ “đưa website lên mạng” — bạn đang vận hành một sản phẩm production đúng nghĩa.
Bình luận (0)
Chưa có bình luận. Hãy là người đầu tiên!