Caddy.service on Raspberry Pi 3

Hi all,

I tried to setup caddyservice following this guide (Step 3: How To Host a Website with Caddy on Ubuntu 16.04 | DigitalOcean) but withouk luck.

I only changed user and group from default to user=pi and group=pi.

If I run sudo systemctl start caddy.service I receive an ellipsed error;
If I run sudo systemctl start caddy.service -l I receive a status=226/NAMESPACE.

I tried to follow this guide to solve it (https://github.com/mholt/caddy/issues/1104) without changes.

Can someone please help me?

Thank you in advance

Hi @Jokerigno,

Could you post your current full service file?

Hi,

sorry for the delay.

Here’s the full caddy.service file:

[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-abnormal

; User and group the process will run as.
User=pi
Group=pi

; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/etc/ssl/caddy

; Always set "-root" to something safe in case it gets forgotten in the Caddyfile.
ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp
ExecReload=/bin/kill -USR1 $MAINPID

; Use graceful shutdown with a reasonable timeout
KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=5s

; 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

; The following additional security directives only work with systemd v229 or later.
; They further retrict privileges that can be gained by caddy. Uncomment if you like.
; Note that you may have to add capabilities required by any plugins in use.
;CapabilityBoundingSet=CAP_NET_BIND_SERVICE
;AmbientCapabilities=CAP_NET_BIND_SERVICE
;NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

Please notice that I’ve only changed the user and group and commented this lines

; 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 

Thank you in advance!

Bit of a long shot, but is /var/tmp a symlink by any chance? I’ve heard of systemd having a conniption when that’s the case, although commenting PrivateTmp is supposedly the usual workaround. Other than that, I’d try it with user and group set to www-data just to rule out pi causing some issue.

Yeah I think the issue are releated to user and folder settings.

I moved caddy.service file from /home/pi to etc/caddy and the output changed showing another kind of error:

pi@jarvis:~ $ sudo systemctl status caddy.service
● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; enabled)
   Active: failed (Result: exit-code) since gio 2017-08-24 07:41:07 CEST; 2min 4                                                                             5s ago
     Docs: https://caddyserver.com/docs
 Main PID: 603 (code=exited, status=1/FAILURE)

ago 24 07:41:05 jarvis systemd[1]: Started Caddy HTTP/2 web server.
ago 24 07:41:07 jarvis caddy[603]: Activating privacy features...2017/08/24...ed
ago 24 07:41:07 jarvis systemd[1]: caddy.service: main process exited, code...RE
ago 24 07:41:07 jarvis systemd[1]: Unit caddy.service entered failed state.
Hint: Some lines were ellipsized, use -l to show in full.
pi@jarvis:~ $ sudo systemctl status caddy.service -l
● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; enabled)
   Active: failed (Result: exit-code) since gio 2017-08-24 07:41:07 CEST; 3min 0                                                                             s ago
     Docs: https://caddyserver.com/docs
 Main PID: 603 (code=exited, status=1/FAILURE)

ago 24 07:41:05 jarvis systemd[1]: Started Caddy HTTP/2 web server.
ago 24 07:41:07 jarvis caddy[603]: Activating privacy features...2017/08/24 07:4                                                                             1:07 stat /etc/ssl/caddy/acme/acme-v01.api.letsencrypt.org/sites/domain.com                                                                         /domain.com.crt: permission denied
ago 24 07:41:07 jarvis systemd[1]: caddy.service: main process exited, code=exit                                                                             ed, status=1/FAILURE
ago 24 07:41:07 jarvis systemd[1]: Unit caddy.service entered failed state.

what happens if i change user from pi to root?

Caddy itself exited, and the last line was stat /etc/ssl/caddy/acme/acme-v01.api.letsencrypt.org/sites/domain.com. Guessing user pi doesn’t have permission to access these files?

yes, that was the problem.

So I changed folder to home/pi/caddy so pi user can access it.

I put caddyfile also in that folder and changed caddy.service accordly.

here’s the full new version:

