SSL certificate for Unifi controller in Synology docker container

I guess the topic perfectly describes what this post is about.

First and foremost, this whole blog idea is just a way for me to easily find this info again, in case I need it.

Secondly, hopefully this info helps you out too, in case you want to have a valid SSL certificate for your Unifi Controller. Which is running in a Docker container. On your Synology NAS.

The actual and useful info starts here.

Ok, first we need to establish a few facts/prerequisites.

  1. I’m running the latest jacobalberty/unifi image. These instructions might work with other images, just make sure the path to the keystore is correct.
  2. You need to install the Java8 package on your Synology. It contains the important keytool command. Without it, you can skip reading the rest of this post.
  3. I’m assuming you have acme.sh already installed on your Synology NAS. If not, check out this post.
  4. In this post I’m using unifi.domain.com as an example, replace it in code snippets and commands with your FQDN.
  5. The path to the keystore in my examples, /volume1/docker/Unifi/Data, is also an example and should be replaced with the correct path.
    I have created a folder in File Station called “docker”, which contains various docker container paths. The Unifi container has mapped paths like this:

If you have all that, it’s time to enable the SSH service to your Synology NAS and start a root session (you can’t log in as root, you’ll have to login as an admin user and sudo su – to root).

Start by creating the following script.

Use your favorite text editor to create and edit /usr/local/share/acme.sh/unifi-renew-hook.sh, then enter the following:

#!/bin/bash
# Renew-hook for ACME / Let's encrypt
echo "** Configuring new Let's Encrypt certs"
cd /volume1/docker/Unifi/Data/
rm -f unifi.p12 unifi.key unifi.crt

openssl pkcs12 -export -in /usr/local/share/acme.sh/unifi.domain.com/unifi.domain.com.cer -inkey /usr/local/share/acme.sh/unifi.domain.com/unifi.domain.com.key -out unifi.p12 -name unifi -password pass:aircontrolenterprise

keytool -importkeystore -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore keystore -srckeystore unifi.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -alias unifi -noprompt

rm -f unifi.p12

echo "** Restarting container"
docker restart jacobalberty-unifi

Save and exit the text editor.

Run the command to issue the certificate for the first time.

The command below will request the first certificate and create a configuration file for acme.sh.
The –pre-hook command will run each time the certificate is renewed. In this case it will create a backup of the Unifi configuration backups and the keystore.
The acme.sh script saves the CSR, certificate and key files under /usr/local/share/acme.sh/unifi.domain.com/, so you can always retrieve them. The –fullchainpath and –keypath parameters copy the certificate and key files to the specified paths. We’re not using these files here, but they might come in handy some time.

acme.sh --force --issue --dns dns_cf -d unifi.domain.com --home /usr/local/share/acme.sh \
    --pre-hook "tar zcvf /usr/local/share/acme.sh/UnifiKeySSL_`date +%Y-%m-%d_%H.%M.%S`.tar.gz /volume1/docker/Unifi/Data/backup /volume1/docker/Unifi/Data/keystore" \
    --fullchainpath /volume1/docker/Unifi/Data/unifi.crt --keypath /volume1/docker/Unifi/Data/unifi.key \
    --reloadcmd "sh /usr/local/share/acme.sh/unifi-renew-hook.sh" \
    --dnssleep 20

Auto-renewing the certificate.

If you haven’t set this up yet, take a look at my previous post.

You only need 1 single Scheduled Task to update all Let’s Encrypt certificates on the same system.

You might want to disable the SSH service when you’re done.

That’s all there is to it.

Credits:

I got my inspiration from naschenweng.info‘s post about Securing Ubiquiti UniFi Cloud Key with Let’s Encrypt SSL.

Follow-up post: automatically renew Let’s Encrypt certificate on your Synology

If you haven’t installed the acme.sh tools on your Synology yet, check out this post first.
If you have, then the next part might be of interest to you!

On DSM 6.x it’s not possible to use cron tasks, so you’ll have to use the DSM’s Task Scheduler, which does essentially the same.

Open your Control Panel and go to the Task Scheduler item under System.

Create a new User-defined task:

 

Configuring General task settings:

