2026-03-30 · linux sysadmin

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.

← All notes