fiber optic network

Nginx Reverse Proxy สำหรับ Node.js และ Python บน VPS

มิถุนายน 2026 · อ่าน 6 นาที

แอปพลิเคชัน Node.js, Python Flask/Django หรือ Go ส่วนใหญ่รันบน port สูง เช่น 3000 หรือ 8000 ซึ่งผู้ใช้ต้องพิมพ์ port ในชื่อโดเมน Nginx Reverse Proxy แก้ปัญหานี้โดยรับ request จาก port 80/443 แล้วส่งต่อไปยังแอป


Reverse Proxy คืออะไร

Reverse Proxy ทำหน้าที่เป็นตัวกลางระหว่าง client กับ backend application:

ผลคือ client เห็นแค่ https://myapp.com ไม่รู้ว่า backend รันบน port อะไร

Config พื้นฐาน: Node.js บน port 3000

สร้างไฟล์ /etc/nginx/sites-available/myapp:

server {
    listen 80;
    server_name myapp.com www.myapp.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name myapp.com www.myapp.com;

    ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;

    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_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_cache_bypass $http_upgrade;
    }
}
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Config สำหรับ Python Gunicorn

Python app (Flask/Django) มักรันผ่าน Gunicorn บน Unix socket ซึ่งเร็วกว่า TCP port:

location / {
    proxy_pass http://unix:/run/gunicorn/myapp.sock;
    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;
}

รัน Multiple Apps บน Domain เดียว

สามารถแยก path ไปยังหลาย backend ได้:

server {
    listen 443 ssl;
    server_name myapp.com;

    # Frontend React บน port 3000
    location / {
        proxy_pass http://127.0.0.1:3000;
    }

    # API Node.js บน port 4000
    location /api/ {
        proxy_pass http://127.0.0.1:4000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Static files serve โดย Nginx โดยตรง
    location /static/ {
        alias /var/www/myapp/static/;
        expires 30d;
    }
}

Timeout Settings สำหรับแอปที่ประมวลผลนาน

proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

ถ้าแอปทำงานนานกว่า 60 วินาที (เช่น video processing) ต้องเพิ่มค่านี้ ไม่งั้น Nginx จะ timeout ก่อน


Header ที่สำคัญสำหรับ IP Logging

แอปที่ต้องการ IP จริงของ client ต้องอ่านจาก X-Real-IP หรือ X-Forwarded-For แทน เพราะ Nginx เป็นตัวที่เชื่อมต่อกับ backend ไม่ใช่ client โดยตรง


สรุป

Nginx Reverse Proxy คือ pattern มาตรฐานสำหรับ deploy web application บน VPS รวม SSL, compression, static file caching และ load balancing ไว้ในจุดเดียว โดยที่ application ไม่ต้องรู้เรื่องเหล่านี้เลย

ตรวจสอบว่า Reverse Proxy ทำงานถูกต้อง

# ทดสอบ config ก่อน reload
nginx -t

# reload config
systemctl reload nginx

# ตรวจว่า request ถูก proxy ไปถูกต้อง
curl -I https://myapp.com
# ดู header X-Powered-By หรือ Server เพื่อยืนยัน backend

# ตรวจ error log
tail -f /var/log/nginx/error.log
Debug X-Forwarded-For: ถ้า backend แสดง IP ของ Nginx (127.0.0.1) แทน client IP จริง ตรวจว่า app อ่าน header X-Forwarded-For หรือ X-Real-IP ถูกต้อง

แก้ปัญหาที่พบบ่อย

Error: "502 Bad Gateway"

Backend app ไม่ได้รัน หรือ port/socket ไม่ตรง:

# ตรวจว่า app รันอยู่ไหม
ss -tlnp | grep :3000  # Node.js บน port 3000
ps aux | grep node

# ทดสอบ connect ตรงโดยไม่ผ่าน Nginx
curl http://127.0.0.1:3000

# ดู error log
tail -50 /var/log/nginx/error.log

Error: "504 Gateway Timeout"

Backend ตอบกลับช้าเกิน proxy timeout ที่ตั้ง (default 60s):

# เพิ่ม timeout ใน nginx config
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;

nginx -t && systemctl reload nginx

Error: "413 Request Entity Too Large" ตอน upload ไฟล์

# เพิ่มใน server block หรือ location
client_max_body_size 50M;

nginx -t && systemctl reload nginx

WebSocket connection ถูกตัดทุก 60 วินาที

Nginx ต้องตั้ง Connection upgrade สำหรับ WebSocket โดยเฉพาะ:

location /ws/ {
    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_read_timeout 3600s;  # ไม่ timeout
}

SSL certificate error หลัง renew Certbot

# ทดสอบ renew
certbot renew --dry-run

# reload nginx หลัง renew
systemctl reload nginx

# ตรวจ cert expiry
echo | openssl s_client -connect myapp.com:443 2>/dev/null | openssl x509 -noout -dates

คำถามที่พบบ่อย

หลาย domain ชี้ไป app เดียวได้ไหม?

ได้ ตั้ง server_name domain1.com www.domain1.com domain2.com รวมกันใน server block เดียว หรือสร้างหลาย server block แยกกัน แต่ละตัว proxy ไป backend เดิม

จะรู้ได้ยังไงว่า Nginx proxy ไปถูก backend?

ดู $upstream_addr ใน access log หรือเพิ่ม header debug ชั่วคราว add_header X-Debug-Upstream $upstream_addr; แล้วดู response header ด้วย curl

Nginx และ Apache รันบนเครื่องเดียวกันได้ไหม?

ได้ ให้ Nginx ฟัง port 80/443 และ Apache ฟัง port 8080 Nginx รับ request แล้ว proxy ไป Apache ที่อยู่หลัง ทำให้ได้ประโยชน์ทั้งสองอย่าง