Cách cấu hình SSL miễn phí cho website Next.js chạy trên VPS với Let’s Encrypt
Website không có HTTPS → trình duyệt cảnh báo, người dùng mất niềm tin, SEO giảm, API dễ lỗi khi gọi từ frontend. Với ứng dụng Next.js chạy trên VPS, cấu hình SSL không khó nếu dùng Let’s Encrypt + Nginx + Certbot. Chi phí: 0đ. Hiệu quả: domain có ổ khóa xanh, tự động gia hạn, bảo mật tốt hơn.
Bài viết này hướng dẫn cấu hình SSL miễn phí cho website Next.js deploy trên VPS Ubuntu, chạy bằng Node.js/PM2, reverse proxy qua Nginx.
Mô hình triển khai phổ biến
Kiến trúc thường dùng:
– Next.js app chạy nội bộ tại localhost:3000
– Nginx nhận req từ internet qua port 80/443
– Let’s Encrypt cấp SSL cert cho domain
– Certbot tự động cấu hình HTTPS cho Nginx
– PM2 giữ app luôn chạy
Luồng req:
User → https://domain.com → Nginx:443 → localhost:3000 → Next.js
Next.js không cần tự xử lý SSL. Nginx làm TLS termination → nhẹ, chuẩn, dễ bảo trì.
Điều kiện trước khi cấu hình SSL
Trước khi chạy Certbot, cần đảm bảo các điểm sau.
1. VPS đã trỏ domain đúng IP
Trong DNS provider, tạo bản ghi:
A @ YOUR_VPS_IP
A www YOUR_VPS_IPVí dụ:
example.com → 123.123.123.123
www.example.com → 123.123.123.123Kiểm tra:
ping example.com
dig example.comNếu domain chưa trỏ đúng IP → Let’s Encrypt không xác minh được → cấp SSL thất bại.
2. VPS mở port 80 và 443
Let’s Encrypt cần truy cập HTTP port 80 để xác minh domain. HTTPS dùng port 443.
Nếu dùng UFW:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw statusKết quả nên có:
80/tcp ALLOW
443/tcp ALLOW
22/tcp ALLOW3. Next.js app đã chạy ổn
Ví dụ app chạy bằng PM2:
npm install
npm run build
pm2 start npm --name "next-app" -- start
pm2 save
pm2 startupKiểm tra local:
curl http://localhost:3000Nếu có HTML trả về → app OK.
Cài Nginx trên VPS
Với Ubuntu/Debian:
sudo apt update
sudo apt install nginx -yKiểm tra:
sudo systemctl status nginxNếu active → OK.
Mở trình duyệt:
http://YOUR_VPS_IPThấy trang mặc định Nginx → web server hoạt động.
Cấu hình Nginx reverse proxy cho Next.js
Tạo file config cho domain:
sudo nano /etc/nginx/sites-available/example.comNội dung ban đầu, chưa SSL:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
proxy_pass http://localhost: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";
}
}
Giải thích nhanh:
– server_name → domain Nginx nhận req
– proxy_pass → chuyển req vào Next.js
– X-Forwarded-Proto → app biết req gốc là HTTP/HTTPS
– Upgrade + Connection → hỗ trợ websocket, hot reload, realtime nếu có
Kích hoạt site:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/Xóa default nếu cần:
sudo rm /etc/nginx/sites-enabled/defaultTest config:
sudo nginx -tReload:
sudo systemctl reload nginxMở:
http://example.comNếu thấy website Next.js → sẵn sàng cấp SSL.
Cài Certbot và plugin Nginx
Certbot là tool chính thức để xin/gia hạn cert Let’s Encrypt.
Ubuntu:
sudo apt install certbot python3-certbot-nginx -yKiểm tra:
certbot --versionCấp SSL miễn phí với Let’s Encrypt
Chạy lệnh:
sudo certbot --nginx -d example.com -d www.example.comCertbot sẽ hỏi email, điều khoản, redirect HTTPS. Nên chọn redirect toàn bộ HTTP → HTTPS.
Quy trình:
1. Certbot đọc Nginx config. 2. Let’s Encrypt xác minh domain qua port 80. 3. Certbot tải cert về VPS. 4. Certbot tự sửa Nginx config. 5. Nginx reload. 6. Website có HTTPS.
Sau khi thành công, sẽ thấy dạng:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pemMở:
https://example.comNếu hiện ổ khóa → xong.
Nginx config sau khi có SSL
Certbot thường tự thêm block HTTPS. Config sẽ gần giống:
server {
server_name example.com www.example.com;
location / {
proxy_pass http://localhost: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";
}
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
}
if ($host = example.com) {
return 301 https://$host$request_uri;
}
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404;
}
Có thể tối ưu redirect domain chính. Ví dụ muốn www → non-www:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
return 301 https://example.com$request_uri;
}
Mục tiêu: chỉ giữ một canonical domain → SEO gọn hơn.
Kiểm tra tự động gia hạn SSL
Let’s Encrypt cert có hạn 90 ngày. Certbot tự tạo timer gia hạn.
Kiểm tra:
systemctl list-timers | grep certbotTest renew:
sudo certbot renew --dry-runNếu output không lỗi → auto-renew OK.
Cert thường được gia hạn khi còn dưới 30 ngày. Không cần cron thủ công nếu systemd timer đã có.
Lỗi thường gặp và cách xử lý
Domain chưa trỏ đúng IP
Lỗi thường gặp:
unauthorized
connection refused
timeout during connectNguyên nhân:
– DNS chưa cập nhật – Trỏ sai IP – Proxy/CDN đang che IP – Port 80 bị chặn
Fix:
dig example.com
sudo ufw status
sudo systemctl status nginxChờ DNS propagation nếu mới chỉnh.
Nginx config lỗi
Kiểm tra:
sudo nginx -tNếu lỗi syntax → sửa file trong:
/etc/nginx/sites-available/example.comReload sau khi sửa:
sudo systemctl reload nginxNext.js không phản hồi sau proxy
Kiểm tra app:
pm2 status
curl http://localhost:3000Nếu app chết:
pm2 restart next-app
pm2 logs next-appNếu app chạy port khác, sửa:
proxy_pass http://localhost:YOUR_PORT;Mixed content
HTTPS site nhưng gọi asset/API bằng HTTP → trình duyệt chặn.
Fix:
– Đổi API URL sang https://
– Dùng biến môi trường đúng:
NEXT_PUBLIC_API_URL=https://api.example.comRebuild app:
npm run build
pm2 restart next-appTăng bảo mật SSL thêm một bước
Sau khi SSL hoạt động, có thể thêm security headers trong Nginx:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;HSTS chỉ bật khi chắc chắn website luôn dùng HTTPS:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;Cảnh báo: HSTS khiến browser ép dùng HTTPS lâu dài. Nếu cert/config lỗi → user có thể không truy cập được bằng HTTP fallback.
Test SSL:
https://www.ssllabs.com/ssltest/Mục tiêu: grade A/A+.
Checklist triển khai nhanh
– Domain A record → VPS IP
– Port 80/443 mở
– Next.js chạy tại localhost:3000
– Nginx reverse proxy OK qua HTTP
– Certbot installed
– Chạy:
sudo certbot --nginx -d example.com -d www.example.com– Test:
sudo certbot renew --dry-run– Kiểm tra browser:
https://example.comKết luận
Cấu hình SSL miễn phí cho Next.js trên VPS không cần phức tạp. Cách ổn định nhất: để Next.js chạy nội bộ, dùng Nginx làm reverse proxy, dùng Let’s Encrypt/Certbot cấp HTTPS. Mô hình này dễ deploy, dễ debug, hỗ trợ auto-renew, phù hợp từ website cá nhân đến production app.
Nếu làm đúng thứ tự — DNS → Nginx → proxy → Certbot → renew test — quá trình thường chỉ mất 10-15 phút. Quan trọng nhất: domain phải trỏ đúng VPS, port 80/443 mở, Next.js app chạy ổn trước khi xin cert. Khi SSL đã hoạt động, hãy kiểm tra mixed content, auto-renew, security headers để website vừa an toàn vừa chuyên nghiệp.
Bình luận (0)
Chưa có bình luận. Hãy là người đầu tiên!