acme.sh, plus Linode, plus DNS, plus FreeBSD

I’ve been meaning to use Let’s Encrypt for some time now, I don’t really have a good excuse as to why it’s taken so long, other than I wanted to use DNS to verify I owned the relevant domains, and I hadn’t found an easy enough tool to use.

My lame excuse faltered when Dan Langille ported the acme.sh client to FreeBSD.

It’s taken me a while to figure out exactly how I aught to use it, as I wasn’t 100% about what I was doing. But after a few false starts, I’ve placed my first certificates into use!

This post describes the steps I’ve taken to get the certs in place, and is mainly documentation for me later on. That said, I hope it’s general enough for others to find it helpful.

1. Installing

First off, we need to install acme.sh, so as root we can do the following:

# pkg install acme.sh

This does a number of things, but most importantly it creates an acme user with the relevant files to start configuring.

2. Configuration

Switching to the acme user, there should be an .acme.sh directory (note the leading full stop to make it hidden), and it is here we create our account.conf:

$ cat .acme.sh/account.conf
USER_PATH='/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/var/db/acme/bin'
LINODE_API_KEY='aVeryLongSeeminglyRandomString'
DEFAULT_DNS_SLEEP="900"
CERT_HOME="/var/db/acme/certs"
LOG_FILE='/var/db/acme/logs/acme.sh.log'

The LINODE_API_KEY is generated by going into the Linode Manager, clicking on “my profile”, and selecting “API Keys” from the submenu. Create a new key and make sure you save it, it won’t be shown in full again! The DEFAULT_DNS_SLEEP is set to 900 seconds (15 minutes) because this is the time between Linode DNS refreshes.

3. Issuing a certificate

Now we’ve done the configuration, we can issue the certificate:

$ acme.sh --issue --dns dns_linode -d bnix.club -d logs.bnix.club -d f.bnix.club -d www.bnix.club 
[Wed Nov 1 21:22:00 BST 2017] Creating domain key
[Wed Nov 1 21:22:00 BST 2017] The domain key is here: /var/db/acme/certs/bnix.club/bnix.club.key
[Wed Nov 1 21:22:00 BST 2017] Multi domain='DNS:logs.bnix.club,DNS:f.bnix.club,DNS:www.bnix.club'
[Wed Nov 1 21:22:00 BST 2017] Getting domain auth token for each domain
[Wed Nov 1 21:22:00 BST 2017] Getting webroot for domain='bnix.club'
[Wed Nov 1 21:22:00 BST 2017] Getting new-authz for domain='bnix.club'
[Wed Nov 1 21:22:02 BST 2017] The new-authz request is ok.
[Wed Nov 1 21:22:02 BST 2017] Getting webroot for domain='logs.bnix.club'
[Wed Nov 1 21:22:02 BST 2017] Getting new-authz for domain='logs.bnix.club'
[Wed Nov 1 21:22:03 BST 2017] The new-authz request is ok.
[Wed Nov 1 21:22:03 BST 2017] Getting webroot for domain='f.bnix.club'
[Wed Nov 1 21:22:05 BST 2017] The new-authz request is ok.
[Wed Nov 1 21:22:05 BST 2017] Getting webroot for domain='www.bnix.club'
[Wed Nov 1 21:22:05 BST 2017] Getting new-authz for domain='www.bnix.club'
[Wed Nov 1 21:22:06 BST 2017] The new-authz request is ok.
[Wed Nov 1 21:22:06 BST 2017] Found domain api file: /var/db/acme/.acme.sh/dnsapi/dns_linode.sh
[Wed Nov 1 21:22:06 BST 2017] Using Linode
[Wed Nov 1 21:22:08 BST 2017] Domain resource successfully added.
[Wed Nov 1 21:22:08 BST 2017] Found domain api file: /var/db/acme/.acme.sh/dnsapi/dns_linode.sh
[Wed Nov 1 21:22:08 BST 2017] Using Linode
[Wed Nov 1 21:22:09 BST 2017] Domain resource successfully added.
[Wed Nov 1 21:22:09 BST 2017] Found domain api file: /var/db/acme/.acme.sh/dnsapi/dns_linode.sh
[Wed Nov 1 21:22:09 BST 2017] Using Linode
[Wed Nov 1 21:22:11 BST 2017] Domain resource successfully added.
[Wed Nov 1 21:22:11 BST 2017] Found domain api file: /var/db/acme/.acme.sh/dnsapi/dns_linode.sh
[Wed Nov 1 21:22:11 BST 2017] Using Linode
[Wed Nov 1 21:22:13 BST 2017] Domain resource successfully added.
[Wed Nov 1 21:22:13 BST 2017] Sleep 900 seconds for the txt records to take effect
[Wed Nov 1 21:37:57 BST 2017] Verifying:bnix.club
[Wed Nov 1 21:38:01 BST 2017] Success
[Wed Nov 1 21:38:01 BST 2017] Verifying:logs.bnix.club
[Wed Nov 1 21:38:05 BST 2017] Success
[Wed Nov 1 21:38:05 BST 2017] Verifying:f.bnix.club
[Wed Nov 1 21:38:09 BST 2017] Success
[Wed Nov 1 21:38:10 BST 2017] Verifying:www.bnix.club
[Wed Nov 1 21:38:14 BST 2017] Success
[Wed Nov 1 21:38:14 BST 2017] Using Linode
[Wed Nov 1 21:38:16 BST 2017] Domain resource successfully deleted.
[Wed Nov 1 21:38:16 BST 2017] Using Linode
[Wed Nov 1 21:38:18 BST 2017] Domain resource successfully deleted.
[Wed Nov 1 21:38:18 BST 2017] Using Linode
[Wed Nov 1 21:38:20 BST 2017] Domain resource successfully deleted.
[Wed Nov 1 21:38:20 BST 2017] Using Linode
[Wed Nov 1 21:38:22 BST 2017] Domain resource successfully deleted.
[Wed Nov 1 21:38:22 BST 2017] Verify finished, start to sign.
[Wed Nov 1 21:38:24 BST 2017] Cert success.
-----BEGIN CERTIFICATE-----
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
v5y$RaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNgRaNdOmStRiNg
-----END CERTIFICATE-----
[Wed Nov 1 21:38:24 BST 2017] Your cert is in  /var/db/acme/certs/bnix.club/bnix.club.cer 
[Wed Nov 1 21:38:24 BST 2017] Your cert key is in  /var/db/acme/certs/bnix.club/bnix.club.key 
[Wed Nov 1 21:38:25 BST 2017] The intermediate CA cert is in  /var/db/acme/certs/bnix.club/ca.cer 
[Wed Nov 1 21:38:25 BST 2017] And the full chain certs is there:  /var/db/acme/certs/bnix.club/fullchain.cer 
[Wed Nov 1 21:38:25 BST 2017] And the full chain certs is there:  /var/db/acme/certs/bnix.club/fullchain.cer 

