Using Caddy to deploy / renew Synology DSM certificate

If you already have Caddy running inside Container Manager (Docker) on your Synology DSM, you can use the TLS key and certificate from Caddy and deploy it to Synology DSM.

That will allow you to

  • avoid exposing your Synology DSM directly to the Internet just so you can get a Let’s Encrypt certificate via Synology’s HTTP-01 challenge.
  • use your own domain for a wildcard certificate, rather than having to use Synology DDNS domain.

To achieve that, you can use Synology Certificate Deployer (synology-cert-deploy.sh) which will help you take the existing Caddy certificate and deploy it to Synology DSM.

In my case, I’m using Caddy Web Server with ACME-DNS Provider, but you can easily adjust the script to any provider of your preference. The script requires two settings:

new_key="/path/to/your/privkey.pem"
new_fullchain="/path/to/your/fullchain.pem"

Assuming you have the following Caddy configurations:

docker-compose.yml :

services:
  caddy:
    image: timelordx/caddy-dns-acmedns:latest
    container_name: caddy
    environment:
      - PUID=YOUR_UID
      - PGID=YOUR_GID
      - TZ=YOUR_TZ
    volumes:
      - /volume1/docker/caddy/etc/caddy:/etc/caddy:ro
      - /volume1/docker/caddy/config:/config
      - /volume1/docker/caddy/data:/data
      - /volume1/docker/caddy/logs:/logs
    network_mode: host
    restart: unless-stopped

Caddyfile:

example.com, *.example.com {

	tls {
		...
	}

	...
}

you can proceed to configure the synology-cert-deploy.sh script:

SCRIPT CONFIG:

new_key='/volume1/docker/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.example.com/wildcard_.example.com.key'
new_fullchain='/volume1/docker/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.example.com/wildcard_.example.com.crt'

With the above configuration, the script will deploy a wildcard TLS certificate *.example.com from your Caddy server to your Synology DSM.

Ensure you run the script with root privileges (using sudo) to avoid any permission issues during the certificate deployment process. For automated execution, consider setting up the script as a Scheduled Task in Task Scheduler to run as root once a week.

For additional details on setting up Caddy with an ACME-DNS provider, please refer to the following links:

More details about Caddy as a certificate manager:

FYI there’s no guarantee that this will continue to work because you’re hard-coding the issuer path. If Caddy uses ZeroSSL to issue a cert instead, then this would fail.

The better thing to do is make use of the cert_obtained event and the exec event handler to run your script, using the event payload to get the correct path to the cert. See Global options (Caddyfile) — Caddy Documentation

1 Like

It’s been working for me as it is right now for quite some time now, but I see what you mean. And thank you for pointing out “on cert_obtained exec” to me. I didn’t know about that config stanza.

The only problem with “on cert_obtained exec” is that I cannot run my script from inside of the Caddy container. I wouldn’t be able to restart services outside of the container. But what I can do is to create a very simple script that would just copy the newly obtained key/cert via “on cert_obtained exec” to a known location (persistent volume) that my script can reach from outside of the container. I like it! I’ll update my docs to make use of “on cert_obtained exec”.

You could also write your own plugin that can react to events in a different way (HTTP request? write a message to a unix socket bind mounted from the host? whatever).