Enter an identifiable Task name, leave the User as root:

Configuring the task Schedule:

I let the task run weekly, because I think that will cause the certificate to renew on time, but the default setting is to run the task daily.
Configure it to your own preference (keep in mind though that Let’s Encrypt certificates need to be renewed every 3 months.

Configuring the actual command to run:

The last tab contains the actual command to run. You can choose to be notified by email on every execution of the task, or when it terminates abnormally.
In which case you might need to do this manually for some reason.

Assuming you installed acme.sh as root, the following command will renew the certificate when needed:

/usr/local/share/acme.sh/acme.sh --cron --home /usr/local/share/acme.sh

Note that the path in the screenshot is incorrect.

This script will also restart the DSM webserver, so if everything goes well you should never have to look at this again!

Enjoy your free SSL certificate.

Let’s Encrypt and Synology DSM 6.1+

If you’re like me and have your Synology NAS safely on your local network, without it being accessible from the big bad internet, you’ll likely find this post quite interesting.

I have encountered a few blogs with different approaches to solve the Let’s Encrypt issue on the latest current DSM release, version 6.1.

None of the solutions I found worked for me, because either the commands were outdated or they were referring to a cronjob, that is no longer available.

In this blog, I am assuming you have your DNS and Cloudflare already set up.
Below are the steps I took to get Let’s Encrypt! working on my Synology DS1515+.

Installing acme.sh and getting your SSL certificate

First, install acme.sh as root (log in SSH using your admin account):

curl -L -o /tmp/master.tgz https://github.com/Neilpang/acme.sh/archive/master.tar.gz
tar xvf /tmp/master.tgz
cd acme.sh-master/
sudo ./acme.sh --install --nocron --home /usr/local/share/acme.sh --accountemail "[email protected]"

Let acme.sh update itself:

sudo acme.sh --upgrade --auto-upgrade

Configure your Cloudflare API account.
Edit /usr/local/share/acme.sh/account.conf with your favorite editor and put this in:

ACCOUNT_EMAIL='[email protected]'
 
export CF_Key="MyCloudFlare-Global-API-Key"
export CF_Email="MyCloudFlare-Account-Email-Address"

Here is the final command that actually works.

acme.sh --issue -d fqdn.domain.com --home /usr/local/share/acme.sh \
    --dns dns_cf --cert-file /usr/syno/etc/certificate/system/default/cert.pem \
    --key-file /usr/syno/etc/certificate/system/default/privkey.pem \
    --ca-file /usr/syno/etc/certificate/system/default/syno-ca-cert.pem \
    --fullchain-file /usr/syno/etc/certificate/system/default/fullchain.pem \
    --reloadcmd "/usr/syno/etc/rc.sysv/nginx.sh reload" --dnssleep 10

And that’s it, now you have a valid Let’s Encrypt SSL certificate on your Synology DSM.

Edit:

If you want to automatically renew the certificate, check out my follow-up post.

 

Sources:

Some snippets were borrowed from this blog and from the acme.sh author mentioned below:
https://www.naschenweng.info/2017/01/06/automatic-ssl-renewal-encrypt-dsm-5-x-synology-ds1010-dns-01-verification/
https://github.com/Neilpang/acme.sh/wiki/Synology-NAS-Guide

This is the last command used on naschenweng’s blog, it works on DSM 5.2:

acme.sh --issue --post-hook "kill -USR1 `cat /run/httpd/httpd-sys.pid`" -d muffinstation.naschenweng.info --dns dns_cf --certpath /usr/syno/etc/ssl/ssl.crt/server.crt --keypath /usr/syno/etc/ssl/ssl.key/server.key --fullchainpath/usr/syno/etc/ssl/ssl.intercrt

And this is the last command taken from Neilpang’s github documentation:

acme.sh --issue -d YOURDOMAIN.TLD --dns dns_cf --certpath /usr/syno/etc/certificate/system/default/cert.pem --keypath /usr/syno/etc/certificate/system/default/privkey.pem --fullchainpath /usr/syno/etc/certificate/system/default/fullchain.pem --reloadcmd "/usr/syno/etc/rc.sysv/nginx.sh reload" --dnssleep 10