Nginx Proxy Manager
๐ก Quick Navigation
Nginx Proxy Manager is the reverse-proxy entry point for my Home Lab. Almost every service that needs browser or external access goes through NPM first, then gets routed to the actual backend service.
I treat it as the front desk of the whole Home Lab: users remember domains and HTTPS entry points, not which machine or port each service is running on.
๐ฏ Why I Use It
Once there are many services, IP:Port does not scale
With only a few services, typing IP:Port is acceptable. After the service count grows, that approach gets messy quickly:
- Every service has a different port, which is hard to remember and hard to share with family
- HTTPS certificates become scattered and harder to troubleshoot
- Too many external entry points make firewall and security boundaries unclear
- When services move hosts or ports, clients also need to change
NPM turns those problems into one entry layer. Backend services can move or change ports, while users keep using the same domain.
The UI is practical enough
I use NPM not because it is the most powerful reverse proxy, but because it is practical. Proxy Hosts, SSL certificates, Access Lists, and custom Nginx snippets can all be managed through a Web UI, which saves time during daily operations.
๐งฑ Role in the Home Lab
flowchart TD U[Users / Browser / App] --> DNS[DNS / Subdomain] DNS --> NPM[Nginx Proxy Manager<br/>OMV / Docker] NPM --> HA[Home Assistant] NPM --> IMM[Immich] NPM --> QZ[Quartz Blog] NPM --> BW[Bitwarden] NPM --> OTHER[Other Services] NPM --> AUTH[Authelia<br/>Forward Auth]
NPM lives in the App Layer and runs on OMV with Docker. It does not hold the core application data, but it is the entry layer. If it fails, many backend services may still be running, yet users will experience them as unavailable.
Current status summary
| Item | Current approach |
|---|---|
| Host layer | OMV / Docker |
| Image | jc21/nginx-proxy-manager:2.15.1 |
| Main purpose | Reverse proxy, HTTPS certificates, service entry management |
| Public entry | HTTP / HTTPS, with raw backend ports not directly exposed |
| Admin entry | NPM Admin UI, which should be limited to trusted networks or additional protection |
| Persistent data | NPM app data, Letโs Encrypt certificates, web root / challenge data |
Warning
NPM is the entry layer, not the only security boundary. Public services still need proper app permissions, login protection, updates, and backup strategy.
๐ณ Deployment Summary
The deployment uses Docker Compose. The core shape is:
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:2.15.1
restart: unless-stopped
ports:
- "<http-port>:80"
- "<https-port>:443"
- "<admin-port>:81"
volumes:
- <npm-data>:/data
- <letsencrypt-data>:/etc/letsencrypt
- <web-root>:/var/www/htmlI do not publish real domains, internal IP addresses, static Docker addresses, or admin ports. Those belong in private configuration and backups.
Current NPM data size
| Type | Count |
|---|---|
| Proxy Hosts | 32 |
| Certificates | 35 |
| Access Lists | 1 |
| Users | 1 |
| Redirection Hosts | 1 |
| Streams | 0 |
This means NPM is no longer a small helper for one service. It is shared infrastructure for the whole Home Lab, so its backup and restore priority should be close to other core infrastructure services.
๐ Proxy Host Model
Each service is modeled as a Proxy Host:
service.example.com -> internal-service:portThe public note keeps only the pattern, not real domains or internal addresses.
Naming rules I follow
- Give each service one stable primary subdomain
- Keep admin entry points and user-facing entry points separate when possible
- Avoid temporary names becoming permanent public entry points
- When a service moves, update the NPM upstream first instead of changing the user-facing URL
- Add clear notes for important services so old proxy hosts are easier to audit later
Why not expose raw service ports directly
Exposing every service port scatters the entry points and makes security rules harder to manage. NPM centralizes external traffic into a small set of fixed ports, then lets each proxy host decide where traffic should go.
๐ HTTPS and Certificate Strategy
NPM manages Letโs Encrypt certificates centrally. Most proxy hosts use SSL and force HTTP to HTTPS.
Things I check
| Item | Rule |
|---|---|
| Force SSL | Enabled by default for public services |
| Certificate renewals | Confirm automatic renewal works |
| WebSocket support | Enable only when the service needs real-time connections |
| HSTS | Decide per service based on maturity and rollback needs |
| Admin UI | Do not expose directly to untrusted networks |
Centralized certificates reduce operations overhead. Instead of troubleshooting TLS in every individual service, most HTTPS issues can start with the NPM proxy host and certificate state.
๐ก๏ธ Split with Authelia
NPM handles entry and routing. Authelia handles identity and access control.
sequenceDiagram participant User as User participant NPM as Nginx Proxy Manager participant Auth as Authelia participant App as Backend Service User->>NPM: Request protected service NPM->>Auth: Forward-auth check Auth-->>NPM: Allow / deny NPM->>App: Proxy request if allowed App-->>User: Response through NPM
Several proxy hosts currently use Authelia forward-auth. These services are not protected only by their own login page; they pass through centralized authentication before reaching the backend.
Responsibility split
- NPM: domain, TLS, proxying, headers, WebSocket, upstream routing
- Authelia: login, 2FA, access-control policy
- Backend services: keep their own permissions and do not assume the outer layer is always perfect
Important
Reverse proxy and forward-auth are part of the defense, not a maintenance-free guarantee. Backend services still need updates, strong passwords, unnecessary features disabled, and limited exposure.
๐พ Backup and Restore
NPM does not store a lot of data, but the data is important. The key things to protect are:
- NPM app data: proxy hosts, users, access lists, and the application database
- Letโs Encrypt data: certificates and renewal state
- Web root / challenge data: certificate validation and static challenge files
- Docker Compose /
.env: startup method and mount paths
Restore checklist
- Container starts successfully
- Admin UI login works
- Proxy host list is complete
- Certificates exist and are not expired
- Important services are reachable through HTTPS entry points
- Authelia-protected services still complete forward-auth correctly
A successful NPM restore does not prove every backend service is healthy, but it quickly confirms whether the entry layer is back.
โ ๏ธ Pitfalls and Operations Principles
Plan naming rules early
I did not fully plan subdomain naming at the beginning, and the service list became harder to manage as it grew. Reverse proxy is not something to bolt on at the end; it should be part of the service launch process.
Leave intent on every Proxy Host
Once there are many proxy hosts, the worst state is not knowing which ones are still used. When adding a service, I try to record:
- Who this entry point is for
- Which layer the backend service lives on
- Whether WebSocket is needed
- Whether Authelia is needed
- Whether the entry can be disabled or deleted later
Upgrade the entry layer conservatively
NPM is not hard to update, but its blast radius is large. Before upgrading, I confirm backups. After upgrading, I test the most common and most important service entry points first.
Conclusion
Nginx Proxy Manager is important infrastructure in this Home Lab. It centralizes service entry points, manages HTTPS certificates, and lets backend services move or rebuild without changing user-facing URLs.
It looks like a Web UI for Nginx, but in practice it is the front door for the whole stack. If a service needs to be reliably used by me or my family, NPM is not optional glue; it is a core component that needs backups, monitoring, and careful upgrades.
Further reading: Home Lab Overview, OpenMediaVault, Authelia