Infrastructure/docker/npm
2026-10-04 21:09:00 +02:00
..
compose.yaml Introduces Optiplex to the home setup. Install the first software. Introduce management vlan 99 2026-10-04 21:09:00 +02:00
README.md Introduces Optiplex to the home setup. Install the first software. Introduce management vlan 99 2026-10-04 21:09:00 +02:00

Nginx Proxy Manager

Runs on the OptiPlex homeserver (192.168.30.20) in ~/npm. Admin UI: http://192.168.30.20:81 (not proxied yet).

Every service gets a name through two entries: a Pi-hole Local DNS record pointing <name>.home.staffenberger.at at 192.168.30.20, and an NPM proxy host forwarding to the real address and port.

Proxy hosts

Name Scheme Forward to Extras
pihole.home.staffenberger.at http 192.168.30.20:8081 Advanced: redirect / to /admin/
omada.home.staffenberger.at https 192.168.30.20:8043 Websockets on
ha.home.staffenberger.at http 192.168.30.20:8123 Websockets on
octoprint.home.staffenberger.at http OctoPrint Pi, port 80 Websockets on

All hosts use the wildcard certificate with Force SSL and HTTP/2 on; HSTS is off for now.

Wildcard certificate

Let's Encrypt certificate for *.home.staffenberger.at, issued and renewed by NPM via a DNS challenge at INWX (the names point at internal addresses, so an HTTP challenge can't work, and wildcards need DNS validation anyway).

Add Certificate → Let's Encrypt via DNS → provider INWX, key type ECDSA 256, propagation 120 seconds:

dns_inwx_url = https://api.domrobot.com/xmlrpc/
dns_inwx_username = <sub-user>
dns_inwx_password = """<password>"""
  • Uses a dedicated INWX sub-user with minimal rights and no 2FA. NPM stores the password in plain text in its database and credentials file, so ./data and ./letsencrypt are secrets — never commit them, and encrypt any backup.
  • Covers exactly one level below home.staffenberger.at; nothing outside *.home is affected.
  • If it leaks: change the sub-user's password at INWX and update it in NPM.
  • Alternative considered: acme-dns via a CNAME on _acme-challenge.home, limiting the credential to a single TXT record. Possible later, ideally self-hosted on the git server.

Lessons learned

  • The Forward Hostname field takes only an IP or host name, never a path. A path there caused a proxy loop (414 Request-URI Too Large).

  • The Advanced tab is the gear icon at the top right of the proxy host dialog. Redirect used for Pi-hole:

    location = / {
        return 301 /admin/;
    }
    
  • For large OctoPrint uploads, add client_max_body_size 0; in the Advanced tab if needed.

  • No MariaDB container — NPM's built-in SQLite is enough at this scale.