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.
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
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 192.168.1.1 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. -----BEGIN CERTIFICATE----- MIIE+zCCA+OgAwIBAgISA8E7yVjrFhYa7NXWQvgNILafMA0GCSqGSIb3DQEBCwUA MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzA5MTExMzA4MDBaFw0x NzEyMTAxMzA4MDBaMBcxFTATBgNVBAMTDGVyeC5rYXpvby5nYTCCASIwDQYJKoZI b3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzANBgkq hkiG9w0BAQsFAAOCAQEAm9F80Zartnr+WjWb2vxx5BBiwyvEX/s0z9KDB+MifyiK 28bJ9Y0PTZGm+b9kWCcDUthmg9OLkzWXLCJZrpWCCxfLguoM5pYR4wCk5xcUirW7 M4g7tvwKylwN75L0Qz9balWAkA5VITO2hEu0IkUzMaxxdmtQ2Q73WZhx1JM4l8Ni Xc7kZpGv2euWUq+5hsLAC7DumBexsGW96WnGEUYREc2Q4CSVmNwEX+Hv45XzgCQ6 MW8GZkbw95gPlQ+xfZ3zIJF18TN6gChg8B47BBfu0LrIFUlQOPIFwpcwSCP53EKz Jzx2woAkZ+NarxtMWugW0dAtZPgY3MkVC64DfzZMNA== -----END CERTIFICATE----- [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
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:
configure 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 commit save exit
We're all set. Enjoy!