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

ItemCurrent approach
Host layerOMV / Docker
Imagejc21/nginx-proxy-manager:2.15.1
Main purposeReverse proxy, HTTPS certificates, service entry management
Public entryHTTP / HTTPS, with raw backend ports not directly exposed
Admin entryNPM Admin UI, which should be limited to trusted networks or additional protection
Persistent dataNPM 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/html

I 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

TypeCount
Proxy Hosts32
Certificates35
Access Lists1
Users1
Redirection Hosts1
Streams0

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:port

The 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

ItemRule
Force SSLEnabled by default for public services
Certificate renewalsConfirm automatic renewal works
WebSocket supportEnable only when the service needs real-time connections
HSTSDecide per service based on maturity and rollback needs
Admin UIDo 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

  1. Container starts successfully
  2. Admin UI login works
  3. Proxy host list is complete
  4. Certificates exist and are not expired
  5. Important services are reachable through HTTPS entry points
  6. 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