Let's Encrypt with DNS-01 on ER-X

Update on Apr 15, 2019: The script, letsencrypt-edgemax.sh has been updated to work on both FW 1.x and 2.x. Please pull it again from my GitHub if you have upgraded to FW v2.0.


This article assumes you already have configured a self-signed certificate for Edgemax GUI. If not, skim through my previous post to gain some background.

We want to replace a self-signed certificate with a certificate signed by Let's Encrypt that works for every single browser anywhere without any extra work. We'll go through the steps using now the de facto slim client, acme.sh, to create a Let's Encrypt certificate and to setup a cron task to renew and reload the certificate before its expiry.

In order for Let's Encrypt to issue a certificate of a given domain, we need to prove that the domain is indeed in our possession. Let's Encrypt offers multiple ways to do the verification (and acme.sh support all of them). We use DNS-01 which I found least work on user end. Many DNS providers support DNS-01. We use Cloudflare as an example.

Install acme.sh

SSH into ER-X, and sudo -i to gain root access. Then,

# download acme.sh archive from GitHub
cd /tmp
curl -L https://api.github.com/repos/Neilpang/acme.sh/tarball | tar xz

# run the installation
cd Neilpang-acme.sh-86dd290
./acme.sh --install --home /config/user-data/acme.sh

# clean up downloads
cd /tmp
rm -rf Neilpang-acme.sh-86dd290

Note that 86dd290 is the current git commit hash as of this writing. You're certainly going to see a different hash.

--home specifies where to install acme.sh. You can pick a different directory under /config. The sub-directory will be created automatically. For more advanced options of acme.sh installation, check here.

At the end of the installation, acme.sh recommends a daily cron job for certificate renewal. We won't use it. Instead we'll create a custom weekly job to renew and reload the certificate.

Issue a certificate with CloudFlare DNS-01

We assume you have added a domain, erx.yourdomain.com to your CloudFlare account and designate it to your ER-X. Note that if you don't have a public IPv4, a private address such as will also work on CloudFlare.

To issue a certificate:

. /config/user-data/acme.sh/acme.sh.env

export CF_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export CF_Email="[email protected]"

acme.sh --issue -d erx.yourdomain.com --dns dns_cf

CF_Email is the email address you have signed up with CloudFalre. CF_Key is available under CloudFlare portal > My Profile > Global API key.

When everything goes smoothly (and it should), we get a new certificate in about two minutes. Below is the output of a sample run:

[Mon Sep 11 14:05:25 UTC 2017] Registering account
[Mon Sep 11 14:05:27 UTC 2017] Registered
[Mon Sep 11 14:05:29 UTC 2017] Update account tos info success.
[Mon Sep 11 14:05:29 UTC 2017] ACCOUNT_THUMBPRINT='Pim77usItggUskHtYgtLnRGnjygggBBG1WvEXq1U'
[Mon Sep 11 14:05:29 UTC 2017] Creating domain key
[Mon Sep 11 14:05:30 UTC 2017] The domain key is here: /config/user-data/acme.sh/erx.yourdomain.com/erx.yourdomain.com.key
[Mon Sep 11 14:05:30 UTC 2017] Single domain='erx.yourdomain.com'
[Mon Sep 11 14:05:30 UTC 2017] Getting domain auth token for each domain
[Mon Sep 11 14:05:30 UTC 2017] Getting webroot for domain='erx.yourdomain.com'
[Mon Sep 11 14:05:30 UTC 2017] Getting new-authz for domain='erx.yourdomain.com'
[Mon Sep 11 14:05:32 UTC 2017] The new-authz request is ok.
[Mon Sep 11 14:05:32 UTC 2017] Found domain api file: /config/user-data/acme.sh/dnsapi/dns_cf.sh
[Mon Sep 11 14:05:34 UTC 2017] Adding record
[Mon Sep 11 14:05:38 UTC 2017] Added, OK
[Mon Sep 11 14:05:38 UTC 2017] Sleep 120 seconds for the txt records to take effect
[Mon Sep 11 14:07:40 UTC 2017] Verifying:erx.yourdomain.com
[Mon Sep 11 14:07:50 UTC 2017] Pending
[Mon Sep 11 14:07:52 UTC 2017] Success
[Mon Sep 11 14:07:57 UTC 2017] Verify finished, start to sign.
[Mon Sep 11 14:07:59 UTC 2017] Cert success.
[Mon Sep 11 14:07:59 UTC 2017] Your cert is in  /config/user-data/acme.sh/erx.yourdomain.com/erx.yourdomain.com.cer 
[Mon Sep 11 14:07:59 UTC 2017] Your cert key is in  /config/user-data/acme.sh/erx.yourdomain.com/erx.yourdomain.com.key 
[Mon Sep 11 14:08:00 UTC 2017] The intermediate CA cert is in  /config/user-data/acme.sh/erx.yourdomain.com/ca.cer 
[Mon Sep 11 14:08:00 UTC 2017] And the full chain certs is there:  /config/user-data/acme.sh/erx.yourdomain.com/fullchain.cer 

Renew and reload the certificate

Let's Encrypt certificates expire every 90 days. We need a weekly job to check and renew our certificate, and reload the certificate for Edgemax GUI if renewed.

I've written a script for this purpose. Modify variables home, domain and lighttpd_pem to suit your setup. lighttpd_pem is the full path to the certificate and private key in PEM format that Edgemax GUI loads. If you don't know, at the bottom of this article you'll find the CLI to configure such a path.

We can copy and paste or download the script from within ER-X:

cd /config/scripts

curl -O https://raw.githubusercontent.com/kvic-z/goodies-edgemax/master/letsencrypt-edgemax.sh

chmod a+x letsencrypt-edgemax.sh

For testing, uncomment "force=--force" in the script to force renew our certificate. Run it manually as non-root. You shall see Edgemax GUI restart with a renewed certificate at the end.

Now, let's schedule a weekly task for this:


set system task-scheduler task renew-letsencrypt
set system task-scheduler task renew-letsencrypt cron-spec "04 01 * * 1"
set system task-scheduler task renew-letsencrypt executable path /config/scripts/letsencrypt-edgemax.sh


We're all set. Enjoy!

comments powered by Disqus