Files
dev_blog/quadlet/dev-blog-caddy.container

50 lines
1.7 KiB
INI

[Unit]
Description=Caddy reverse proxy with Coraza WAF (OWASP CRS) and Google Cloud DNS plugin
Wants=network-online.target
After=network-online.target dev-blog-app.service
Requires=dev-blog-app.service
[Container]
ContainerName=dev-blog-caddy
# Build with: podman build -t localhost/dev-blog-caddy:latest ./caddy
Image=localhost/dev-blog-caddy:latest
# Caddy uses the *host* network namespace so it sees real client IP addresses
# (both v4 and v6). Required for fail2ban / Coraza to act on actual sources
# instead of the bridge gateway. With Network=host, PublishPort= is a no-op
# and is intentionally omitted -- Caddy binds 80/443 directly on the host.
Network=host
# --- Configuration ---
Environment=SITE_ADDRESS=https://example.com
Environment=ACME_EMAIL=admin@example.com
# Required by the googleclouddns plugin; must match a GCP project that owns
# the DNS zone for SITE_ADDRESS.
Environment=GCP_PROJECT=my-gcp-project
# A Workload-Identity / service-account JSON key mounted read-only below.
Environment=GOOGLE_APPLICATION_CREDENTIALS=/run/secrets/gcp-dns.json
# Mount the GCP service-account key as a read-only secret.
# Create with: podman secret create gcp-dns-sa /path/to/key.json
Secret=gcp-dns-sa,type=mount,target=gcp-dns.json,mode=0400
# Persistent state for ACME certificates and Caddy's data directory.
Volume=caddy-data.volume:/data
Volume=caddy-config.volume:/config
# Bind-mount the host log directory so fail2ban can tail Caddy access logs
# and Coraza audit logs. The :Z suffix asks Podman to relabel for SELinux.
Volume=/var/log/caddy:/var/log/caddy:Z
# Hardening
NoNewPrivileges=true
DropCapability=ALL
AddCapability=CAP_NET_BIND_SERVICE
[Service]
Restart=on-failure
TimeoutStartSec=120
[Install]
WantedBy=multi-user.target default.target