The command tells acme.sh to issue a new certificate using Linode DNS entries for the list of sites (each address is preceded with a -d). We now have a certificate sitting in the certs directory (as instructed in our account file). Now we just need to install the certificates.

4. Installing certificates

I’ve opted to allow the acme user to write to the directory where these certificates will be installed, these will then be readable by the www user that nginx runs as.

$ mkdir -p /usr/local/etc/ssl/bnix
$ acme.sh --install-cert -d bnix.club -d logs.bnix.club -d f.bnix.club -d www.bnix.club --leypatkeypath /usr/local/etc/ssl/bnix/privssl/bnix/fullchain.pem --reloadcmd "sleep 65 && touch /var/db/acme/.restart_nginx"
[Mon Oct 23 21:56:44 BST 2017] Installing key to:/usr/local/etc/ssl/bnix/privkey.pem
[Mon Oct 23 21:56:44 BST 2017] Installing full chain to:/usr/local/etc/ssl/bnix/fullchain.pem
[Mon Oct 23 21:56:44 BST 2017] Run reload cmd: sleep 65 && touch /var/db/acme/.restart_nginx
[Mon Oct 23 21:57:49 BST 2017] Reload success

You’ll notice the odd reload command there. I don’t want to give the acme user direct permission to restart nginx, so instead I wait for a time and create restart file. I think have the following script in my root users directory:

#!/bin/sh
if [ -f /var/db/acme/.restart_nginx ]; then
    service nginx force-reload
    rm -rf /var/db/acme/.restart_nginx
fi

The the following in /etc/crontab:

#minute hour    mday    month   wday    who command
*   *   *   *   *   root    /bin/sh /root/scripts/restart_nginx.sh

This means that every minute, root checks to see if that file is created, if it is then root restarts nginx and removes the file.

5. Renewing certificates

In order to renew certificates, the acme user must check once a day (using cron):

#minute hour    mday    month   wday    command
43 0 * * * /usr/local/sbin/acme.sh --cron --home "/var/db/acme/acme.sh"

This will cause cron to run the acme.sh script every day at 00:43

Please note: Please choose another time other than 00:43 to spread the load on both Linode’s DNS servers and the Let’s Encrypt servers.


comments powered by Disqus