Caddy Under systemd — Hardening Checklist
The basics
[Service]
User=caddy
Group=caddy
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
Run as a dedicated system user, grant only the capability to bind ports below 1024. setcap cap_net_bind_service=+ep /usr/local/bin/caddy is the alternative if you prefer not to use AmbientCapabilities.
Filesystem isolation
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/caddy /var/log/caddy
ReadOnlyPaths=/etc/caddy /srv/naiveproxy
PrivateTmp=true
The one that breaks Go
MemoryDenyWriteExecute=true sounds good but breaks Go's runtime, which needs to write executable memory for its JIT-compiled trampolines. Do not enable it for any Go binary.
Worth checking
systemd-analyze security caddy.service
Gives an exposure score. Aim for ≥7.0. The remaining points usually come from AppArmor or SELinux profiles, which are worth adding if you have them.