Allow the image to be run as any arbitrary UID/GID#441
Merged
francislavoie merged 1 commit intocaddyserver:masterfrom Feb 4, 2026
Merged
Allow the image to be run as any arbitrary UID/GID#441francislavoie merged 1 commit intocaddyserver:masterfrom
francislavoie merged 1 commit intocaddyserver:masterfrom
Conversation
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
```
Member
|
Technically |
francislavoie
approved these changes
Feb 4, 2026
Member
francislavoie
left a comment
There was a problem hiding this comment.
Makes sense to me.
Of course this would only fix fresh deployments, wouldn't fix existing named volumes if the user tries to switch from root to a different UID. But not much we can do about that anyway.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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/caddyand/data/caddybecause 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
--tmpfsmounts in the container, but with this change, I can run it much more simply.Failing without mounts/permissions:
Succeeding with permissions (this change):
Alternative to #428 (see especially #428 (comment))