Cách deploy Next.js lên VPS Ubuntu
Hướng dẫn build và chạy ứng dụng Next.js production bằng PM2, Nginx, domain và HTTPS trên VPS Ubuntu theo từng bước kiểm tra được.
Mục lục bài viết
VPS & Hosting cho dự án của bạn
Khám phá các gói máy chủ và lưu trữ phù hợp từ website cá nhân đến ứng dụng production.
Một bản deploy tốt không dừng ở việc ứng dụng “chạy được”. Bạn cần biết tiến trình nào đang phục vụ ứng dụng, traffic đi qua đâu và cách kiểm tra từng lớp khi có sự cố.
Kiến trúc triển khai
Người dùng → Nginx → Next.js (PM2)
Nginx nhận request từ Internet và chuyển tiếp vào tiến trình Next.js đang chạy cục bộ. PM2 giữ tiến trình sống và hỗ trợ khởi động lại sau khi VPS reboot.
Điều kiện chuẩn bị
- Một VPS Ubuntu đã cập nhật package.
- Domain đã trỏ bản ghi DNS về IP của VPS.
- Source code Next.js và quyền sử dụng
sudo. - Node.js LTS, Nginx và PM2.
Không commit file
.env, private key hay thông tin đăng nhập production vào Git.
Build production
Tại thư mục ứng dụng, cài đúng dependency từ lockfile rồi build. Nếu dự án cần biến môi trường khi build, hãy tạo file .env.production trực tiếp trên VPS hoặc nạp chúng từ secret store trước khi chạy lệnh:
npm ci
npm run build
Với biến chỉ được dùng ở phía server, không thêm tiền tố NEXT_PUBLIC_. Mọi biến có tiền tố này có thể được đóng gói vào JavaScript gửi xuống trình duyệt và không phù hợp để lưu mật khẩu, token hoặc khóa API bí mật.
Nếu build hoàn tất, chạy thử ứng dụng trước khi cấu hình reverse proxy:
npm run start
curl -I http://127.0.0.1:3000
Chạy ứng dụng bằng PM2
pm2 start npm --name deployeasy-web -- start
pm2 save
pm2 startup
Chạy lệnh mà pm2 startup in ra để đăng ký service với systemd, sau đó kiểm tra:
pm2 status
pm2 logs deployeasy-web --lines 100
Reverse proxy với Nginx
Tạo file /etc/nginx/sites-available/example.com và thay example.com bằng tên miền thật:
server {
listen 80;
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";
}
}
Kích hoạt cấu hình, kiểm tra syntax rồi mới reload Nginx:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo nginx -t
sudo systemctl reload nginx
curl -I http://example.com
Nếu muốn hiểu rõ luồng request và ý nghĩa của từng header, xem thêm Nginx reverse proxy là gì. Nếu gặp 502 Bad Gateway, kiểm tra tiến trình PM2, port ứng dụng và log Nginx theo checklist sửa lỗi Nginx 502 trước khi thay đổi firewall.
Bật HTTPS cho domain
Chỉ mở các cổng cần thiết trên firewall, sau đó dùng Certbot để cấp chứng chỉ TLS:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo certbot --nginx -d example.com -d www.example.com
curl -I https://example.com
Kết quả mong đợi là phản hồi HTTPS hợp lệ và request HTTP được chuyển hướng sang HTTPS. Bạn có thể làm theo hướng dẫn chi tiết về HTTPS với Certbot và Nginx.
Cập nhật phiên bản mới an toàn
Không nên vừa tải source vừa dừng ứng dụng đang phục vụ người dùng. Hãy build thành công trước, sau đó mới reload tiến trình:
git pull --ff-only
npm ci
npm run build
pm2 reload deployeasy-web --update-env
pm2 status
Sau mỗi lần cập nhật, kiểm tra trang chủ, một route động, file tĩnh và log lỗi. Ghi lại commit đang chạy để có thể quay về nhanh nếu bản mới gặp sự cố:
git rev-parse --short HEAD
pm2 logs deployeasy-web --lines 100
Nếu cần tự động hóa quá trình này, xem CI/CD deploy VPS bằng GitHub Actions. Với hệ thống quan trọng, nên dùng thư mục release riêng hoặc chiến lược blue-green để rollback không phụ thuộc vào việc sửa source ngay trên thư mục đang chạy.
Cách chẩn đoán theo từng lớp
Khi website không truy cập được, kiểm tra từ trong ra ngoài để tránh sửa nhầm:
pm2 statusxác nhận tiến trình còn online.curl -I http://127.0.0.1:3000xác nhận Next.js đang lắng nghe đúng port.sudo nginx -tvà log/var/log/nginx/error.logxác nhận reverse proxy hợp lệ.dig example.comxác nhận DNS trả về đúng IP VPS.curl -I https://example.comxác nhận HTTPS và phản hồi công khai.
Nếu bước 2 thất bại, vấn đề nằm ở ứng dụng hoặc PM2. Nếu bước 2 thành công nhưng bước 5 thất bại, tập trung vào Nginx, firewall, DNS hoặc chứng chỉ thay vì sửa mã Next.js.
Checklist hoàn tất
- Domain trả về đúng ứng dụng qua HTTPS.
- PM2 khôi phục tiến trình sau khi reboot.
- Nginx config vượt qua
nginx -t. - Secret chỉ tồn tại trên server hoặc secret store.
- Có cách xem log và rollback về phiên bản ổn định.
- Có theo dõi uptime, tài nguyên và dung lượng ổ đĩa.
Đọc tiếp
Bài viết liên quan
Deploy Next.js standalone bằng Docker và Nginx trên VPS
Hướng dẫn self-host Next.js production với output standalone, Docker multi-stage, biến môi trường, static files, Nginx và healthcheck.
Đọc bài →Hướng dẫn deploy REMAP lên VPS Ubuntu
Triển khai monorepo REMAP gồm NestJS, Next.js, React và PostgreSQL lên VPS Ubuntu bằng PM2, Nginx, domain và chứng chỉ SSL.
Đọc bài →Deploy Node.js production bằng PM2 và Nginx trên VPS
Hướng dẫn deploy ứng dụng Node.js bằng PM2, ecosystem file, biến môi trường, startup, log, Nginx reverse proxy và rollback.
Đọc bài →