Public exposure via NGINX Proxy Manager + Cloudflare tunnel #13

Closed
opened 2026-07-12 20:11:04 -06:00 by jhodgkin · 1 comment
Owner

Add an NPM proxy host (CT102) routing to CT122, and a Cloudflare tunnel route (CT110), matching how other public services are exposed. Needs either NPM/Cloudflare API credentials or the user to add these manually via their dashboards. Should land after local auth is solid and ideally after OIDC (#12).

Add an NPM proxy host (CT102) routing to CT122, and a Cloudflare tunnel route (CT110), matching how other public services are exposed. Needs either NPM/Cloudflare API credentials or the user to add these manually via their dashboards. Should land after local auth is solid and ideally after OIDC (#12).
Author
Owner

Done. https://monitor.jerodrigged.com is live: Cloudflare tunnel (existing tunnel, new Public Hostname added by the user) → NPM proxy host (id 14) → dashboard, Let's Encrypt cert issued via NPM's API.

Hit one real bug: initially set ssl_forced: true on the NPM proxy host (matching a security instinct, not the established pattern) and got an infinite redirect loop — Cloudflare is in Flexible SSL mode, so it terminates TLS at its edge and talks plain HTTP to the tunnel origin. ssl_forced: true made NPM 301 every one of those plain-HTTP requests back to https, which just looped forever through Cloudflare. Fixed by setting it back to false, matching every other existing proxy host's config — should've checked the established pattern more carefully before deviating. Documented clearly in CLAUDE.md so it isn't "fixed" by accident later.

Also registered both the public and LAN OIDC redirect URIs in Authentik and switched .env to the public one as primary. Verified end-to-end over the public URL: local login works, /api/hosts returns real data, and the OIDC redirect chain builds with correct params (final interactive Authentik login click-through still needs a human, noted in CLAUDE.md).

Done. `https://monitor.jerodrigged.com` is live: Cloudflare tunnel (existing tunnel, new Public Hostname added by the user) → NPM proxy host (id 14) → dashboard, Let's Encrypt cert issued via NPM's API. Hit one real bug: initially set `ssl_forced: true` on the NPM proxy host (matching a security instinct, not the established pattern) and got an infinite redirect loop — Cloudflare is in Flexible SSL mode, so it terminates TLS at its edge and talks plain HTTP to the tunnel origin. `ssl_forced: true` made NPM 301 every one of those plain-HTTP requests back to https, which just looped forever through Cloudflare. Fixed by setting it back to `false`, matching every other existing proxy host's config — should've checked the established pattern more carefully before deviating. Documented clearly in CLAUDE.md so it isn't "fixed" by accident later. Also registered both the public and LAN OIDC redirect URIs in Authentik and switched `.env` to the public one as primary. Verified end-to-end over the public URL: local login works, `/api/hosts` returns real data, and the OIDC redirect chain builds with correct params (final interactive Authentik login click-through still needs a human, noted in CLAUDE.md).
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jhodgkin/homelab-monitor#13