NPM » History » Version 2
Redmine Admin, 10/26/2026 02:24 AM
deploy-publish.sh
| 1 | 2 | Redmine Admin | Unit: `nginx-proxy-manager.container`. Published on **host 81 → 80, 444 → 443** |
|---|---|---|---|
| 2 | (rootless can't bind <1024); admin UI on **:8181**, reachable only from the |
||
| 3 | subnets allowed by firewalld rich rules (`firewall-cmd --list-rich-rules`, root): |
||
| 4 | 10.202.10.0/24 (VB21 = home LAN, own FortiGate, S2S to HQ), 192.168.100.0/24 |
||
| 5 | (MDS-HQ office LAN), 172.16.103.0/24 (the host's own DMZ segment). Deliberately NOT the SSL-VPN pool (10.21.0.0/24): the |
||
| 6 | host rule must not depend on who the FortiGate let onto the VPN; from the road use |
||
| 7 | the SSH tunnel. A new admin subnet = one more rich rule |
||
| 8 | (`--permanent --add-rich-rule='rule family=ipv4 source address=<net>/24 port port=8181 protocol=tcp accept'` + `--reload`). |
||
| 9 | Fallback from anywhere SSH works: `ssh -L 8181:127.0.0.1:8181 root@dmz-web` → `http://localhost:8181`. |
||
| 10 | The FortiGate VIP |
||
| 11 | does the public **443 → 444** translation. No hairpin NAT, so from inside the |
||
| 12 | public names resolve to the WAN IP and don't work — see [[Health Check]]. |
||
| 13 | 1 | Redmine Admin | |
| 14 | 2 | Redmine Admin | NPM must be a member of every site's network to reach `site-<name>:80` by |
| 15 | container name. Each new site adds three lines to the unit, above the |
||
| 16 | `# --- next site: …` marker comments (`add-wordpress-site.sh` does this |
||
| 17 | 1 | Redmine Admin | automatically; for Redmine/Snipe-IT do it by hand): |
| 18 | |||
| 19 | 2 | Redmine Admin | ```ini |
| 20 | 1 | Redmine Admin | [Unit] |
| 21 | After=net-<name>-network.service |
||
| 22 | Requires=net-<name>-network.service |
||
| 23 | [Container] |
||
| 24 | Network=net-<name>.network |
||
| 25 | ``` |
||
| 26 | |||
| 27 | then `cp` to `~/.config/containers/systemd/`, `daemon-reload`, `restart nginx-proxy-manager.service`. |
||
| 28 | |||
| 29 | 2 | Redmine Admin | **Before any `cp` of this unit: the repo copy must contain every `Network=` line |
| 30 | the live copy has.** On 2026-10-25 `snipeit-install.sh` copied a repo version that |
||
| 31 | only knew `net-snipeit` over the live unit → NPM left the other three networks → |
||
| 32 | every site 502 until the lines were re-added. Check with |
||
| 33 | `diff <(grep '^Network=' ~/.config/containers/systemd/nginx-proxy-manager.container) <(grep '^Network=' ~/deploy/quadlet/nginx-proxy-manager.container)` |
||
| 34 | (empty = safe). Restarting NPM drops every site for ~10–20 s — all three install scripts do it. |
||
| 35 | 1 | Redmine Admin | |
| 36 | 2 | Redmine Admin | Proxy host (UI or API): Domain `<domain>` → scheme http, Forward Hostname |
| 37 | `site-<name>`, Forward Port 80 (Redmine: 3000), Block Common Exploits, |
||
| 38 | Websockets; SSL tab → Let's Encrypt, Force SSL, HTTP/2. |
||
| 39 | LE needs DNS A record + FortiGate VIP live first (HTTP-01 challenge comes in |
||
| 40 | over 80 → 81). The LE contact email is the NPM *user account's* email, not a |
||
| 41 | 1 | Redmine Admin | per-cert setting. |
| 42 | |||
| 43 | 2 | Redmine Admin | API credentials are Podman secrets `npm-admin-identity` / `npm-admin-secret`. |
| 44 | 1 | Redmine Admin | Quick API test: |
| 45 | |||
| 46 | 2 | Redmine Admin | ```bash |
| 47 | 1 | Redmine Admin | curl -s http://localhost:8181/api/ | head -c 200 |
| 48 | podman network inspect net-<name> | jq '.[0].containers | keys' # must list nginx-proxy-manager |
||
| 49 | ``` |
||
| 50 | |||
| 51 | 2 | Redmine Admin | Restrict an internal-only app (Snipe-IT, Redmine admin): NPM **Access List** |
| 52 | 1 | Redmine Admin | with the VPN/office ranges attached to that proxy host. |
| 53 | |||
| 54 | --- |
||
| 55 | 2 | Redmine Admin | _Source: `dmz-web-podman-cheatsheet.md` v1.2 in the `dmz-web-deploy` repo ([[Releases]]). Edit the wiki and the repo copy together._ |