Skip to content

NGINX Proxy Manager

NPM (NGINX Proxy Manager) runs on TrueNAS @ 192.168.2.203. It terminates HTTP on the LAN, maps hostnames to backend containers, and can issue Let's Encrypt certs for internal or legacy setups.

Post–Cloudflare Tunnel era, most public traffic hits *.saxobroko.com at the Cloudflare edge and tunnels straight to app ports. NPM is still useful but no longer the only front door.

Role today (tunnel era)

Before (CGNAT workaround):  Internet → Cloudflare DNS → NPM → app
Now (typical):              Internet → Cloudflare Tunnel → app (direct port or Docker hostname)
Still valid:                LAN client → NPM → pretty hostname / TLS / path rules → app
NPM still helps with… Tunnel-only is enough when…
One LAN hostname for many backends (npm.lan → multiple proxy hosts) Each app has its own tunnel public hostname
WebSocket/path tweaks in one UI App works with default tunnel → http://192.168.2.203:port
Local TLS (HTTPS on LAN without trusting raw ports) You only need HTTPS on public URL (Cloudflare handles edge SSL)
Legacy CNAME → local.saxobroko.com services Everything migrated to tunnel hostnames

See Network for the current public URL list.

When to use NPM vs direct tunnel

Use Cloudflare Tunnel directly to the app when:

  • Adding a new public subdomain (e.g. newapp.saxobroko.comhttp://192.168.2.203:8080)
  • WebSockets and headers work without extra proxy config
  • You do not need path-based routing (/api → different container)

Put NPM in the path when:

  • Tunnel points at NPM once (http://192.168.2.203:81 or container name) and NPM splits hostnames internally
  • You want consistent LAN URLs matching public names (same cert/hostname on .lan or hosts file)
  • You need custom locations, large header buffers, or quick host changes without editing tunnel config

Current homelab trend: tunnels direct to services; NPM retained for LAN convenience and any hosts not yet migrated.

LAN admin access

NPM admin UI is LAN-first — do not expose the admin port to the public internet without Access/WAF.

  1. On home network (PC @ 192.168.2.200 or Wi‑Fi on 192.168.2.0/24)
  2. Open admin URL — historically http://192.168.2.203:6081 or port shown in TrueNAS Apps → NPM
  3. Log in with credentials from Vaultwarden

From Windows, bookmark the LAN admin URL; no need to go through Cloudflare for day-to-day proxy edits.

Admin tasks

Task NPM section
Add internal site Hosts → Proxy Hosts → Add
TLS for LAN hostname SSL tab → Let's Encrypt or custom cert
Redirect HTTP → HTTPS Proxy host SSL + force SSL
Default catch-all Redirection Hosts or custom 404 host

How to add a proxy host (LAN or legacy public)

  1. Hosts → Proxy Hosts → Add Proxy Host
  2. Domain names — e.g. jellyfin.lan or legacy public name
  3. Forward hostname / IP — Docker service name on TrueNAS network or 192.168.2.203
  4. Forward port — app port (Jellyfin, Navidrome, etc.)
  5. Enable Block Common Exploits
  6. Enable Websockets Support for Jellyfin, Navidrome, Sonarr, Radarr, qBittorrent Web UI, etc.
  7. SSL — request cert if this hostname resolves to your LAN or tunnel terminates at NPM

Proxy Hosts

Add proxy host

For new public sites, prefer adding the hostname in Cloudflare Tunnel first — see Cloudflare and Network. Use NPM only if the tunnel targets NPM instead of the app.

Relationship to Cloudflare

Piece Role
Cloudflare DNS *.saxobroko.com records
Cloudflare Tunnel Inbound from internet without port forward (CGNAT)
NPM Optional middle tier on LAN
WAF (block no aus) Cloudflare edge — independent of NPM

Tunnel config example (conceptual): stream.saxobroko.comhttp://192.168.2.203:<jellyfin-port> orhttp://npm:81 with NPM proxy host for that domain.

Document which hostnames still chain through NPM when you change tunnel entries.

Credentials and secrets

  • NPM admin login → Vaultwarden
  • Let's Encrypt email and DNS challenge tokens (if used) → env or Vaultwarden, not SaxDocs

Troubleshooting

Symptom Check
502 Bad Gateway Backend container down; wrong IP/port in proxy host
WebSocket fails (Jellyfin sync) Websockets Support enabled on proxy host
Works on LAN, public broken Tunnel hostname points to wrong port — fix in Cloudflare, not NPM
SSL errors on LAN Cert domain mismatch; use LAN DNS name matching cert