name: Reload Caddy description: >- Reload the host Caddy service from a DooD job container via a privileged sibling container and nsenter. No inputs. runs: using: composite steps: - name: Reload Caddy shell: bash # Apply any committed Caddyfile changes before smoke-testing the # public surface. Without this step, a Caddyfile edit lands in the # repo but Caddy keeps serving the previous config until someone # reloads it manually — the smoke test would then catch a stale # header or a still-proxied /actuator route rather than confirming # the current config is live. # # The runner executes job steps inside Docker containers (DooD). # `systemctl` is not present in container images and cannot reach # the host's systemd directly. We use the Docker socket (mounted # into every job container via runner-config.yaml) to spin up a # privileged sibling container in the host PID namespace; nsenter # then enters the host's namespaces so systemctl talks to the real # host systemd daemon. No sudoers entry is required — the Docker # socket already grants root-equivalent host access. # # Alpine is used: ~5 MB vs ~70 MB for ubuntu, no unnecessary # tooling, and the digest is pinned so any upstream change requires # an explicit bump PR. util-linux (which ships nsenter) is installed # at run time; apk add takes ~1 s on the warm VPS cache. # # `reload` not `restart`: reload sends SIGHUP so Caddy re-reads its # config in-process without dropping TLS connections. `restart` # would briefly stop the service, losing in-flight requests. # # If Caddy is not running this step fails fast before the smoke test # issues a misleading "port 443 refused" error. run: | docker run --rm --privileged --pid=host \ alpine:3.21@sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d \ sh -c 'apk add --no-cache util-linux -q && nsenter -t 1 -m -u -n -p -i -- /bin/systemctl reload caddy'