Running Caddy Server as a service with systemd

In a previous blogpost I explained how to run Caddy (a brilliant and simple web server) as a service using Upstart. Systemd, however, replaced Upstart on most of the operating systems, so it makes more sense to have a guide for systemd.

Caddy executable

We don’t run Caddy as root to keep things as secure as possible. To allow a non-root user to listen on port 80 or 443, we must allow the executable to do so:

$ sudo setcap cap_net_bind_service=+ep ./caddy

systemd unit file

Now we create a systemd configuration file /etc/systemd/system/caddy.service, which looks like this on my server:

[Unit]
Description=Caddy webserver
Documentation=https://caddyserver.com/
After=network.target

[Service]
User=mathias
#Group=some_group
WorkingDirectory=/home/mathias
LimitNOFILE=4096
PIDFile=/var/run/caddy/caddy.pid
ExecStart=/home/mathias/caddy -agree -email my_lets_encrypt@mail.com -pidfile=/var/run/caddy/caddy.pid
Restart=on-failure
StartLimitInterval=600

[Install]
WantedBy=multi-user.target

A brief explanation of the directives:

  • After=network.target will automatically start Caddy after all networking stuff is loaded at boot.
  • User, Group and WorkingDirectory speak for themselves… Make sure that your Caddyfile is in the working directory. You can always manually specify the location of the Caddyfile: $ caddy -conf="/path/to/Caddyfile".
  • LimitNOFILE=4096 sets max file descriptor (to a good production value), like you would do with ulimit -n 4096 in your terminal.
  • ExecStart is the actual script that will be executed. In this case it runs the Caddy binary which is in my home directory, agrees the Let’s Encrypt user agreement, and sets a default email for your Let’s Encrypt account. If you don’t add those two flags, Caddy will prompt for user input, which will naturally not work when you start it as a daemon.
  • Restart=on-failure will automatically respawn the Caddy process if Caddy crashes (i.e. stopping with non-zero exit code).
  • StartLimitInterval=600 makes sure that if Caddy crashes too many times (being 5 by systemd’s default value) it will wait 10 min before trying again.
  • WantedBy specifies a target we want this service to be included with.

Make sure too take a peak at the systemd documentation, since it’s very powerful  and supports a lot of features!

Running the service

After you have created the service file, you must enable it: sudo systemctl enable caddy. Don’t forget to reload the service file if you make changes to it: systemctl daemon-reload.

Now you can start Caddy using sudo service caddy start. And of course stop, restart, …

You can view the status of your service using sudo service caddy status.