Vercel hay Netlify là những nền tảng PaaS tuyệt vời để đưa một dự án Next.js lên production chỉ trong vài cú click chuột. Tuy nhiên, khi dự án bắt đầu có lượng traffic lớn, sử dụng nhiều bandwidth truyền tải ảnh, gọi API Serverless liên tục hoặc dự án thuộc các doanh nghiệp yêu cầu lưu trữ dữ liệu tại máy chủ nội địa, chi phí sử dụng các nền tảng đám mây này có thể tăng chóng mặt.
Việc tự triển khai (**Self-hosting**) Next.js lên một máy chủ ảo cá nhân (**VPS Ubuntu**) mang lại rất nhiều lợi ích: - **Tối ưu chi phí vượt trội**: Chỉ với một gói VPS từ 5$ – 10$/tháng (DigitalOcean, Hetzner, Linode, OVH hoặc các nhà cung cấp VPS Việt Nam như Viettel IDC, Vietnix, BKNS), bạn có thể chạy thoải mái nhiều ứng dụng cùng lúc với băng thông không giới hạn. - **Toàn quyền kiểm soát hệ thống**: Tự do can thiệp cấu hình Nginx Caching, thiết lập hệ thống phòng chống DDoS, giới hạn rate limit, kết nối Database nội bộ (PostgreSQL, Redis) trên cùng mạng riêng (Private Network) với độ trễ cực thấp. - **Tùy biến môi trường sâu**: Không bị giới hạn thời gian thực thi (Execution Timeout) như Serverless Functions (10s – 60s).
Bài viết này là cẩm nang thực chiến từng bước (Step-by-Step) giúp bạn đưa ứng dụng Next.js lên môi trường Production với đầy đủ các tiêu chuẩn an toàn, mượt mà và tự động hóa.
1. Chuẩn bị VPS & Cài đặt môi trường cần thiết trên Ubuntu
Sau khi đăng ký một VPS chạy hệ điều hành Ubuntu 22.04 LTS hoặc Ubuntu 24.04 LTS, bạn kết nối vào máy chủ thông qua SSH:
ssh root@<ip-vps-cua-ban>Sau khi đăng nhập thành công, hãy cập nhật toàn bộ các gói hệ thống lên phiên bản mới nhất:
# 1. Cập nhật danh sách gói và nâng cấp hệ thống
sudo apt update && sudo apt upgrade -y
# 2. Cài đặt các công cụ cơ bản cần thiết
sudo apt install -y curl wget git ufw htop build-essential2. Cài đặt Node.js (LTS), pnpm và PM2 thông qua NVM
Sử dụng NVM (Node Version Manager) là phương pháp chuẩn và linh hoạt nhất để quản lý các phiên bản Node.js trên Ubuntu. NVM giúp bạn dễ dàng cài đặt, chuyển đổi giữa các phiên bản Node (Node 20, 22, v.v.) mà không gặp xung đột quyền hạn (permission denied hay phải dùng sudo):
# 1. Tải và cài đặt NVM (phiên bản mới nhất)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# 2. Tải lại cấu hình shell terminal để nhận lệnh nvm
source ~/.bashrc
# (Hoặc source ~/.zshrc nếu bạn dùng Zsh)
# 3. Kiểm tra NVM đã cài thành công chưa
nvm -v # Vd: 0.40.1
# 4. Cài đặt phiên bản Node.js LTS mới nhất (Node 22 hoặc 20)
nvm install --lts
# 5. Đặt phiên bản LTS làm mặc định
nvm use --lts
nvm alias default 'lts/*'
# 6. Kiểm tra phiên bản Node và npm
node -v # Vd: v22.14.0
npm -v # Vd: 10.9.2
# 7. Cài đặt pnpm và PM2 toàn cục (không cần sudo khi dùng NVM)
npm install -g pnpm pm2
# 8. Kiểm tra pnpm và pm2
pnpm -v
pm2 -v3. Tối ưu mã nguồn Next.js với chế độ Standalone Output
Theo mặc định, thư mục node_modules của một dự án Next.js có thể nặng tới hàng trăm megabytes hoặc hàng gigabytes. Khi deploy lên VPS, bạn nên bật tính năng Standalone Output trong file next.config.js (hoặc next.config.ts).
Chế độ này sẽ tự động phân tích và chỉ gom đúng những file, dependencies thực sự cần thiết khi chạy ứng dụng vào thư mục .next/standalone, giúp tiết kiệm dung lượng và tăng tốc khởi động ứng dụng vượt bậc.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// Bật chế độ standalone để tối ưu build size khi self-host
output: "standalone",
// Tùy chọn tối ưu ảnh
images: {
unoptimized: false, // Sử dụng Sharp để tối ưu ảnh trên VPS
},
};
export default nextConfig;Facing similar challenges?
I can help you optimize your website — reach out for a free consultation.
4. Clone mã nguồn lên VPS và Build Production
Tạo một thư mục chứa ứng dụng (thường đặt tại /var/www/) và clone mã nguồn từ GitHub/GitLab:
# Tạo thư mục chứa app và phân quyền
sudo mkdir -p /var/www/my-next-app
sudo chown -R $USER:$USER /var/www/my-next-app
# Di chuyển vào thư mục
cd /var/www/my-next-app
# Clone repository của bạn
git clone https://github.com/your-username/your-repo.git .
# Tạo file biến môi trường production
cp .env.example .env.production
nano .env.production # Điền các biến môi trường thực tế (DATABASE_URL, API_KEYS, v.v.)
# Cài đặt dependencies và Build
pnpm install --frozen-lockfile
pnpm build5. Quản lý tiến trình Next.js chuyên nghiệp với PM2
Khi chạy ứng dụng trên máy chủ production, chúng ta không thể sử dụng lệnh pnpm start thông thường vì nếu ứng dụng crash hoặc VPS reboot, trang web sẽ sập hoàn toàn.
PM2 là công cụ quản lý tiến trình (Process Manager) chuẩn công nghiệp cho Node.js, cung cấp các tính năng:
- Tự động restart ngay lập tức khi ứng dụng bị unhandled exception.
- Hỗ trợ chạy Cluster Mode để tận dụng tối đa số lượng nhân CPU.
- Tự động khởi động lại ứng dụng khi máy chủ bị khởi động lại (Reboot).
- Ghi log truy cập và log lỗi chuyên nghiệp.
Hãy tạo file cấu hình ecosystem.config.js ngay tại thư mục gốc của dự án:
module.exports = {
apps: [
{
name: "next-app",
// Nếu dùng standalone mode:
script: ".next/standalone/server.js",
// Nếu dùng chế độ build thông thường:
// script: "node_modules/next/dist/bin/next",
// args: "start -p 3000",
instances: "max", // Chạy tối đa theo số core CPU (hoặc số cụ thể: 2)
exec_mode: "cluster", // Chạy dạng cluster để phân tải
watch: false,
max_memory_restart: "500M", // Tự restart nếu rò rỉ bộ nhớ vượt 500MB
env: {
NODE_ENV: "production",
PORT: 3000,
},
// Cấu hình log
error_file: "./logs/pm2-err.log",
out_file: "./logs/pm2-out.log",
merge_logs: true,
time: true,
},
],
};6. Khởi chạy ứng dụng với PM2 và thiết lập Auto Startup
Lưu ý: Nếu sử dụng chế độ standalone, trước khi chạy server.js bạn cần copy thư mục public và .next/static vào đúng vị trí của standalone:
# Sao chép static files vào thư mục standalone (chỉ cần làm nếu dùng standalone)
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/
# Khởi chạy ứng dụng qua PM2
pm2 start ecosystem.config.js
# Kiểm tra trạng thái tiến trình
pm2 status
# Lưu lại danh sách tiến trình đang chạy
pm2 save
# Thiết lập PM2 tự khởi động cùng hệ điều hành Ubuntu
pm2 startup
# (Chạy dòng lệnh mà PM2 vừa in ra màn hình để hoàn tất cấu hình startup)7. Cài đặt và cấu hình Nginx làm Reverse Proxy
Hiện tại ứng dụng Next.js đang chạy nội bộ tại cổng 3000 (localhost:3000). Chúng ta cần cài đặt Nginx để làm Reverse Proxy tiếp nhận các request từ cổng tiêu chuẩn 80 (HTTP) và 443 (HTTPS) từ internet rồi chuyển tiếp vào cổng 3000.
Cài đặt Nginx:
``bash
sudo apt install -y nginx
``
Tạo một file cấu hình Virtual Host mới cho tên miền của bạn tại /etc/nginx/sites-available/your-domain.com:
# Upstream trỏ về cổng Next.js đang lắng nghe
upstream nextjs_upstream {
server 127.0.0.1:3000;
keepalive 64;
}
server {
listen 80;
listen [::]:80;
server_name your-domain.com www.your-domain.com;
# Giới hạn dung lượng upload file (mặc định Nginx là 1MB)
client_max_body_size 20M;
# Gzip Compression tối ưu tốc độ tải trang
gzip on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
# Cache static assets từ Next.js (_next/static)
location /_next/static {
proxy_pass http://nextjs_upstream;
proxy_set_header Host $host;
expires 365d;
access_log off;
add_header Cache-Control "public, max-age=31536000, immutable";
}
# Cache các file tĩnh trong public (ảnh, fonts, favicon)
location ~* .(ico|jpg|jpeg|png|gif|svg|webp|avif|woff|woff2|ttf|eot)$ {
proxy_pass http://nextjs_upstream;
proxy_set_header Host $host;
expires 30d;
access_log off;
add_header Cache-Control "public, max-age=2592000";
}
# Chuyển tiếp tất cả request còn lại về Next.js
location / {
proxy_pass http://nextjs_upstream;
proxy_http_version 1.1;
# Hỗ trợ WebSockets & SSE Streaming (cần thiết cho React 19 / AI streaming)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Chuyển tiếp thông tin client IP thực tế
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;
# Timeout cho các tác vụ xử lý lâu
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
}
}8. Kích hoạt Virtual Host Nginx
Kích hoạt cấu hình vừa tạo bằng cách tạo symbolic link sang thư mục sites-enabled, kiểm tra lỗi cú pháp và khởi động lại Nginx:
# 1. Tạo symbolic link kích hoạt site
sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/
# 2. Xóa cấu hình mặc định default nếu không dùng
sudo rm -f /etc/nginx/sites-enabled/default
# 3. Kiểm tra tính hợp lệ của cấu hình Nginx
sudo nginx -t
# Nếu hiển thị: "nginx: configuration file /etc/nginx/nginx.conf test is successful" -> Hợp lệ!
# 4. Reload Nginx
sudo systemctl reload nginx9. Cài đặt chứng chỉ SSL miễn phí với Certbot (Let's Encrypt)
Trước khi thực hiện bước này, hãy đảm bảo bạn đã trỏ bản ghi A record của tên miền your-domain.com và www.your-domain.com về địa chỉ IP của VPS trên trang quản lý DNS (Cloudflare, Namecheap, v.v.).
Cài đặt Certbot và plugin Nginx để tự động tạo và cấu hình chứng chỉ HTTPS an toàn:
# Cài đặt Certbot qua apt
sudo apt install -y certbot python3-certbot-nginx
# Yêu cầu cấp chứng chỉ SSL và tự động cấu hình file Nginx
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
# Quá trình này sẽ yêu cầu bạn nhập Email và chọn tự động Redirect HTTP -> HTTPS.
# Hãy chọn Yes để toàn bộ truy cập đều được mã hóa an toàn.
# Kiểm tra tính năng tự động gia hạn chứng chỉ (Auto-Renewal)
sudo certbot renew --dry-run10. Thiết lập tường lửa bảo mật với UFW
Để bảo vệ máy chủ VPS khỏi các cuộc quét cổng trái phép, bạn nên bật tường lửa UFW và chỉ mở đúng 3 cổng cần thiết: SSH (22), HTTP (80) và HTTPS (443):
# Cho phép kết nối SSH (BẮT BUỘC, nếu không bạn sẽ bị mất quyền truy cập VPS!)
sudo ufw allow OpenSSH
# Cho phép traffic Web HTTP và HTTPS
sudo ufw allow 'Nginx Full'
# Kích hoạt tường lửa
sudo ufw enable
# Kiểm tra trạng thái
sudo ufw status11. Tự động hóa cập nhật mã nguồn với Script Deploy 1-chạm
Mỗi khi bạn đẩy code mới lên GitHub, thay vì phải gõ lại từng lệnh trên terminal VPS, hãy tạo một file script deploy.sh tại thư mục gốc /var/www/my-next-app/deploy.sh:
#!/bin/bash
set -e
echo "🚀 Bắt đầu quá trình Deploy Next.js..."
# 1. Kéo mã nguồn mới nhất từ nhánh main
echo "📥 Đang tải code mới từ Git..."
git pull origin main
# 2. Cài đặt các thư viện mới nếu có
echo "📦 Đang cài đặt dependencies..."
pnpm install --frozen-lockfile
# 3. Build lại ứng dụng Next.js
echo "🏗️ Đang build Next.js Production..."
pnpm build
# 4. Đồng bộ static assets cho standalone mode (nếu có)
if [ -d ".next/standalone" ]; then
echo "📂 Sao chép static files vào standalone directory..."
cp -r public .next/standalone/
cp -r .next/static .next/standalone/.next/
fi
# 5. Reload PM2 không gián đoạn (Zero-Downtime Reload)
echo "♻️ Khởi động lại PM2 instances..."
pm2 reload next-app --update-env
echo "✅ Deploy thành công rực rỡ!"12. Cấp quyền thực thi cho Deploy Script
Cấp quyền thực thi cho file script:
chmod +x /var/www/my-next-app/deploy.shTừ bây giờ, mỗi lần cần cập nhật website, bạn chỉ cần SSH vào VPS và chạy đúng 1 lệnh duy nhất:
``bash
cd /var/www/my-next-app && ./deploy.sh
``
Hoặc bạn có thể tích hợp lệnh này vào GitHub Actions thông qua SSH Action để đạt được quy trình CI/CD hoàn toàn tự động mỗi khi có commit mới vào nhánh main!
Kết luận
Chúc mừng bạn! Bạn đã tự tay thiết lập thành công một hạ tầng máy chủ Production hoàn chỉnh cho ứng dụng Next.js với đầy đủ các thành phần cốt lõi: VPS Ubuntu, Node.js LTS, PM2 Process Manager, Nginx Reverse Proxy & Caching, cùng chứng chỉ SSL Let's Encrypt.
Mô hình triển khai này không chỉ giúp bạn tiết kiệm tối đa ngân sách vận hành mà còn mang lại sự linh hoạt vô hạn trong việc mở rộng hạ tầng, nâng cấp phần cứng và làm chủ hoàn toàn sản phẩm của mình.
Want to discuss further?
If you have specific questions about web performance, React, or want to collaborate on a project — reach out directly.