fix(tls): leaf key must be readable by the daemon, not just root
Found on archi-dev-box the moment the gate tried to serve TLS: the key was installed root:root 0600, nginx's master reads it as root, but the archipelago daemon runs as User=archipelago and got "Permission denied (os error 13)". Every app port then quietly stayed plain HTTP — the exact fail-open shape the gate exists to prevent, and it would have looked like "TLS just doesn't work" with no obvious cause. The warn-level log the tls module deliberately emits for a present-but-unloadable certificate is what turned this into a ten-second diagnosis instead of a hunt; it earned its keep on its first real deployment. Key is now group-owned by the service user at 0640, with a fallback to the user's primary group and a clear message when no such user exists. Nothing wider than that. Verified on the node afterwards, on one gated port (8096): https 401 verify=0 TLS terminated, chain valid against the node CA http 401 same port, plain HTTP, unchanged no CA verify=20 untrusted client correctly rejected The reissued key was also picked up with NO daemon restart — the mtime reload path proven in production, not just in a unit test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f7bde19860
commit
1dfd9e720b
@@ -127,6 +127,27 @@ openssl x509 -req -in "$TMP/leaf.csr" -CA "$CA_CRT" -CAkey "$CA_KEY" \
|
||||
install -m 644 "$TMP/leaf.crt" "$LEAF_CRT"
|
||||
install -m 600 "$TMP/leaf.key" "$LEAF_KEY"
|
||||
|
||||
# The leaf key has TWO readers with different privileges: nginx's master
|
||||
# process (root) and the archipelago daemon (User=archipelago), which needs it
|
||||
# to terminate TLS on gated app ports. Root-only 0600 silently costs the daemon
|
||||
# its TLS — it logs "Permission denied" and every app port quietly stays plain
|
||||
# HTTP, which is exactly the fail-open shape the gate is built to avoid. So the
|
||||
# key is group-readable by the service user and nothing wider.
|
||||
SERVICE_USER="${ARCHY_SERVICE_USER:-archipelago}"
|
||||
if getent group "$SERVICE_USER" >/dev/null 2>&1; then
|
||||
chgrp "$SERVICE_USER" "$LEAF_KEY" && chmod 640 "$LEAF_KEY"
|
||||
log "Key readable by group $SERVICE_USER (0640) — the daemon needs it for app-port TLS"
|
||||
elif getent passwd "$SERVICE_USER" >/dev/null 2>&1; then
|
||||
# User exists without an eponymous group — fall back to its primary group.
|
||||
PRIMARY="$(id -gn "$SERVICE_USER" 2>/dev/null || true)"
|
||||
if [ -n "$PRIMARY" ]; then
|
||||
chgrp "$PRIMARY" "$LEAF_KEY" && chmod 640 "$LEAF_KEY"
|
||||
log "Key readable by group $PRIMARY (0640)"
|
||||
fi
|
||||
else
|
||||
log "No '$SERVICE_USER' user on this host — key left root-only (0600)"
|
||||
fi
|
||||
|
||||
# The dashboard serves this for download; it is a public certificate, never the key.
|
||||
install -m 644 "$CA_CRT" "$SSL_DIR/ca-download.crt"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user