1. The problem I’m having:
I’ve trying to run caddy as systemd unit with www-data:www-data
(or caddy:www-data
).
I have few users (with same named groups):
www-data
(httpd user, httpd and nginx also runs with that in other cases)
manager
(is a developer acc, this user is owner and editor for site files, also php-fpm runs with that)
caddy
(of course)
each of this users are member of www-data
Root folder for web is /srv/
(/srv/sites/domain
as web root for domain) and it’s owned by manager:www-data
and has 755+644 permissions on dirs/files - this allow editing for manager and get reading access for httpd/nginx in the same time.
The next runs fine (site works as expected), but it’s root
, so that is unwanted way.
sudo caddy run --config /etc/caddy/Caddyfile
Next way is systemd unit variations:
sudo systemctl start caddy
- Unit run as
caddy:caddy
.
It works, BUT only if folder and files chown’ed ascaddy:caddy
(unacceptable for this case - files must be owned bymanager:www-data
) - Unit run as
caddy:www-data
.
Get 403 on any file routes. Expected that is get reading access through group rights as another web-servers (with files owned bymanager:www-data
) - Unit run as
www-data:www-data
.
Failed. Looks like it has some issues with internal tls (look at errors section). This is most wanted way to start it, but how to combine internal tls with that? Please, help me
2. Error messages and/or full log output:
when run as unit with www-data:www-data
- failed with error (seems like problem with tls internal
)
Error: loading http app module: provision http: getting tls app: loading tls app module: provision tls: provisioning automation policy 0: loading TLS automation management module: position 0: loading module 'internal': provision tls.issuance.internal: loading pki app module: provisio
n pki: provisioning CA 'local': loading root cert: open /var/lib/caddy/pki/authorities/local/root.crt: permission denied
when run as caddy:www-data
- runned, but got 403 error on any files
Feb 11 12:31:31 host caddy[10618]: {"level":"debug","ts":1739287891.695817,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"management.loc","subjects":["management.loc"],"managed":true,"issuer_key":"local","hash":"a01e3e0705c483e8c9fd8269cf5b7683c90b0ab0cd362f99c189cf83654b0b11"}
Feb 11 12:31:31 host caddy[10618]: {"level":"debug","ts":1739287891.6958232,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"127.0.0.1","remote_port":"50826","subjects":["management.loc"],"managed":true,"expiration":1739330634,"hash":"a01e3e0705c483e8c9fd8269cf5b7683c90b0ab0cd362f99c189cf83654b0b11"}
Feb 11 12:31:31 host caddy[10618]: {"level":"debug","ts":1739287891.7009768,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/srv/sites/management.loc/","fs":"","request_path":"/index.html","result":"/srv/sites/management.loc/index.html"}
Feb 11 12:31:31 host caddy[10618]: {"level":"debug","ts":1739287891.7010245,"logger":"http.log.error","msg":"open /srv/sites/management.loc/index.html: permission denied","request":{"remote_ip":"127.0.0.1","remote_port":"50826","client_ip":"127.0.0.1","proto":"HTTP/2.0","method":"GET","host":"management.loc","uri":"/index.html",
"headers":{"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-User":["?1"],"Priority":["u=0, i"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"Accept-Language":["en-US,en;q=0.5"],"Dnt":["1"],"Cookie":["REDACTED"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"Te":["trailers"],"Cac
he-Control":["no-cache"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Mode":["navigate"],"Pragma":["no-cache"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"management.loc"}},"duration"
:0.000122302,"status":403,"err_id":"n160pre38","err_trace":"fileserver.(*FileServer).ServeHTTP (staticfiles.go:283)"}
Feb 11 12:31:31 host caddy[10618]: {"level":"debug","ts":1739287891.7381935,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/srv/sites/management.loc/","fs":"","request_path":"/favicon.ico","result":"/srv/sites/management.loc/favicon.ico"}
Feb 11 12:31:31 host caddy[10618]: {"level":"debug","ts":1739287891.738252,"logger":"http.log.error","msg":"open /srv/sites/management.loc/favicon.ico: permission denied","request":{"remote_ip":"127.0.0.1","remote_port":"50826","client_ip":"127.0.0.1","proto":"HTTP/2.0","method":"GET","host":"management.loc","uri":"/favicon.ico"
,"headers":{"Accept":["image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Referer":["https://management.loc/index.html"],"Cookie":["REDACTED"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:135.0) Gecko/20100101 Firefox/135.0"],"Accept-Language":["en-US,
en;q=0.5"],"Dnt":["1"],"Sec-Fetch-Dest":["image"],"Sec-Fetch-Site":["same-origin"],"Te":["trailers"],"Sec-Fetch-Mode":["no-cors"],"Priority":["u=6"],"Pragma":["no-cache"],"Cache-Control":["no-cache"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"management.loc"}},"duration":0.00016901
5,"status":403,"err_id":"hbvtpgs31","err_trace":"fileserver.(*FileServer).ServeHTTP (staticfiles.go:283)"}
3. Caddy version:
v2.8.4
4. How I installed and ran Caddy:
installed from repositories
a. System environment:
Arch x86-64, systemd 257.2
b. Command:
systemctl start caddy
sudo caddy run --config /etc/caddy/Caddyfile
c. Service/unit/compose file:
[Unit]
Description=Caddy web server
Documentation=https://caddyserver.com/docs/
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=14400
StartLimitBurst=10
[Service]
Type=notify
User=caddy
Group=www-data
Environment=XDG_DATA_HOME=/var/lib
Environment=XDG_CONFIG_HOME=/etc
ExecStartPre=/usr/bin/caddy validate --config /etc/caddy/Caddyfile
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
ExecStopPost=/usr/bin/rm -f /run/caddy/admin.socket
# Do not allow the process to be restarted in a tight loop. If the
# process fails to start, something critical needs to be fixed.
Restart=on-abnormal
# Use graceful shutdown with a reasonable timeout
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
# Hardening options
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
DevicePolicy=closed
LockPersonality=true
MemoryAccounting=true
MemoryDenyWriteExecute=true
NoNewPrivileges=true
PrivateDevices=true
PrivateTmp=true
ProcSubset=pid
ProtectClock=true
ProtectControlGroups=true
ProtectHome=true
ProtectHostname=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectProc=invisible
ProtectSystem=strict
RemoveIPC=true
ReadWritePaths=/var/lib/caddy /var/log/caddy /run/caddy
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
[Install]
WantedBy=multi-user.target
d. My complete Caddy config:
{
debug
storage_clean_interval 72h
admin "unix//run/caddy/admin.socket"
servers :443 {
name https
}
servers :80 {
name http
protocols h1 h2c
}
}
management.loc {
encode gzip
tls internal
root * "/srv/sites/management.loc/"
file_server
php_fastcgi unix//run/php-fpm/php-fpm.sock
}
5. Links to relevant resources:
I found similar issue on the forum, but I didn’t figure it out what is final solution is