Commit da8ae9e5 authored by W-Mark Kubacki's avatar W-Mark Kubacki

systemd: Run caddy with even less privileges and more confined

The exemplary unit file for systemd is intentionally redundant at times, for
example dropping privileges which an unprivileged user "www-data" did not have
in the first place: To aid as fallback in case the file gets copied and an
operator setting UID to 0 (which reportedly happened in the past).
parent d377c79a
...@@ -4,6 +4,25 @@ Please do not hesitate to ask if you have any questions. ...@@ -4,6 +4,25 @@ Please do not hesitate to ask if you have any questions.
## Quickstart ## Quickstart
The provided unit file assumes that you want to run caddy as `www-data` and group `www-data`,
both having UID and GID 33 here.
Adjust this to your liking according to the preferences of you Linux distribution!
```bash
groupadd -g 33 www-data
useradd \
-g www-data --no-user-group \
--home-dir /var/www --no-create-home \
--shell /usr/sbin/nologin \
--system --uid 33 www-data
mkdir /etc/caddy
chown -R root:www-data /etc/caddy
mkdir /etc/ssl/caddy
chown -R www-data:root /etc/ssl/caddy
chmod 0770 /etc/ssl/caddy
```
- Install the unit configuration file: `cp caddy.service /etc/systemd/system/` - Install the unit configuration file: `cp caddy.service /etc/systemd/system/`
- Reload the systemd daemon: `systemctl daemon-reload` - Reload the systemd daemon: `systemctl daemon-reload`
- Make sure to [configure](#configuration) the service unit before starting caddy. - Make sure to [configure](#configuration) the service unit before starting caddy.
...@@ -52,3 +71,9 @@ sudo -u www-data -g www-data -s \ ...@@ -52,3 +71,9 @@ sudo -u www-data -g www-data -s \
`systemctl kill --signal=USR1 caddy.service` `systemctl kill --signal=USR1 caddy.service`
- If you have more files that start with `caddy` – like a `caddy.timer`, `caddy.path`, or `caddy.socket` – then it is important to append `.service`. - If you have more files that start with `caddy` – like a `caddy.timer`, `caddy.path`, or `caddy.socket` – then it is important to append `.service`.
Although if `caddy.service` is all you have, then you can just use `caddy` without any extension, such as in: `systemctl status caddy` Although if `caddy.service` is all you have, then you can just use `caddy` without any extension, such as in: `systemctl status caddy`
- You can make your other certificates and private key files accessible to a user `www-data` by command `setfacl`, if you must:
```bash
setfacl -m user:www-data:r-- /etc/ssl/private/my.key
```
[Unit]
Description=Caddy HTTP/2 web server
Documentation=https://caddyserver.com/docs
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
[Service]
Restart=on-failure
; User and group the process will run as.
User=www-data
Group=www-data
; Letsencrypt-issued certificates will be written to this directory.
Environment=HOME=/etc/ssl/caddy
; Always set "-root" to something safe in case it gets forgotten in the Caddyfile.
ExecStart=/usr/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp
ExecReload=/bin/kill -USR1 $MAINPID
; Limit the number of file descriptors; see `man systemd.exec` for more limit settings.
LimitNOFILE=1048576
; Unmodified caddy is not expected to use more than that.
LimitNPROC=64
; Use private /tmp and /var/tmp, which are discarded after caddy stops.
PrivateTmp=true
; Use a minimal /dev
PrivateDevices=true
; Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
ProtectHome=true
; Make /usr, /boot, /etc and possibly some more folders read-only.
ProtectSystem=full
; … except /etc/ssl/caddy, because we want Letsencrypt-certificates there.
; This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
ReadWriteDirectories=/etc/ssl/caddy
; Drop all other capabilities. Important if you run caddy as privileged user (which you should not).
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
; … but permit caddy to open ports reserved for system services.
; This could be redundant here, but is needed in case caddy runs as nobody:nogroup.
AmbientCapabilities=CAP_NET_BIND_SERVICE
; … and prevent gaining any new privileges.
NoNewPrivileges=true
; Caveat: Some plugins need additional capabilities. Add them to both above lines.
; - plugin "upload" needs: CAP_LEASE
[Install]
WantedBy=multi-user.target
; see `man systemd.unit` for configuration details
; the man section also explains *specifiers* `%x`
[Unit]
Description=Caddy HTTP/2 web server %I
Documentation=https://caddyserver.com/docs
After=network-online.target
Wants=network-online.target
Wants=systemd-networkd-wait-online.service
[Service]
; run user and group for caddy
User=%i
Group=http
ExecStart=/usr/bin/caddy -agree=true -conf=/etc/caddy/Caddyfile
Restart=on-failure
; create a private temp folder that is not shared with other processes
PrivateTmp=true
; limit the number of file descriptors, see `man systemd.exec` for more limit settings
LimitNOFILE=8192
[Install]
WantedBy=multi-user.target
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment