Caddy vs inotify — 2

This is a continuation of my previous topic, Caddy vs inotify.

I just wanted to share a solution for providing TLS certificates for non-HTTPs services that relies on systemd.path mechanism.

Given two units are in place, /etc/systemd/system/tls@.path:

[Unit]
Description=Caddy TLS hook - %i

[Path]
PathChanged=/var/lib/caddy/certificates/acme-v02.api.letsencrypt.org-directory/%i/%i.json

[Install]
WantedBy=multi-user.target

and /etc/systemd/system/tls@.service:

Description=Caddy TLS hook - %i
AssertPathExists=/var/lib/caddy/certificates/acme-v02.api.letsencrypt.org-directory/%i/%i.crt
AssertPathExists=/var/lib/caddy/certificates/acme-v02.api.letsencrypt.org-directory/%i/%i.key

[Service]
Type=oneshot
Environment="TLS_DOMAIN=%i" "TLS_CERT=/var/lib/caddy/certificates/acme-v02.api.letsencrypt.org-directory/%i/%i.crt" "TLS_KEY=/var/lib/caddy/certificates/acme-v02.api.letsencrypt.org-directory/%i/%i.key"
ExecStart=/usr/lib/caddy-tls-hooks/%i

one enables the path unit, say, systemctl enable --now tls@example.com, and once Caddy renews TLS certificate, /usr/lib/caddy-tls-hooks/example.com script will be triggered. In that script the admin is free to shuffle certificate files for whatever daemon they need, and also reload/restart the daemon to make a new certificate effective.

An abstract example of /usr/lib/caddy-tls-hooks/example.com for an abstract postfix setup:

#!/usr/bin/env bash

cp ${TLS_CERT} ${TLS_KEY} /var/lib/postfix/tls
chown postfix: /var/lib/postfix/tls/${TLS_DOMAIN}.crt /var/lib/postfix/tls/${TLS_DOMAIN}.key
chmod 400 /var/lib/postfix/tls/${TLS_DOMAIN}.crt /var/lib/postfix/tls/${TLS_DOMAIN}.key
systemctl reload postfix || true

Comments and feedback are appreciated.

1 Like

I’ve changed the category to Wiki because you’re sharing a solution and an approach to how to implement a particular usage. It’s very neat setup!

FYI, Caddy may choose to use ZeroSSL instead of Let’s Encrypt based on a few different factors. In that case, this setup would break.

Our recommended approach is to use events.

Yup, I totally get it, but OTOH IIUC events requires 3rd-party modules right now to be useful, and for me personally it’s not a quite go ATM.

As for ZeroSSL, I’d appreciate knowing more about a) “few different factors”; and b) what changes with regard to certificate path so that the .path unit can be adapted as and if needed.

Many thanks for your inputs.

See Automatic HTTPS — Caddy Documentation which explains. Basically, LE is tried first by default, but if anything ever fails for any reason (transient network issues, rate limiting, LE downtime) then it’ll swap over to ZeroSSL to try that instead.

You can turn off ZeroSSL by specifying the issuer in your config to only use LE, but I don’t recommend that because you’d be making your Caddy server more brittle.

The problem is ZeroSSL certs will use a different filesystem path (i.e. with the ZeroSSL domain as the directory) so your setup would fail to detect that.

Yes, but if a fallback is disabled, caddy will still gracefully retry to obtain certificates with the only issuer configured anyway.

Will the ZeroSSL certs be saved into /var/lib/caddy/certificates/acme.zerossl.com-v2-DV90?

I don’t remember the exact path off-hand, but something like that yes.

Ack, thank you.

FWIW, I’ve also realised tls@.path needs Before=caddy.service to avoid a situation when caddy starts and (re)obtains a certificate, and then .path unit starts and misses this event.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.