Wildcard Let's Encrypt SSL Cert on Synology NAS
Photo by Matteo Bernardis on Unsplash
Thanks to this post on vdr.one I was able to set up a wildcard Let's Encrypt Cert on my Synology NAS.
The problem is I have to manually renew every 3 months which involves setting a new TXT record on my DNS and remembering the steps to renew.
After more research, I found a way to automate the renewal of my wildcard DNS. It does require a DNS server with API access. It turns out there are lots of options on the acme.sh wiki.
It would be nice if I could use GoDaddy or NameCheap, where I have most of my
domains, but this particular domain is hosted with iwantmyname. It looks like
there is no support in acme.sh
for iwantmyname, but
iwantmyname does have an API for adding a TXT record.
Luckily, acme.sh
has provided a solution to use my own API, so that is what
I'll do!
First, let's log into the NAS via ssh and install acme.sh
sudo -i
wget https://github.com/Neilpang/acme.sh/archive/master.tar.gz
tar xvf master.tar.gz
cd acme.sh-master/
./acme.sh --install --nocron --home /usr/local/share/acme.sh --accountemail "letsencryptemail@sample.com"
Now we'll create the script that will created our TXT record on iwantmyname. (If
you use some other DNS service that is already supported, you can skip this step
and replace dns_iwmn
with whatever DNS service you are using.)
touch /usr/local/share/acme.sh/dnsapi/dns_iwmn.sh
chmod +x /usr/local/share/acme.sh/dnsapi/dns_iwmn.sh
vim /usr/local/share/acme.sh/dnsapi/dns_iwmn.sh
I added the following to this script:
#!/usr/bin/env sh
# Guide: https://github.com/acmesh-official/acme.sh/wiki/DNS-API-Dev-Guide
#Usage: dns_iwmn_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_iwmn_add() {
local fulldomain=$1
local txtvalue=$2
_info "Using iwantmyname"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
curl -u "$IWMN_EMAIL:$IWMN_PASSWORD" "https://iwantmyname.com/basicauth/ddns?hostname=$fulldomain&type=txt&value=$txtvalue"
}
#Usage: fulldomain
#Remove the txt record after validation.
dns_iwmn_rm() {
local fulldomain=$1
_info "Using iwantmyname"
_debug fulldomain "$fulldomain"
curl -u "$IWMN_EMAIL:$IWMN_PASSWORD" "https://iwantmyname.com/basicauth/ddns?hostname=$fulldomain&type=txt&value=delete"
}
Now, let's run the following the command to issue the wildcard cert:
export CERT_DOMAIN="*.mydomain.tld"
export IWMN_EMAIL="iwantmynameemail@sample.com"
export IWMN_PASSWORD="iwantmyname-password"
/usr/local/share/acme.sh/acme.sh --issue -d $CERT_DOMAIN --dns dns_iwmn \
--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 \
--capath /usr/syno/etc/certificate/system/default/chain.pem \
--dnssleep 20 \
--config-home "/path/to/save/acmeconfigs/"
I found that after renewing a cert that my main domain pointing to my control
panel worked, but all my other reverse proxy subdomains were still pointing to
the expired certificate. After digging around I found the
/usr/syno/etc/certificate/ReverseProxy
directory. I added the following to my
script:
cd /usr/syno/etc/certificate/ReverseProxy/
ls -d $PWD/* | xargs -n 1 cp -v /usr/syno/etc/certificate/system/default/*.pem
This basically copies my renewed cert to each of my reverse proxy certificates directories.
So the full script now looks like this:
export CERT_DOMAIN="*.mydomain.tld"
export IWMN_EMAIL="iwantmynameemail@sample.com"
export IWMN_PASSWORD="iwantmyname-password"
/usr/local/share/acme.sh/acme.sh --issue -d $CERT_DOMAIN --dns dns_iwmn \
--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 \
--capath /usr/syno/etc/certificate/system/default/chain.pem \
--dnssleep 20 \
--config-home "/path/to/save/acmeconfigs/" && \
cd /usr/syno/etc/certificate/ReverseProxy/ && \
ls -d $PWD/* | xargs -n 1 cp -v /usr/syno/etc/certificate/system/default/*.pem && \
cd -
Now I just run this script regularly by adding the following to /etc/crontab
to keep the cert renewed:
0 2 */10 * * root /path/to/cert_install.sh >/dev/null 2>&1
NOTE: When I add a new reverse proxy, I need to copy the wildcard cert to
the new reverse proxy directory. Because I don't know what the directory name is
exactly, I just put the snippet above (added again below) in a script named
update-reverse-proxies.sh
and it will copy the wild copy the cert to all the
reverse proxies again.
cd /usr/syno/etc/certificate/ReverseProxy/
ls -d $PWD/* | xargs -n 1 cp -v /usr/syno/etc/certificate/system/default/*.pem
💥👊