Systemd fails to load caddy on a raspberry Pi

(Jean-Luc Lacroix) #1

Installation went flawlessly and test runs were also successful launching the caddy binary from the command line. This became a bit more complicated when I tried to run caddy as a systemd service using the caddy.service file available on github.

The service would no launch and the logs showed:
Jan 02 15:13:17 raspberrypi systemd[1]: Started Caddy HTTP/2 web server.
Jan 02 15:13:17 raspberrypi caddy[1378]: Activating privacy features… done.
Jan 02 15:13:17 raspberrypi caddy[1378]: 2018/01/02 15:13:17 listen tcp :80: bind: permission denied
Jan 02 15:13:17 raspberrypi systemd[1]: caddy.service: Main process exited, code=exited, status=1/FAILURE
Jan 02 15:13:17 raspberrypi systemd[1]: caddy.service: Unit entered failed state.
Jan 02 15:13:17 raspberrypi systemd[1]: caddy.service: Failed with result ‘exit-code’.

setcap 'cap_net_bind_service=+ep' /usr/local/bin/caddy was done as per the caddy systemd howto

After a bit of fiddling into the caddy.service file I found that the culprit was this line:
; Use a minimal /dev

Running fine without it. Any idea why? Does that line have anything to do with the bind-to-port problem?

And, BTW, thanks to the devs for Caddy. I am a fan of golang and love using it as a web server.

(Federico Bruni) #2

Disclaimer: I’m very new to systemd.
I’ve read here that:

Note that PrivateNetwork=yes should not be used for:

Services that actually require network access (with the exception of daemons only needing socket activation)

Perhaps caddy.service falls into this category?

(Federico Bruni) #3

Sorry, wrong quote. I meant to quote this:

Note that PrivateDevices=yes should not be used for:

  1. Services that actually require physical device access
  2. Services which may be used to execute arbitrary user or administrator supplied programs (such as cron, …). We shouldn’t limit what people can do with these services.
  3. This option creates a new file system namespace where mount/umount propagation is turned off back into the host. This means that mounts made by the service will stay private to the service. Thus this option should not be used by services which shall be able to establish mounts in the host.

(Jean-Luc Lacroix) #4

Ok. Thanks for the link. It is not specific to the RPI, I just bumped into the same problem on a VPS instance. Probably for the same reason.

(Kevin Kub) #5

Can you show us your caddy.service file?

I am quite happy with this one from

Description=Caddy HTTP/2 web server

ExecStart=/usr/bin/caddy -log stdout -agree -conf /etc/caddy/caddy.conf -root /tmp
ExecReload=/usr/bin/kill -USR1 $MAINPID
ReadWritePaths=/var/lib/caddy /var/log/caddy


(Jean-Luc Lacroix) #6

Here is mine (a cc from github)

Description=Caddy HTTP/2 web server
Documentation= systemd-networkd-wait-online.service

ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp
ExecReload=/bin/kill -USR1 $MAINPID


(Magikstm) #7

Related to:

@matt as it is hard to investigate and hinders usage I would suggest:

  1. Adding more details above it and disabling it by default here:

  2. Adding details about the added security it may provide as well as the possible issues here:

I think it would help users setupping Caddy with systemd. Could an issue and a PR for it be created?

(Matt Holt) #8

I really want to keep the Caddy repo as free from system admin-related issues as much as possible, and keep it focused on Caddy itself. But we can make changes to the dist/init files for the better in the meantime; just submit a pull request. :slight_smile:

(Magikstm) #9


I created this PR for it:

(Kevin Kub) #10

@JeanLucLacroix Please try to add this line to your service definition (probably right after [Service]:


This will allow the service to bind to any port (e.g. 80 and 443).

(Jean-Luc Lacroix) #11

Yes, it works without any error message with that systemd directive . Thanks. But it works also without the PrivateDevices=true directive. I don’t know which solution is better:




P.S. Just ran kind of benchmark and the version with PrivateDevices=false runs marginally faster (3%). Tested with ab -n3000 -c200

(Matthew Fay) #12

PrivateDevices hides physical devices under /dev from the service’s process.

There’s a system call filter and bind mounts involved, might explain the slight slowdown while it’s enabled?

Up to you if you think hiding disks and other devices from Caddy is a reasonable security measure. Personally I don’t think it’s necessary, given that Caddy is open source and doesn’t interact directly with your devices anyway.