Lỗi
502 Bad Gateway
Lỗi này xảy ra ở tầng proxy. Nginx, Apache, load balancer hoặc Cloudflare nhận được yêu cầu của bạn bình thường — nhưng khi cố gắng chuyển tiếp yêu cầu đó lên upstream, nó không nhận được phản hồi hữu ích nào. Proxy vẫn hoạt động. Backend mới là bên không phối hợp.
Nguyên nhân thường gặp: app server bị crash, sai port, upstream timeout, hoặc cấu hình sai chỉ thị proxy_pass.
Bước 1 — Kiểm tra xem Backend có thực sự đang chạy không
Trước khi đụng vào cấu hình Nginx, hãy xác nhận tiến trình upstream còn sống.
# Kiểm tra xem app Node.js/Python/Gunicorn có đang lắng nghe không
sudo ss -tlnp | grep 3000
# hoặc
sudo netstat -tlnp | grep 3000
# Nếu không có gì hiện ra, app đã down — khởi động lại
sudo systemctl restart myapp
# Kiểm tra log của app
journalctl -u myapp -n 50 --no-pager
Nếu port đó không mở, Nginx không có gì để kết nối. Thay đổi cấu hình bao nhiêu cũng vô ích. Hãy sửa app trước.
Bước 2 — Xác minh Nginx đang trỏ đúng chỗ
Mở file cấu hình site của bạn:
sudo nano /etc/nginx/sites-available/mysite
Kiểm tra kỹ dòng proxy_pass:
location / {
proxy_pass http://127.0.0.1:3000; # must match your app's actual port
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;
}
Bốn lỗi thường gặp gây ra lỗi này:
- Sai port — app chạy trên
3000nhưng cấu hình lại ghi8080 - Dùng
localhostthay vì127.0.0.1khi phân giải IPv6 hoạt động không như mong đợi - Không nhất quán về dấu gạch chéo cuối —
proxy_pass http://127.0.0.1:3000/so với không có dấu gạch chéo sẽ thay đổi cách path được viết lại - Trỏ đến Unix socket không tồn tại hoặc có quyền sai
Bước 3 — Kiểm tra cài đặt Timeout của Upstream
Các truy vấn DB nặng, cold start, hoặc gọi API ngoài chậm có thể khiến backend vượt quá timeout mặc định 60 giây của Nginx. Proxy bỏ cuộc và trả về 502 trước khi phản hồi kịp đến.
location / {
proxy_pass http://127.0.0.1:3000;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
Tăng các giá trị này chỉ mua thêm thời gian, không giải quyết gốc rễ. Backend mà thường xuyên mất hơn 90 giây là có vấn đề hiệu suất cần được xử lý từ nguồn.
Bước 4 — Đọc Error Log của Nginx
Theo dõi error log trước — nó thường cho bạn biết chính xác điều gì đã hỏng:
sudo tail -f /var/log/nginx/error.log
Bạn sẽ thấy nội dung kiểu như:
[error] 12345#0: *1 connect() failed (111: Connection refused) while connecting to upstream,
client: 1.2.3.4, server: example.com, request: "GET / HTTP/1.1",
upstream: "http://127.0.0.1:3000/", host: "example.com"
Connection refused = backend không chạy trên port đó.
upstream timed out = backend đang chạy nhưng quá chậm hoặc bị treo.
Bước 5 — Môi trường Docker / Container
Đang chạy app trong Docker với Nginx trên host (hoặc trong container riêng)? Thì 127.0.0.1 sẽ không hoạt động — bên trong container, địa chỉ đó trỏ đến chính container, không phải máy host.
# Tùy chọn 1: Dùng IP gateway của host (Docker Desktop trên Linux)
proxy_pass http://172.17.0.1:3000;
# Tùy chọn 2: Dùng DNS nội bộ của Docker nếu cả hai cùng network
proxy_pass http://app-container-name:3000;
# Tìm IP gateway
docker network inspect bridge | grep Gateway
Trong docker-compose.yml, cả hai service cần chia sẻ cùng một network:
services:
nginx:
networks:
- webnet
app:
networks:
- webnet
networks:
webnet:
Bước 6 — Unix Socket thay vì TCP Port
Gunicorn và uWSGI thường dùng Unix socket thay vì TCP port. Có hai vấn đề có thể xảy ra: file socket không tồn tại, hoặc Nginx không đọc được nó.
# Kiểm tra xem socket có tồn tại không
ls -la /run/myapp.sock
# Cấu hình Nginx cho socket
location / {
proxy_pass http://unix:/run/myapp.sock;
}
# Sửa quyền nếu user Nginx (www-data) không đọc được
sudo chown www-data:www-data /run/myapp.sock
Xác nhận bản sửa lỗi
Kiểm tra theo thứ tự này — mỗi bước xác nhận một tầng khác nhau:
# Kiểm tra cú pháp cấu hình Nginx trước
sudo nginx -t
# Reload không có downtime
sudo systemctl reload nginx
# Xác nhận backend có thể truy cập trực tiếp (bỏ qua Nginx)
curl -v http://127.0.0.1:3000/
# Sau đó kiểm tra qua Nginx
curl -v http://yourdomain.com/
# Theo dõi access log trực tiếp
sudo tail -f /var/log/nginx/access.log
Nhận được 200 OK khi curl trực tiếp và qua Nginx là xác nhận mọi thứ đã được kết nối đúng.
Mẹo
Lỗi 502 không liên tục — chỉ xuất hiện khi tải cao, không phải lúc nào cũng có — thường có nghĩa là upstream pool đã cạn kiệt. Thêm một instance thứ hai và Nginx sẽ phân phối tải luân phiên giữa chúng:
upstream backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
keepalive 32;
}
Nhân tiện, hãy thêm trang lỗi tùy chỉnh để người dùng thấy nội dung hữu ích thay vì trang 502 trần của trình duyệt:
error_page 502 /502.html;
location = /502.html {
root /var/www/html;
internal;
}
Khi debug các vấn đề định tuyến giữa proxy và upstream — đặc biệt trong môi trường Docker nhiều network — công cụ tính subnet trên ToolCraft giúp nhanh chóng xác minh dải CIDR và xác nhận các host có thực sự cùng network segment hay không. Giải quyết được rất nhiều vấn đề kiểu "tại sao chúng không kết nối được với nhau".

