caddy + pihole: make both boot-persistent and self-healing
Caddy left compose.yaml for a quadlet unit (caddy.service): joins dankclaw_default for container-name upstreams, Pull=never for the local-only image, Porkbun credentials via /home/dank/Containers/caddy/env written by deploy from .env, bare-IP-catch-all health check. deploy_caddy installs, enables, and starts the unit after retiring the bare container (state is in host volumes). Pi-hole: the repo now owns the sysctl drop-in (dankclaw/pihole/sysctl/99-dnsmasq.conf, ip_unprivileged_port_start=53); deploy_pihole installs it to /etc/sysctl.d/, stages conflicting later-sorted drop-ins in the home trash, and applies 'sysctl --system' (the boot code path). This fixes the 2026-08-26 crash loop (port-53 bind denied, restart counter 1645) caused by a second drop-in resetting the value to 80. Tests: new caddy_quadlet.bats seam; caddyfile/deployment_flow assertions repointed from the removed compose service to the quadlet; pihole.bats pins the sysctl drop-in and its deployment; test-changed.sh routes dankclaw/caddy/ and the pihole subtree to their seams. Docs: Caddy, Pi-hole, Dankclaw Stack, work log.
This commit is contained in:
1 parent
66b58a127b
commit
8660209c35
14 files changed
+248
-60
No files matched your search
@@ -0,0 +1,7 @@
|
||||
# Caddy environment (placeholders only). The deploy writes the live file at
|
||||
# /home/dank/Containers/caddy/env from the checkout's .env; the quadlet reads
|
||||
# it via EnvironmentFile. Consumed by the Caddyfile's acme_dns block
|
||||
# (DNS-01 wildcard cert issuance). PORKBUN_API_SECRET_KEY is the name the
|
||||
# caddy-dns/porkbun module expects.
|
||||
PORKBUN_API_KEY=changeme
|
||||
PORKBUN_API_SECRET_KEY=changeme
|
||||
@@ -0,0 +1,54 @@
|
||||
# Quadlet unit: canonical Caddy reverse proxy + ACME (rootless, boot-persistent).
|
||||
#
|
||||
# Install path on dankclaw: ~/.config/containers/systemd/caddy.container
|
||||
# Unit name: caddy.service (container name: caddy)
|
||||
#
|
||||
# The homelab's single Caddy: it fronts every service on both hosts and issues
|
||||
# Let's Encrypt wildcard certs via DNS-01 (Porkbun). It left compose.yaml on
|
||||
# 2026-08-26 after a reboot exposed that the bare compose container never came
|
||||
# back: rootless Podman has no boot-time auto-start for bare containers, and
|
||||
# `restart: unless-stopped` does not survive the explicit stop that shutdown
|
||||
# performs. See AGENTS.md "Boot Persistence & Self-Healing" and
|
||||
# docs/Infrastructure/Caddy.md.
|
||||
#
|
||||
# It joins the existing compose network (dankclaw_default) so the Caddyfile's
|
||||
# container-name upstreams (authentik-server, grafana, ...) still resolve; if
|
||||
# no compose service has created that network yet at boot, quadlet creates it
|
||||
# first and compose reuses it by name later. The image is built locally from
|
||||
# dankclaw/caddy/Containerfile and exists only on this host, so Pull=never: a
|
||||
# boot must not stall on a registry that does not have it. Porkbun credentials
|
||||
# come from /home/dank/Containers/caddy/env (deploy writes it from the
|
||||
# checkout's .env; secrets never enter the repo).
|
||||
|
||||
[Unit]
|
||||
Description=Caddy reverse proxy + ACME (Porkbun DNS-01) container
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Container]
|
||||
ContainerName=caddy
|
||||
Image=franksdank/caddy-porkbun:latest
|
||||
Pull=never
|
||||
Network=dankclaw_default
|
||||
PublishPort=0.0.0.0:80:80/tcp
|
||||
PublishPort=0.0.0.0:443:443/tcp
|
||||
EnvironmentFile=/home/dank/Containers/caddy/env
|
||||
Volume=/home/dank/Containers/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
Volume=/home/dank/Containers/caddy/data:/data
|
||||
Volume=/home/dank/Containers/caddy/config:/config
|
||||
# The homepage: the host's /srv/homepage (deploy-managed, not the repo's
|
||||
# shared/homepage).
|
||||
Volume=/srv/homepage:/srv/homepage:ro
|
||||
# The bare-IP catch-all answers 302 (curl -f passes on <400); this proves
|
||||
# Caddy itself is serving without touching any upstream.
|
||||
HealthCmd=curl -sf -o /dev/null http://localhost:80/
|
||||
HealthInterval=30s
|
||||
HealthTimeout=10s
|
||||
HealthRetries=3
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
Reference in new issue
Block a user