From 2603138de6c7744a3b6b152e010e5b19d309ee88 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 4 Feb 2026 10:13:54 -0800 Subject: [PATCH] Allow the image to be run as any arbitrary UID/GID Namely, this sets the runtime-mutable directory permissions to 1777 (matching the notable/venerable `/tmp`) -- this allows them to be writable by anyone, but files created are owned by the user who creates them. In specific, the two directories this changes are `/config/caddy` and `/data/caddy` because those appear to be the only two that Caddy tries to write to at runtime by default (and thus needs access to create files/folders it can then own within). Prior to this change, I could run Caddy as an arbitrary user by getting "clever" with `--tmpfs` mounts in the container, but with this change, I can run it much more simply. Failing without mounts/permissions: ```console $ docker run -it --rm --user 1234:5678 --security-opt no-new-privileges caddy 2026/02/04 18:49:39.972 INFO maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined 2026/02/04 18:49:39.972 INFO GOMEMLIMIT is updated {"package": "github.com/KimMachineGun/automemlimit/memlimit", "GOMEMLIMIT": 60335312486, "previous": 9223372036854775807} 2026/02/04 18:49:39.972 INFO using config from file {"file": "/etc/caddy/Caddyfile"} 2026/02/04 18:49:39.973 INFO adapted config to JSON {"adapter": "caddyfile"} 2026/02/04 18:49:39.973 INFO admin admin endpoint started {"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]} 2026/02/04 18:49:39.974 WARN http.auto_https server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server {"server_name": "srv0", "http_port": 80} 2026/02/04 18:49:39.974 WARN http HTTP/2 skipped because it requires TLS {"network": "tcp", "addr": ":80"} 2026/02/04 18:49:39.974 WARN http HTTP/3 skipped because it requires TLS {"network": "tcp", "addr": ":80"} 2026/02/04 18:49:39.974 INFO http.log server running {"name": "srv0", "protocols": ["h1", "h2", "h3"]} 2026/02/04 18:49:39.974 ERROR unable to autosave config {"file": "/config/caddy/autosave.json", "error": "open /config/caddy/autosave.json: permission denied"} 2026/02/04 18:49:39.974 INFO serving initial configuration 2026/02/04 18:49:39.974 INFO tls.cache.maintenance started background certificate maintenance {"cache": "0xc000183480"} 2026/02/04 18:49:39.974 WARN tls unable to get instance ID; storage clean stamps will be incomplete {"error": "open /data/caddy/instance.uuid: permission denied"} 2026/02/04 18:49:39.974 ERROR tls could not clean default/global storage {"error": "unable to acquire storage_clean lock: creating lock file: open /data/caddy/locks/storage_clean.lock: no such file or directory"} 2026/02/04 18:49:39.974 INFO tls finished cleaning storage units ``` Succeeding with permissions (this change): ```console $ docker run -it --rm --user 1234:5678 --security-opt no-new-privileges sha256:359f2a56ad454e5516c5473a9b9203c70b8801a9e2405d5e883e3c8e1c55da58 2026/02/04 18:50:28.491 INFO maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined 2026/02/04 18:50:28.491 INFO GOMEMLIMIT is updated {"GOMEMLIMIT": 60335312486, "previous": 9223372036854775807} 2026/02/04 18:50:28.491 INFO using config from file {"file": "/etc/caddy/Caddyfile"} 2026/02/04 18:50:28.491 INFO adapted config to JSON {"adapter": "caddyfile"} 2026/02/04 18:50:28.492 INFO admin admin endpoint started {"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]} 2026/02/04 18:50:28.492 WARN http.auto_https server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server {"server_name": "srv0", "http_port": 80} 2026/02/04 18:50:28.492 WARN http HTTP/2 skipped because it requires TLS {"network": "tcp", "addr": ":80"} 2026/02/04 18:50:28.492 WARN http HTTP/3 skipped because it requires TLS {"network": "tcp", "addr": ":80"} 2026/02/04 18:50:28.492 INFO http.log server running {"name": "srv0", "protocols": ["h1", "h2", "h3"]} 2026/02/04 18:50:28.492 INFO tls.cache.maintenance started background certificate maintenance {"cache": "0xc00050fb00"} 2026/02/04 18:50:28.497 INFO autosaved config (load with --resume flag) {"file": "/config/caddy/autosave.json"} 2026/02/04 18:50:28.497 INFO serving initial configuration 2026/02/04 18:50:28.501 INFO tls cleaning storage unit {"storage": "FileStorage:/data/caddy"} 2026/02/04 18:50:28.503 INFO tls finished cleaning storage units ``` --- 2.10/alpine/Dockerfile | 1 + 2.11/alpine/Dockerfile | 1 + Dockerfile.tmpl | 1 + 3 files changed, 3 insertions(+) diff --git a/2.10/alpine/Dockerfile b/2.10/alpine/Dockerfile index 044ea3a..0105d95 100644 --- a/2.10/alpine/Dockerfile +++ b/2.10/alpine/Dockerfile @@ -13,6 +13,7 @@ RUN set -eux; \ /etc/caddy \ /usr/share/caddy \ ; \ + chmod 1777 /config/caddy /data/caddy; \ wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/config/Caddyfile"; \ wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/welcome/index.html" diff --git a/2.11/alpine/Dockerfile b/2.11/alpine/Dockerfile index 2b2a055..394fba8 100644 --- a/2.11/alpine/Dockerfile +++ b/2.11/alpine/Dockerfile @@ -13,6 +13,7 @@ RUN set -eux; \ /etc/caddy \ /usr/share/caddy \ ; \ + chmod 1777 /config/caddy /data/caddy; \ wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/config/Caddyfile"; \ wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/welcome/index.html" diff --git a/Dockerfile.tmpl b/Dockerfile.tmpl index e2f40fc..9bd642a 100644 --- a/Dockerfile.tmpl +++ b/Dockerfile.tmpl @@ -13,6 +13,7 @@ RUN set -eux; \ /etc/caddy \ /usr/share/caddy \ ; \ + chmod 1777 /config/caddy /data/caddy; \ wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/{{ .config.dist_commit }}/config/Caddyfile"; \ wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/{{ .config.dist_commit }}/welcome/index.html"