Description
I was testing out some container hardening features and ran into the following error message when attempting to drop all capabilities inside the official Caddy container (e.g. <docker/podman> run --cap-drop=ALL caddy
):
caddy[12709]: {"msg":"exec container process `/usr/bin/caddy`: Operation not permitted","level":"error","time":"2025-04-04T19:20:00.696030Z"}
It works fine with only CAP_NET_BIND_SERVICE
, which makes sense for the default config. The problem is that the error persists even after configuring Caddy to only use unprivileged ports. Indeed, the container produces the same error even when the command is simply caddy --version
!
The error message above comes from crun
during container initialization. The root cause appears to be the file effective capability bit set on the executable with setcap
.
While normally fine, the problem with the effective capability bit is that execve
fails with EPERM
if unable to obtain the permitted capabilities (see the section "Safety checking for capability-dumb binaries"). This is the case when --cap-drop=ALL
is used in both Podman and Docker.
A solution is to use the libcap
API as mentioned by capability(7)
above and avoid the use of the effective capability bit. Doing so would allow Caddy to only require the capability when actually needed.
A workaround is to not drop CAP_NET_BIND_SERVICE
, which should be fairly safe inside containers. Still, considering that the capability is actually unnecessary in some setups (e.g. socket activation), users should be able to remove it in the default container setup. Also, troubleshooting why this error is occurring even when the binary isn't using the capability is a bit frustrating.
If this proposal is denied, then perhaps the docs should be updated to mention that users may run into this permission error in some environments even when not using any functionality that needs the capability.