[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-abnormal

; User and group the process will run as.
User=pi
Group=pi

; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/home/pi/caddy

; Always set “-root” to something safe in case it gets forgotten in the Caddyfile.
ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/home/pi/caddy/Caddyfile -root=/var/tmp
ExecReload=/bin/kill -USR1 $MAINPID

; Use graceful shutdown with a reasonable timeout
KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=5s

; 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

; The following additional security directives only work with systemd v229 or later.
; They further retrict privileges that can be gained by caddy. Uncomment if you like.
; Note that you may have to add capabilities required by any plugins in use.
;CapabilityBoundingSet=CAP_NET_BIND_SERVICE
;AmbientCapabilities=CAP_NET_BIND_SERVICE
;NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

so now something changed.

If i run sudo systemctl start caddy.service -l that’s the new error message:

● caddy.service - Caddy HTTP/2 web server
   Loaded: loaded (/etc/systemd/system/caddy.service; enabled)
   Active: failed (Result: exit-code) since sab 2017-08-26 18:19:16 CEST; 1min 4                                                                             2s ago
     Docs: https://caddyserver.com/docs
 Main PID: 602 (code=exited, status=1/FAILURE)

ago 26 18:19:14 jarvis systemd[1]: Started Caddy HTTP/2 web server.
ago 26 18:19:16 jarvis caddy[602]: Activating privacy features...
ago 26 18:19:16 jarvis caddy[602]: Your sites will be served over HTTPS automati                                                                             cally using Let's Encrypt.
ago 26 18:19:16 jarvis caddy[602]: By continuing, you agree to the Let's Encrypt                                                                              Subscriber Agreement at:
ago 26 18:19:16 jarvis caddy[602]: https://acme-v01.api.letsencrypt.org/terms
ago 26 18:19:16 jarvis caddy[602]: Please enter your email address so you can re                                                                             cover your account if needed.
ago 26 18:19:16 jarvis caddy[602]: You can leave it blank, but you'll lose the a                                                                             bility to recover your account.
ago 26 18:19:16 jarvis caddy[602]: Email address: 2017/08/26 18:19:16 get direct                                                                             ory at 'https://acme-v01.api.letsencrypt.org/directory': failed to get json "htt                                                                             ps://acme-v01.api.letsencrypt.org/directory": Get https://acme-v01.api.letsencry                                                                             pt.org/directory: dial tcp: lookup acme-v01.api.letsencrypt.org on [::1]:53: rea                                                                             d udp [::1]:37980->[::1]:53: read: connection refused
ago 26 18:19:16 jarvis systemd[1]: caddy.service: main process exited, code=exit                                                                             ed, status=1/FAILURE
ago 26 18:19:16 jarvis systemd[1]: Unit caddy.service entered failed state.

It’s strange that i see connection refused. Ports 80 and 443 are still open on my router to the pi.

Any help?

Looks like a DNS issue. It tried to look up LetsEncrypt and was refused by [::1]:53? Are you running a DNS server locally?

absolutely not!

I just setup google’s DNS on my asus router.

No one had the same issue?

First of all, always restore these lines (someone commented them out because he/she used an obsolete version of systemd that did not support those directives; contrary to their misleading comment they actually grant the process a crucial capability!):

Then, add another line below the existing one to whitelist the directories you serve or read from (the config, in your case):

ReadWriteDirectories=/home/pi/caddy

I highly recommend you restore the lines you’ve uncommented, including PrivateTmp.

Ports 80 and 443 are most likely still open from your previous tests, like from starting Caddy as root to see if it works at all. That’s no indication of a failure whatsoever. I recommend you check if a firewall is configured, though: iptables-save, ip6tables-save. If so, you will need to google how to ACCEPT packets on those ports.

Hi Mark and THANK YOU for your support!

I’ve done as you suggest me but uncommenting capability generates an error:

pi@jarvis:~ $ sudo systemctl status caddy.service -l
● caddy.service - Caddy HTTP/2 web server
Loaded: loaded (/etc/systemd/system/caddy.service; enabled)
Active: failed (Result: exit-code) since gio 2017-09-14 21:26:02 CEST; 5min ago
Docs: Welcome — Caddy Documentation
Main PID: 637 (code=exited, status=226/NAMESPACE)

set 14 21:26:02 jarvis systemd[1]: Started Caddy HTTP/2 web server.
set 14 21:26:02 jarvis systemd[1]: caddy.service: main process exited, code=exited, status=226/NAMESPACE
set 14 21:26:02 jarvis systemd[1]: Unit caddy.service entered failed state.
set 14 21:30:44 jarvis systemd[1]: [/etc/systemd/system/caddy.service:48] Unknown lvalue ‘AmbientCapabilities’ in section ‘Service’
set 14 21:30:49 jarvis systemd[1]: [/etc/systemd/system/caddy.service:48] Unknown lvalue ‘AmbientCapabilities’ in section ‘Service’

Here’s the new caddy.service file used:

[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-abnormal

; User and group the process will run as.
User=pi
Group=pi

; Letsencrypt-issued certificates will be written to this directory.
Environment=CADDYPATH=/home/pi/caddy

; Always set "-root" to something safe in case it gets forgotten in the Caddyfile.
ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/home/pi/caddy/Caddyfile -root=/var/tmp
ExecReload=/bin/kill -USR1 $MAINPID

; Use graceful shutdown with a reasonable timeout
KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=5s

; 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
ReadWriteDirectories=/home/pi/caddy

; The following additional security directives only work with systemd v229 or later.
; They further retrict privileges that can be gained by caddy. Uncomment if you like.
; Note that you may have to add capabilities required by any plugins in use.
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

The error disapper commenting those lines:

● caddy.service - Caddy HTTP/2 web server
Loaded: loaded (/etc/systemd/system/caddy.service; enabled)
Active: failed (Result: exit-code) since gio 2017-09-14 21:37:34 CEST; 3min 5 4s ago
Docs: Welcome — Caddy Documentation
Main PID: 646 (code=exited, status=226/NAMESPACE)

set 14 21:37:34 jarvis systemd[1]: Started Caddy HTTP/2 web server.
set 14 21:37:34 jarvis systemd[1]: caddy.service: main process exited, code=exit ed, status=226/NAMESPACE
set 14 21:37:34 jarvis systemd[1]: Unit caddy.service entered failed state.

Any suggestion?

So you get the 226/NAMESPACE error now. Did you google it? What did you try that didn’t help?

I guess you either didn’t set a hostname properly (→ hostnamectl), and invalid hostname (no FQDN, or a trailing dot), or didn’t enable systemd-hostnamed,
or have a kernel without everything needed for cgroups (custom kernel? old one? zgrep -F CONFIG_NAMESPACES /proc/config.gz? no support for private mounts?).

Hey Mark!

I spent the night trying to fix it. At the end I followed the tutorial step by step (using a new user www-data and not the pi user) and voilà! IT WORKS!

Thank you again!

1 Like