Files
archipelago e382e679ae fix(apps): NPM needs /etc/letsencrypt mounted and NET_BIND_SERVICE
Converting Nginx Proxy Manager to a platform manifest (fc68c5b6) dropped
two things its image hard-requires, and the result was an endless
start/die loop — shorty-s watched it restart 3,176 times:

1. /etc/letsencrypt mount: NPM's s6 'prepare' service refuses to boot
   without it ('ERROR: /etc/letsencrypt is not mounted!'). Mounted from
   the same persistent app directory as before
   (/var/lib/archipelago/nginx-proxy-manager/letsencrypt), so existing
   certificates are preserved — no data moves, no migration.

2. NET_BIND_SERVICE: NPM's internal nginx listens on 80, 443 AND 81,
   and the orchestrator runs --cap-drop=ALL. The legacy podman-run path
   defaulted to the full capability set (and the legacy repair path in
   package/config.rs always listed it), which is why this only broke
   once the manifest became the source of truth.

The signed catalog embeds manifests with origin-wins semantics, so the
catalog carries the fix for every catalog-covered node — regenerate it
here (plus the generated store/launcher-port artifacts, which also pick
up drift from bf6ef964's retired apps). Catalog re-signing follows the
usual ceremony.
2026-09-01 10:29:05 -04:00

89 lines
2.7 KiB
YAML

app:
id: nginx-proxy-manager
name: Nginx Proxy Manager
version: 2.12.1
upstream:
kind: github
repo: NginxProxyManager/nginx-proxy-manager
description: >-
Reverse proxy with SSL. Beautiful web interface for managing proxies.
On a node, this manages its admin UI and upstream configuration — the
proxy's own :80/:443 listeners are not published (the node's web server
owns those ports).
container:
image: source.archipelago-foundation.org/lfg2025/nginx-proxy-manager:latest
pull_policy: if-not-present
network: pasta
dependencies:
- storage: 1Gi
resources:
memory_limit: 512Mi
disk_limit: 1Gi
security:
# NET_BIND_SERVICE is load-bearing, not decoration: NPM's internal nginx
# listens on 80, 443 AND 81, and the orchestrator runs --cap-drop=ALL —
# without this cap every start dies with "bind() to 0.0.0.0:80 failed
# (13: Permission denied)" and s6 restart-loops forever (shorty-s,
# 2026-09-01, restart counter 3176 within hours of the manifest
# conversion). The legacy podman-run path defaulted to the full cap set,
# which is why it never showed there.
capabilities: [CHOWN, SETUID, SETGID, DAC_OVERRIDE, NET_BIND_SERVICE]
readonly_root: false
no_new_privileges: true
network_policy: isolated
ports:
- host: 8081
container: 81
protocol: tcp
bind: 127.0.0.1
# open, not gated: NPM carries a complete admin login of its own. The
# gate still fronts the port (TLS on the same port, header fixes, retry
# page, Tor) without putting a cookie challenge in front of it.
auth: open
auth_rationale: >-
Nginx Proxy Manager enforces its own admin account on every page;
the initial setup wizard also has to answer before any account exists.
volumes:
- type: bind
source: /var/lib/archipelago/nginx-proxy-manager
target: /data
options: [rw]
# Current NPM images refuse to start unless /etc/letsencrypt is a mount in
# its own right. Keeping the files below the same persistent app directory
# preserves existing certificates while satisfying that startup contract.
- type: bind
source: /var/lib/archipelago/nginx-proxy-manager/letsencrypt
target: /etc/letsencrypt
options: [rw]
environment: []
health_check:
type: tcp
endpoint: localhost:81
interval: 30s
timeout: 5s
retries: 3
interfaces:
main:
name: Admin UI
description: Nginx Proxy Manager admin interface
type: ui
port: 8081
protocol: http
path: /
metadata:
author: Nginx Proxy Manager
category: networking
icon: /assets/img/app-icons/nginx.svg
repo: https://github.com/NginxProxyManager/nginx-proxy-manager
tier: optional