Build docker image and push to registry.bitdeals.org / main-build-job (push) Successful in 36s
The placeholder is the whole reason a first start works at all: HAProxy resolves `bind ... ssl crt` while parsing its configuration, so it cannot start without site.pem, and certbot writes a self-signed one to break that circle. It wrote it 0600 root-only, under the umask the subshell sets for the private key it builds it from. HAProxy runs unprivileged (uid 1001 in the bitnami image), so it could not open the file and exited -- and because it never came up, it never created the runtime API socket the pass waits for, and the pass hung in that wait instead of reaching the 12-hour sleep. A node whose first issuance failed -- a typo in CERTBOT_DOMAIN is enough -- served nothing at all on 80 or 443, retried nothing, and said so only in two container logs. The real certificate escapes this by accident: 2-concatenate-cert.sh writes it with `cat >` under the default umask, so site.pem is 0644 on every node that ever issued one. That is why nobody hit this -- it needs a first issuance that fails. chmod on the temporary file rather than after the rename, so the atomic rename stays the only thing HAProxy can observe and site.pem never exists with a mode that stops it. The intermediates keep the tight umask. Reproduced on a disposable haproxy+certbot stack with empty volumes and CERTBOT_DOMAIN=testnet2.bitdeals.invalid: before, HAProxy crash-looped on "cannot open the file" while certbot waited for admin.sock; after, HAProxy starts on the placeholder, certbot reports the rejected domain, the loop retries in 12h, and the site answers on 80 and terminates TLS on 443 with the self-signed certificate. Claude-Session: https://claude.ai/code/session_01BvgYcYPWd1KGABLKViVPSk