There are many other ACME clients out there, here’s a list https://letsencrypt.org/docs/client-options/#acme-v2-compatible-clients but I likeacme.sh
because it saved me one day when I was desperately searching for a tool I could use without having to fumble with
package managers, so we will explore some more of its capabilities now.
I did all of this as root on a Vultr VM. Install acme.sh
per https://github.com/acmesh-official/acme.sh/wiki/How-to-install
Let’s experiment with the DNS API feature of acme.sh
per the documentation here https://github.com/acmesh-official/acme.sh/wiki/dnsapi
To take advantage of this, we must start using Cloudflare for DNS. We want to use this for a few reasons:
- No need to listen on a port on a server to generate valid certs. In fact you don’t need any records in your zone at all to do this!
- We want to generate wildcard certificates. Only the DNS API appears to support this feature, so we need a compatible DNS provider with an API supported by
acme.sh
, hence Cloudflare.
If your domain belongs to some other registrar, you can switch your nameservers over to Cloudflare.
This is important as Cloudflare’s DNS API is well-supported by acme.sh
as this article will demonstrate.
Generate an API token at Cloudflare here https://dash.cloudflare.com/profile/api-tokens
This is one of three inputs required by acme.sh
; in these next few steps we wish to establish these environment variables. Once you issue the cert, they will be stored in acme.sh
‘s configuration for future use.
1 | export CF_Token="" # API token you generated on the site. It should have Zone.DNS edit permission for at least one Zone being the domain you're generating certs for |
Once you have set your API token the following will help you get the remaining two. You may want to apt install -y jq
if you’re pasting these commands so the JSON is parsed out for you.
1 | curl -X GET "https://api.cloudflare.com/client/v4/zones" -H "Authorization: Bearer $CF_Token" | jq |
If you can’t read jq
selectors, you will now, as I’m showing you which key paths get you the AccountID and ZoneID below:
1 | zone id: ... | jq '.result[0].id' |
1 | account id: ... | jq '.result[0].account.id' |
Export those variables too and now you can move on to issuing the cert.
1 | acme.sh --issue -d keyvan.pw -d '*.keyvan.pw' --dns dns_cf |
We got our cert! Install apache now too, enabling SSL while we’re at it.
1 | apt install -y apache2 |
Decide on a location where the certs should be installed to by acme.sh
and read from by apache, I’m choosing the following:
mkdir -p /etc/ssl/keyvan.pw
Make apache point to the files that will exist there very soon. I did this in the default-ssl virtual host apache creates:
1 | SSLCertificateFile /etc/ssl/keyvan.pw/keyvan.pw.cer |
Now we will use acme.sh
to install the certs. acme.sh
is storing all this information for future runs, it’s nice like that.
1 | acme.sh --install-cert -d keyvan.pw -d '*.keyvan.pw' \ |
Confirm it worked by hitting the website. Did you even bother creating your A record yet? I hadn’t yet at this point. This is a nice aspect of using DNS API. It is nice not to actually need a server, yet simply show ownership of the DNS.
Pretty amazing… people used to pay a lot of money and go through a lot more hassle to get this capability. But now within minutes I have proper wildcard and naked domain encryption.
Let’s install the cron so this automatically renews.
1 | 0 0 * * * acme.sh --cron |
Nice. We can test it with –force too, which I have done. It seems that acme will do everything per previous commands upon renewal including running your reloadcmd, e.g.:
[Sun 12 Sep 2021 02:38:25 AM UTC] Your cert is in: /root/.acme.sh/keyvan.pw/keyvan.pw.cer
[Sun 12 Sep 2021 02:38:25 AM UTC] Your cert key is in: /root/.acme.sh/keyvan.pw/keyvan.pw.key
[Sun 12 Sep 2021 02:38:25 AM UTC] The intermediate CA cert is in: /root/.acme.sh/keyvan.pw/ca.cer
[Sun 12 Sep 2021 02:38:25 AM UTC] And the full chain certs is there: /root/.acme.sh/keyvan.pw/fullchain.cer
[Sun 12 Sep 2021 02:38:26 AM UTC] Installing cert to: /etc/ssl/keyvan.pw/keyvan.pw.cer
[Sun 12 Sep 2021 02:38:26 AM UTC] Installing key to: /etc/ssl/keyvan.pw/keyvan.pw.key
[Sun 12 Sep 2021 02:38:26 AM UTC] Installing full chain to: /etc/ssl/keyvan.pw/fullchain.cer
[Sun 12 Sep 2021 02:38:26 AM UTC] Run reload cmd: systemctl reload apache2
[Sun 12 Sep 2021 02:38:26 AM UTC] Reload success
[Sun 12 Sep 2021 02:38:26 AM UTC] ===End cron===
SSL has never been so cheap, easy, and automatable…