

5·
1 day agoYou can use rootless caddy via systemd socket activation, here’s a basic setup:
- rootless-caddy.service
[Unit]
Description=rootless-caddy
Requires=rootless-caddy.socket
After=rootless-caddy.socket
[Service]
# a non root user here
User=El_Quentinator
ExecStart=podman run --name caddy --rm -v [...] docker.io/caddy:alpine
[Install]
WantedBy=default.target
- rootless-caddy.socket
[Socket]
BindIPv6Only=both
### sockets for the HTTP reverse proxy
# fd/3
ListenStream=[::]:443
# fdgram/4
ListenDatagram=[::]:443
[Install]
WantedBy=sockets.target
- Caddyfile
{$SITE_ADDRESS} {
# tcp/443
bind fd/3 {
protocols h1 h2
}
# udp/443
bind fdgram/4 {
protocols h3
}
[...]
}
And that’s it really.
You can find a few more examples over here: https://github.com/eriksjolund/podman-caddy-socket-activation
Systemd socket activation has a few more interesting advantages on top of unlocking binding priviliged ports:
- allowing to not bind any port on the container, which itself allows to use
--network none
while still being able to connect to it via systemd socket, pretty neat to expose some web app while completely cutting its own external access. - getting rootful networking performance
- starting up your service only when connecting to it (and potentially shutting it back down after some time)
Drawbacks is that the file descriptor binding is a bit awkward and not always supported (caddy/nginx/haproxy do support it though). And that podman pods / kube do not support it (or at least not yet).
TBH I haven’t played with passing caddy’s podman network to other containers, mine is a simple reverse proxy to other standalone containers but not directly connected via
podman run --network
(or quadlet network). In my scenario I can at least confirm thatnet.ipv4.ip_unprivileged_port_start
doesn’t need to be modified, the only annoyance is that I cannot use a systemd user service, even though the end process doesn’t run as root.EDIT: Actually looking at the examples a bit more closely I think the primary difference with my setup is that the systemd socket is started with
systemd --user
which thus requires the sysctl change, whereas I’m not using a systemd user service, relying instead onUser=some-non-root-user
to use rootless podman, but requiring root privileges to manage the systemd service.