Infrastructure/docker/npm/README.md

59 lines
2.4 KiB
Markdown

# 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:
```nginx
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.