Khi phát triển ứng dụng Next.js, các nền tảng serverless như Vercel hay Netlify mang lại trải nghiệm deploy rất tiện lợi. Tuy nhiên, khi dự án cần chạy các tác vụ nền dài hạn, kết nối database nội bộ, xử lý socket thời gian thực hoặc bạn muốn tối ưu chi phí server hàng tháng khi traffic tăng cao, việc tự host Next.js trên một VPS (Virtual Private Server) là sự lựa chọn tối ưu và kinh tế nhất.
Trong bài viết này, tôi sẽ hướng dẫn chi tiết từng bước thiết lập một máy chủ Ubuntu sạch (Ubuntu 22.04 / 24.04 LTS), cấu hình quản lý tiến trình với PM2, thiết lập Nginx làm Reverse Proxy, cài đặt chứng chỉ bảo mật SSL miễn phí với Certbot và tự động hóa quá trình deploy qua GitHub Actions.
1. Chuẩn bị VPS và cài đặt môi trường bằng NVM
Sau khi thuê VPS (từ DigitalOcean, Linode, Hetzner, Vultr hoặc các nhà cung cấp trong nước), bạn kết nối vào VPS thông qua SSH.
Để quản lý nhiều phiên bản Node.js một cách linh hoạt và không cần quyền sudo khi cài đặt global packages, chúng ta sẽ cài đặt Node.js thông qua NVM (Node Version Manager):
# 1. Cập nhật package hệ thống & cài công cụ cần thiết
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl git ufw nginx
# 2. Cài đặt NVM (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# 3. Kích hoạt NVM cho session hiện tại
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"
# 4. Cài đặt phiên bản Node.js LTS mới nhất (v20 hoặc v22)
nvm install --lts
nvm use --lts
node -v # Kiểm tra phiên bản node
npm -v # Kiểm tra npm
# 5. Cài đặt pnpm và PM2 toàn cục (không cần sudo)
npm install -g pnpm pm22. Cấu hình tường lửa UFW
Bảo vệ VPS bằng cách chỉ mở các cổng mạng cần thiết: cổng 22 (SSH), 80 (HTTP) và 443 (HTTPS).
# Cho phép SSH và Nginx
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
# Bật tường lửa
sudo ufw enable
sudo ufw status3. Clone mã nguồn và Build ứng dụng
Tạo thư mục chứa dự án tại /var/www/ hoặc trong thư mục home của user:
# Tạo thư mục và cấp quyền
sudo mkdir -p /var/www/my-nextjs-app
sudo chown -R $USER:$USER /var/www/my-nextjs-app
# Clone dự án từ GitHub
git clone https://github.com/username/my-nextjs-app.git /var/www/my-nextjs-app
cd /var/www/my-nextjs-app
# Tạo file biến môi trường .env.production
nano .env.production
# Cài đặt dependencies và build
pnpm install
pnpm buildFacing similar challenges?
I can help you optimize your website — reach out for a free consultation.
4. Quản lý tiến trình Next.js bằng PM2
PM2 giúp ứng dụng chạy nền liên tục, tự động restart khi gặp crash và tự khởi động lại khi VPS reboot.
Hãy tạo file cấu hình ecosystem.config.js tại thư mục gốc của dự án:
module.exports = {
apps: [
{
name: "my-nextjs-app",
script: "node_modules/next/dist/bin/next",
args: "start -p 3000",
cwd: "/var/www/my-nextjs-app",
instances: "max", // Chạy dạng cluster tận dụng đa nhân CPU
exec_mode: "cluster",
env: {
NODE_ENV: "production",
PORT: 3000,
},
max_memory_restart: "800M",
},
],
};Khởi chạy và lưu cấu hình PM2
Chạy các lệnh sau để PM2 nhận file cấu hình và đăng ký service khởi động cùng OS:
# Khởi động ứng dụng
pm2 start ecosystem.config.js
# Lưu danh sách tiến trình
pm2 save
# Tạo script startup khi boot VPS
pm2 startup5. Cấu hình Nginx Reverse Proxy
Nginx sẽ tiếp nhận request từ cổng 80/443 của domain và chuyển tiếp (proxy_pass) về ứng dụng Next.js đang chạy tại cổng localhost:3000, đồng thời xử lý nén Gzip và tối ưu cache cho các file tĩnh trong thư mục _next/static.
Tạo file cấu hình virtual host:
server {
listen 80;
server_name duynoa.com www.duynoa.com;
# Cấu hình proxy sang Next.js Node server
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;
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;
}
# Cache file tĩnh Next.js tĩnh dài hạn
location /_next/static {
alias /var/www/my-nextjs-app/.next/static;
expires 365d;
access_log off;
}
}Kích hoạt virtual host và test cấu hình Nginx
Kích hoạt site bằng symbolic link và reload Nginx:
# Tạo symbolic link
sudo ln -s /etc/nginx/sites-available/my-nextjs-app /etc/nginx/sites-enabled/
# Kiểm tra cú pháp cấu hình
sudo nginx -t
# Khởi động lại Nginx
sudo systemctl restart nginx6. Cài đặt chứng chỉ SSL miễn phí (Let's Encrypt)
Sử dụng Certbot để tự động đăng ký chứng chỉ HTTPS và cấu hình redirect HTTP -> HTTPS trong Nginx:
# Cài đặt Certbot và plugin Nginx
sudo apt install -y certbot python3-certbot-nginx
# Yêu cầu cấp chứng chỉ SSL cho domain
sudo certbot --nginx -d duynoa.com -d www.duynoa.com
# Kiểm tra tính năng tự động gia hạn
sudo systemctl status certbot.timer7. Thiết lập CI/CD tự động Deploy với GitHub Actions
Để không phải SSH vào VPS mỗi khi có code mới, bạn có thể tạo GitHub Action workflow .github/workflows/deploy.yml:
name: Deploy Next.js to VPS
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy qua SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USERNAME }}
key: ${{ secrets.VPS_SSH_KEY }}
script: |
# Load NVM vào session SSH
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
cd /var/www/my-nextjs-app
git pull origin main
pnpm install --frozen-lockfile
pnpm build
pm2 reload my-nextjs-app --update-envKết luận
Việc tự deploy ứng dụng Next.js lên VPS cho bạn toàn quyền kiểm soát hạ tầng, tối ưu chi phí và mở rộng quy mô theo ý muốn. Khi đã nắm vững quy trình kết hợp giữa PM2, Nginx và Certbot, bạn có thể tự tin triển khai bất kỳ dự án production nào với hiệu năng và độ ổn định cao nhất.
Nếu bạn gặp khó khăn trong quá trình cấu hình server, hãy để lại liên hệ bên dưới để được hỗ trợ!
Want to discuss further?
If you have specific questions about web performance, React, or want to collaborate on a project — reach out directly.