Research note · 23.07.2026

Một cổng 443.
Nhiều service.

Nginx Proxy Manager giữ domain và SSL ở edge; Nginx trong VM chỉ nhận HTTP qua mạng LAN. “Double Nginx” không phải vấn đề nếu mỗi lớp có một trách nhiệm rõ ràng.

Luồng đang chạy

HTTPS dừng ở NPM. Phần còn lại là HTTP private trong LAN.

Route thật của trang này: test.kikigaki.io.vn:443 → NPM → http://192.168.2.40:18081 → nginx:80.

Quan trọng: đây không phải NAT toàn cục 443 → 18081. NPM đọc hostname test.kikigaki.io.vn rồi chọn đúng backend. Các domain khác vẫn dùng chung public port 443 và đi tới backend khác.

Setup trên UI

Không có magic config. Không dùng Stream.

Tab Details PROXY HOST

Domain Names
test.kikigaki.io.vn
Scheme
http
Forward IP
192.168.2.40
Forward Port
18081
Access List
Publicly Accessible
Common Exploits
On
WebSockets
On nếu app cần
Cache Assets
Off mặc định

Tab SSL EDGE TLS

Certificate
test.kikigaki.io.vn
Force SSL
On
HTTP/2
On
HSTS
Off lúc lab; bật sau
Advanced
Để trống
VM certificate
Không cần
Stream
Không dùng
SSL passthrough
Không dùng

Nhiều service vẫn dùng 443

Hostname quyết định backend, không phải một port public riêng cho mỗi web app.

Public hostnameNPM forward nội bộVai trò
app.example.net:443192.168.2.40:3000Frontend
api.example.net:443192.168.2.40:8000API
admin.example.net:443192.168.2.41:8080Admin UI
test.kikigaki.io.vn:443192.168.2.40:18081Lab hiện tại
Router chỉ cần giữ WAN 80 → NPM:80WAN 443 → NPM:443. Không forward trực tiếp từng backend port ra Internet.

Nginx trong VM làm gì?

Nó phục vụ app nội bộ; NPM lo phần public edge.

01

Serve frontend hoặc static files

React/Vue build, landing page, media hoặc file tải xuống có thể được Nginx trong VM phục vụ trực tiếp.

02

Route các thành phần nội bộ

Ví dụ / tới frontend, /api/ tới backend và /media/ tới storage — tất cả nằm sau một backend port mà NPM nhìn thấy.

03

Chuyển tiếp đúng proxy headers

Giữ Host, chuỗi IP client và protocol HTTPS ban đầu để app sinh URL/cookie chính xác.

server {
    listen 18081;
    server_name test.kikigaki.io.vn;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $http_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Trong lab hiện tại, Docker bind trực tiếp 192.168.2.40:18081 → nginx container:80; không cần thêm server block vì container chỉ serve một trang tĩnh.

Biên an toàn

HTTP nội bộ chỉ hợp lý khi backend không bị public trực tiếp.

  • Bind service vào IP LAN cụ thể, ví dụ 192.168.2.40:18081, thay vì public wildcard nếu không cần.
  • Router không forward port backend; Internet chỉ thấy 80/443 của NPM.
  • Nếu dùng firewall, chỉ cho IP LAN của máy NPM truy cập port backend.
  • SSL certificate và renewal tập trung ở NPM; VM không giữ private key public.
  • Chỉ dùng HTTPS giữa NPM và VM khi LAN không đáng tin cậy hoặc có yêu cầu compliance/end-to-end encryption.

Lỗi thường gặp

Phần tốn não thường đến từ double TLS, không phải double Nginx.

Redirect loop

NPM gửi HTTP vào VM nhưng app cứ ép HTTPS dựa trên scheme cục bộ. Giải pháp: Force SSL ở NPM và để app tin X-Forwarded-Proto.

Mất IP client

Backend chỉ thấy IP NPM. Dùng X-Forwarded-For và chỉ trust đúng IP/subnet của reverse proxy.

Nhầm Proxy Host với Stream

Web HTTP/HTTPS dùng Proxy Host. Stream dành cho TCP/UDP như SSH, database hoặc protocol không phải HTTP.

Advanced Config quá sớm

Để trống trước. Chỉ thêm timeout, body size hoặc buffering khi app có yêu cầu cụ thể và đã có lỗi tái hiện.

Bằng chứng lab

Các kiểm tra đã chạy sau khi cấu hình.

301HTTP tự chuyển sang HTTPS
200HTTPS trả nội dung từ eonsr-1
LAN only192.168.2.40:18081; WireGuard port đóng
nginx -t ✓NPM config syntax hợp lệ

Quy tắc quyết định

Dùng cách đơn giản nhất phù hợp protocol.

Web app bình thường: DNS → NPM Proxy Host → HTTP LAN → app/Nginx VM. Raw TCP/UDP: cân nhắc Stream. mTLS hoặc TLS phải tới tận backend: mới cân nhắc SSL passthrough/end-to-end TLS.
# Công thức triển khai chuẩn
1. App/Nginx VM listen trên LAN_IP:PORT
2. DNS hostname trỏ về public IP của NPM
3. NPM → Add Proxy Host
4. Scheme=http, Forward=LAN_IP:PORT
5. Chọn/request certificate, bật Force SSL
6. Test HTTP 301, HTTPS 200, certificate và backend isolation