Nginx reverse proxy là mô hình rất phổ biến khi ứng dụng backend chạy trên một port nội bộ như 3000, 5000 hoặc 8000 nhưng người dùng truy cập qua domain và HTTPS chuẩn ở port 80/443. Thay vì mở trực tiếp port ứng dụng ra Internet, Nginx đứng ở phía trước để nhận request, xử lý TLS, header, redirect và chuyển traffic tới backend qua `proxy_pass`. Bài viết này hướng dẫn từng bước trên VPS Ubuntu: cài Nginx, tạo server block, proxy tới app local, truyền các header quan trọng, hỗ trợ WebSocket, kiểm tra bằng `nginx -t`, cấp SSL bằng Certbot và xử lý các lỗi thường gặp như 502 Bad Gateway, redirect loop, mất IP thật hoặc WebSocket không kết nối.
Khi chạy backend Node.js, Python, Go hoặc một ứng dụng web riêng trên VPS Ubuntu, ứng dụng thường lắng nghe ở một port nội bộ như:
127.0.0.1:3000
127.0.0.1:5000
127.0.0.1:8000
Bạn có thể mở port này trực tiếp ra Internet, nhưng mô hình tốt hơn trong nhiều trường hợp là đặt Nginx reverse proxy ở phía trước.
Nginx sẽ nhận request từ domain, xử lý HTTP/HTTPS rồi chuyển tiếp tới backend bằng proxy_pass.
Nếu bạn chưa có Nginx, có thể tham khảo bài Hướng dẫn cài website trên VPS Ubuntu. Nếu app chạy bằng systemd, bài Tạo systemd service trên VPS Ubuntu sẽ giúp backend tự chạy sau reboot.
1. Reverse proxy là gì?
Reverse proxy là server đứng giữa client và backend.
Luồng request:
Client
↓
Nginx :443
↓
Backend 127.0.0.1:3000
Client không cần biết backend thật chạy ở port nào.
2. Lợi ích của Nginx reverse proxy
- chỉ cần mở port 80/443;
- backend có thể bind localhost;
- xử lý HTTPS tập trung;
- hỗ trợ redirect;
- truyền header chuẩn;
- route nhiều domain/subdomain;
- cân bằng tải trong kiến trúc lớn hơn;
- hỗ trợ cache hoặc rate limit khi cần.
3. Chuẩn bị VPS
Bạn cần:
- Ubuntu Server;
- quyền sudo;
- domain trỏ về VPS;
- backend đang chạy ổn;
- Nginx;
- firewall mở 80/443.
Nếu đang cần một VPS Linux cho backend hoặc website, có thể tham khảo VPS tại HUONG CLOUD.
4. Cài Nginx
sudo apt update
sudo apt install nginx -y
Kiểm tra:
sudo systemctl status nginx
5. Kiểm tra backend trước khi cấu hình proxy
Giả sử app chạy port 3000:
curl -I http://127.0.0.1:3000
Hoặc:
curl http://127.0.0.1:3000
Nếu backend không trả lời local, Nginx cũng không thể proxy được.
6. Không nên mở backend port public nếu không cần
Nếu app chỉ được Nginx truy cập, nên bind:
127.0.0.1:3000
thay vì:
0.0.0.0:3000
Điều này giảm bề mặt tấn công.
7. Tạo server block
Ví dụ domain:
api.example.com
Tạo:
sudo nano /etc/nginx/sites-available/api.example.com
Cấu hình cơ bản:
server {
listen 80;
listen [::]:80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
8. Bật site
sudo ln -s /etc/nginx/sites-available/api.example.com /etc/nginx/sites-enabled/api.example.com
Kiểm tra:
sudo nginx -t
Nếu ổn:
sudo systemctl reload nginx
9. Truyền header quan trọng
Một cấu hình thực tế thường cần:
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;
}
Nginx documentation mô tả proxy_set_header để thay đổi/thêm header gửi tới upstream.
10. Vì sao cần Host header?
Backend có thể dùng hostname để:
- tạo URL;
- xác định tenant;
- redirect;
- validate domain.
Nếu không truyền $host, app có thể nhận host upstream nội bộ thay vì domain public.
11. X-Real-IP và X-Forwarded-For
Backend trực tiếp kết nối từ Nginx nên source IP socket thường là localhost hoặc IP reverse proxy.
Các header này giúp app biết IP client gốc trong mô hình proxy.
Tuy nhiên, app phải chỉ tin header từ proxy đáng tin cậy, không tin tùy tiện từ Internet.
12. X-Forwarded-Proto
Header:
X-Forwarded-Proto
cho backend biết request gốc là HTTP hay HTTPS.
Nếu app không nhận đúng, có thể tạo redirect loop hoặc sinh URL http:// dù người dùng truy cập HTTPS.
13. proxy_pass có dấu / khác gì?
Đây là điểm dễ nhầm.
Ví dụ:
location /api/ {
proxy_pass http://127.0.0.1:3000/;
}
và:
location /api/ {
proxy_pass http://127.0.0.1:3000;
}
có hành vi URI khác nhau.
Hãy kiểm tra tài liệu Nginx proxy_pass và test endpoint thật trước production.
14. Proxy một subpath
Ví dụ backend chạy root /, nhưng public dùng /api/:
location /api/ {
proxy_pass http://127.0.0.1:3000/;
}
Test:
curl http://api.example.com/api/health
15. WebSocket cần cấu hình gì?
WebSocket dùng cơ chế HTTP Upgrade.
Nginx cần chuyển các header phù hợp:
location /socket/ {
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;
}
Nginx có tài liệu riêng về WebSocket proxying.
16. Cách cấu hình Connection tốt hơn
Với nhiều location, bạn có thể dùng map trong block http:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
Sau đó:
proxy_set_header Connection $connection_upgrade;
Cách này tránh gửi upgrade khi request không phải WebSocket.
17. Timeout cho backend
Một số API xử lý lâu có thể cần điều chỉnh timeout.
Ví dụ:
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
Không tăng timeout lên vài giờ chỉ để che lỗi ứng dụng.
18. Upload file lớn
Nginx có giới hạn request body qua:
client_max_body_size 20M;
Nếu upload báo 413 Request Entity Too Large, kiểm tra option này.
Đừng đặt quá lớn nếu ứng dụng không cần.
19. Buffering
Nginx có proxy buffering mặc định trong nhiều cấu hình.
Với streaming hoặc SSE, buffering có thể cần tắt:
proxy_buffering off;
Chỉ tắt ở endpoint cần thiết.
20. Server-Sent Events
Nếu backend dùng SSE, cần đảm bảo:
- read timeout đủ;
- buffering phù hợp;
- app flush dữ liệu;
- CDN/proxy phía trước không đóng connection sớm.
21. Cấp SSL bằng Certbot
Khi domain đã trỏ đúng VPS:
sudo snap install --classic certbot
Sau đó:
sudo certbot --nginx -d api.example.com
Certbot có thể cấu hình HTTPS và redirect trong nhiều trường hợp.
22. Kiểm tra SSL
curl -I https://api.example.com
Kiểm tra renew:
sudo certbot renew --dry-run
23. Firewall
Nếu dùng UFW:
sudo ufw allow 'Nginx Full'
Không cần mở port 3000 public nếu Nginx và app cùng VPS.
24. Lỗi 502 Bad Gateway
Đây là lỗi phổ biến nhất.
Nguyên nhân:
- backend không chạy;
- port sai;
- backend bind sai interface;
- socket permission;
- app crash;
- Nginx không kết nối được upstream.
Kiểm tra:
curl http://127.0.0.1:3000
sudo ss -tulnp | grep 3000
sudo tail -n 100 /var/log/nginx/error.log
25. Lỗi 504 Gateway Timeout
Nginx kết nối được upstream nhưng backend không phản hồi kịp.
Kiểm tra:
- app bị treo;
- query database chậm;
- external API;
- timeout quá thấp;
- CPU/RAM quá tải.
Đừng chỉ tăng timeout mà không tìm nguyên nhân.
26. Redirect loop sau khi bật HTTPS
Thường xảy ra khi backend không biết request gốc đã là HTTPS.
Đảm bảo:
proxy_set_header X-Forwarded-Proto $scheme;
và framework được cấu hình trust proxy đúng cách.
27. Backend nhận IP 127.0.0.1
Đây là bình thường ở socket connection giữa Nginx và app.
Dùng:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Sau đó cấu hình framework tin proxy đúng nguồn.
28. Nginx reverse proxy Node.js
Ví dụ:
server {
listen 80;
server_name app.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;
}
}
Node app nên chạy bằng systemd hoặc process manager phù hợp.
29. Nginx reverse proxy Python/Gunicorn
Backend:
127.0.0.1:8000
Proxy:
proxy_pass http://127.0.0.1:8000;
Gunicorn có thể chạy bằng systemd.
30. Reverse proxy tới Unix socket
Một số backend dùng Unix socket:
/run/myapp.sock
Nginx hỗ trợ proxy tới Unix socket với cú pháp phù hợp.
Bạn cần đặc biệt chú ý permission của socket và user www-data.
31. Reverse proxy nhiều app trên một VPS
Ví dụ:
api.example.com → 127.0.0.1:3000
admin.example.com → 127.0.0.1:4000
status.example.com → 127.0.0.1:3001
Mỗi domain có server block riêng.
Đây là cách tốt để chạy nhiều service mà không mở hàng loạt port public.
32. Reverse proxy theo path
Ví dụ:
example.com/api → backend A
example.com/admin → backend B
Cấu hình nhiều location.
Tuy nhiên, app phải hỗ trợ base path hoặc rewrite đúng cách.
33. Health check đơn giản
Tạo endpoint:
/health
Nginx có thể proxy tới backend và monitoring như Uptime Kuma kiểm tra endpoint này.
Bạn có thể tham khảo bài Cài Uptime Kuma trên VPS Ubuntu.
34. Log Nginx
Access log:
/var/log/nginx/access.log
Error log:
/var/log/nginx/error.log
Theo dõi:
sudo tail -f /var/log/nginx/error.log
35. Kiểm tra cấu hình trước reload
Luôn chạy:
sudo nginx -t
Sau đó:
sudo systemctl reload nginx
Không reload nếu syntax test fail.
36. Graceful reload
Nginx hỗ trợ reload cấu hình theo cách graceful: worker mới nhận config mới trong khi worker cũ hoàn tất request hiện tại theo cơ chế của Nginx.
Điều này giúp giảm gián đoạn khi thay đổi cấu hình.
37. Bảo mật backend
- bind localhost nếu chỉ Nginx truy cập;
- không chạy app bằng root;
- dùng firewall;
- cập nhật runtime;
- validate header;
- không tin X-Forwarded-For từ mọi nguồn;
- hạn chế debug endpoint.
38. Có nên proxy database qua Nginx?
Không. Nginx HTTP reverse proxy dành cho HTTP/HTTPS và một số giao thức liên quan.
Database nên dùng network/private firewall riêng.
39. Rate limit có thể làm ở Nginx không?
Có qua limit_req, nhưng cần cấu hình theo API và traffic thực tế.
Không đặt rate quá thấp khiến user hợp lệ bị chặn.
40. Cache API ở Nginx có nên không?
Có thể, nhưng chỉ với endpoint cacheable và khi bạn hiểu cache key/invalidation.
Không cache response cá nhân hóa hoặc dữ liệu nhạy cảm tùy tiện.
41. Tình huống thực tế: app chạy port 3000
Quy trình:
- app chạy
127.0.0.1:3000; - test curl local;
- tạo server block;
nginx -t;- reload;
- trỏ DNS;
- cấp SSL;
- test HTTPS;
- monitor
/health.
42. Checklist Nginx reverse proxy
- Backend local hoạt động.
- Backend không public nếu không cần.
- Domain trỏ đúng VPS.
- Server block đúng hostname.
-
proxy_passđúng port. - Header forwarded đúng.
- WebSocket được cấu hình nếu cần.
-
nginx -tpass. - SSL hoạt động.
- Firewall chỉ mở 80/443.
- Monitoring endpoint hoạt động.
43. FAQ về Nginx reverse proxy
Reverse proxy có khác redirect không?
Có. Redirect yêu cầu client truy cập URL khác, còn reverse proxy nhận request rồi chuyển nội bộ tới backend.
Có cần mở port backend ra Internet không?
Không nếu Nginx và backend cùng VPS.
Vì sao gặp 502?
Thường backend không chạy, sai port hoặc Nginx không kết nối được upstream.
WebSocket có cần cấu hình riêng không?
Có. Cần chuyển Upgrade/Connection header phù hợp.
Có thể proxy nhiều domain trên một VPS không?
Có. Mỗi server block có thể chuyển tới backend khác nhau.
Có thể dùng HTTPS ở Nginx và HTTP nội bộ tới backend không?
Có. Đây là mô hình rất phổ biến khi cả hai chạy trên cùng host/private network.
Kết luận
Nginx reverse proxy trên VPS Ubuntu giúp bạn đưa backend ra Internet theo cách gọn và dễ quản lý hơn: client chỉ truy cập domain qua 80/443, còn app có thể nằm ở localhost.
Hãy kiểm tra backend trước, truyền đúng header, cấu hình WebSocket nếu cần và luôn chạy nginx -t trước reload. Khi gặp 502/504, hãy xem log và xác minh upstream thay vì restart ngẫu nhiên.
Nếu bạn cần VPS Ubuntu tại HUONG CLOUD để chạy API, Node.js, Python hoặc nhiều service sau Nginx, hãy chọn RAM/CPU dựa trên workload backend và theo dõi response time thực tế sau khi triển khai.
Nguồn tham khảo
- Nginx – Proxy module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
- Nginx – WebSocket proxying: https://nginx.org/en/docs/http/websocket.html
- Nginx – Beginner's Guide: https://nginx.org/en/docs/beginners_guide.html
- Nginx – Controlling nginx: https://nginx.org/en/docs/control.html
Kết luận
Nếu chưa chắc cấu hình hoặc loại dịch vụ nào phù hợp, hãy gửi nhu cầu thực tế để đội ngũ hỗ trợ tư vấn trước khi mua.
Chưa biết nên chọn gói nào?
Xem bảng giá VPS hoặc liên hệ đội ngũ hỗ trợ để chọn cấu hình phù hợp.
Xem bảng giá VPS →