50 lines
1.7 KiB
INI
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
|