mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
Merge pull request #817 from mholt/systemd-service-file
Provides some more guidelines to operators on how to avoid running Caddy as root. Introduces an user www-data, which really is a placeholder. Such an user with the same UID/GID combination is created on the most popular Linux distribution. I trust any operator can spot the difference to his/her distro and adjust the unit file. User nobody is not used here to avoid two easy pitfalls: Such an user should not be able to access private keys (for TLS), and should not write private keys (we would do that with Letsencrypt).
This commit is contained in:
commit
e516aebc08
3 changed files with 110 additions and 44 deletions
81
dist/init/linux-systemd/README.md
vendored
81
dist/init/linux-systemd/README.md
vendored
|
@ -1,40 +1,79 @@
|
|||
# systemd unit for caddy
|
||||
|
||||
Please do not hesitate to ask [me](mailto:klingt.net+caddy@gmail.com) if you've any questions.
|
||||
Please do not hesitate to ask if you have any questions.
|
||||
|
||||
## Quickstart
|
||||
|
||||
- install the unit configuration file: `cp caddy@.service /etc/systemd/system`
|
||||
- reload the systemd daemon: `systemctl deamon-reload`
|
||||
- make sure to [configure](#configuration) the service unit before starting caddy
|
||||
- start caddy: `systemctl start caddy@someuser`
|
||||
- enable the service (automatically start on boot): `systemctl enable caddy@someuser`
|
||||
- the `.caddy` folder will be created inside the users home directory that runs caddy, i.e. `/home/someuser/.caddy` for `systemctl start caddy@someuser`
|
||||
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/`
|
||||
- Reload the systemd daemon: `systemctl daemon-reload`
|
||||
- Make sure to [configure](#configuration) the service unit before starting caddy.
|
||||
- Start caddy: `systemctl start caddy.service`
|
||||
- Enable the service (automatically start on boot): `systemctl enable caddy.service`
|
||||
- A folder `.caddy` will be created inside the home directory of the user that runs caddy;
|
||||
you can change that by providing an environment variable `HOME`,
|
||||
i.e. `Environment=HOME=/var/lib/caddy` will result in `/var/lib/caddy/.caddy`.
|
||||
|
||||
## Configuration
|
||||
|
||||
- do not edit the systemd unit directly, use systemd's builtin tools:
|
||||
- `systemctl edit caddy@` to make user local modifications to the service unit
|
||||
- `systemctl edit --full caddy@` to make system-wide modifications
|
||||
- in most cases it's enough to adapt the `ExecStart` directive:
|
||||
- `systemctl edit caddy@`
|
||||
- systemd needs absolute paths, therefore make sure that the path to caddy is correct
|
||||
- Do not edit the systemd unit file directly. Instead, use systemd's builtin tools:
|
||||
- `systemctl edit caddy.service` to make user-local modifications
|
||||
- `systemctl edit --full caddy.service` for system-wide ones
|
||||
- In most cases it is enough to override the `ExecStart` directive.
|
||||
- systemd needs absolute paths, therefore make sure that the path to caddy is correct.
|
||||
- example:
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
; reset the original setting
|
||||
; an empty value clears the original (and preceding) settings
|
||||
ExecStart=
|
||||
ExecStart=/usr/bin/caddy -conf="/etc/caddy/myCaddy.conf" -agree -email="my@mail.address"
|
||||
```
|
||||
|
||||
- to view your configuration use `systemctl cat caddy@`
|
||||
- double check the permissions of your web root path to make sure that caddy can access it as its run user and group
|
||||
- To view the resulting configuration use `systemctl cat caddy`
|
||||
- Double check permissions of your *document root* path.
|
||||
The user caddy runs as needs to have access to it. For example:
|
||||
|
||||
```bash
|
||||
# caddy would run as www-data:www-data
|
||||
# serving, in this example: /var/www
|
||||
|
||||
sudo -u www-data -g www-data -s \
|
||||
ls -hlAS /var/www
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
- use `log stdout` and `errors stderr` in your Caddyfile to make use of `journalctl`
|
||||
- `journalctl` is systemd's log query tool
|
||||
- lets say you want all the log entries for caddy since the last boot beginning from the last entry: `journalctl --reverse --boot --unit caddy@someuser`
|
||||
- maybe you want to follow caddys log output: `journalctl -fu caddy@someuser`
|
||||
- to send a signal to a service units main PID, e.g. let caddy reload its config: `systemctl kill --signal=USR1 caddy@someuser`
|
||||
- Use `log stdout` and `errors stderr` in your Caddyfile to utilize `journalctl`.
|
||||
- `journalctl` is systemd's log query tool.
|
||||
- Let's say you want all the log entries since the last boot, beginning from the last entry:
|
||||
`journalctl --reverse --boot --unit caddy.service`
|
||||
- To follow caddy's log output: `journalctl -fu caddy.service`
|
||||
- Send a signal to a service unit's main PID, e.g. have caddy reload its config:
|
||||
`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`.
|
||||
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
|
||||
```
|
||||
|
|
50
dist/init/linux-systemd/caddy.service
vendored
Normal file
50
dist/init/linux-systemd/caddy.service
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
[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
|
23
dist/init/linux-systemd/caddy@.service
vendored
23
dist/init/linux-systemd/caddy@.service
vendored
|
@ -1,23 +0,0 @@
|
|||
; 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
|
Loading…
Reference in a new issue