I’ve been wanting to experiment with SSL certificates for some time. I’ve run up an internal CA and done things that way but I’ve always found it a pain to import root certificates for clients. On the other hand though, I’m also a cheap man and don’t want to pay a lot for SSL certificates. For those reasons, I decided to give LetsEncrypt a go.
I’ve loved the idea of LetsEncrypt for a while. The web should be a more secure place and it shouldn’t cost and arm and a leg to make it that way. Luckily I had an existing domain that was parked for the time being and perfect to use for the test.
Before jumping into my experience, I need to briefly explain how LetsEncrypt works. It’s essentially a free service that is a trusted CA and will issue certificates for a given domain. In order to do that however, it needs to verify that you own the domain. The two options for this are:
– Web method
– DNS challenge method
To use the web method, you simply ensure that the DNS record for the domain is directed to your external IP address which you’re issuing the request from and forward port 80 to your internal server that is performing the request.
The DNS challenge method on the other hand requires you to update your domain with a TXT record containing some specific text (provided by the LetsEncrypt backend). It will then verify that the text is there, thus confirming that you must own the domain.
My first hurdle was that I needed an always-on host to run this from. Given my ESXi server is rarely turned on except for when I’m tinkering, the only option was my Raspberry Pi. The next issue was that the ‘easy method’ for LetsEncrypt requires port 80 to be open and directed to the internal server. My Raspberry Pi is already running a web service for PiHole which I didn’t want exposed to the Internet so I needed an alternate method. Therefore, I decided to go with the DNS challenge method.
The DNS challenge method is perfectly fine for this use-case provided it can be automated. Upon researching, I found that the original provider that I purchased the domain through doesn’t provide any automated way to interact with their DNS. So instead, I moved the DNS hosting to cloudflare which has an inbuilt API for updates. After that, the rest of the process was very simple.
1. Generate an API Token within Cloudflare and verify it’s ready for use
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer <token>" \
-H "Content-Type:application/json"
{"result":{"id":"<ID>","status":"active...}
2. Save you API token into a file and store it somewhere secure. In this example, the file is called “cloudflare-api-token.ini” and should be stored somewhere secure. The file itself should contain the following:
dns_cloudflare_api_token = <PutYourApiTokenHere>
2. Install the Certbot Python package with inbuilt Cloudflare API’s. In my circumstance, I received an error regarding pyopenssl being too old and so needed to install a new version of this too.
sudo apt update && sudo apt upgrade
sudo apt install python3-pip
sudo python3 -m pip install certbot certbot-dns-cloudflare
git clone https://github.com/cloudflare/python-cloudflare
sudo python3 -m pip install pyopenssl << I needed to run this, you may not need to
cd python-cloudflare/
python3 setup.py build
3. Request a certificate
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /<location>/cloudflare-api-token.ini -d <pihole.example.com>
4. Install the certificate. The steps for this will vary depending on which application you need to install it for. Google will be your friend for this. For me, it was PiHole itself and therefore I needed to update the lighttpd configuration file and restart the service.
5. Verify the certificate – Navigate to the web page using HTTPS and look for the padlock.
6. Setup auto-renew. This is a simple as creating a cron job as below to ensure the cert is renewed before expiry. Be aware however that you will have to install the certificate after renewal (each 3 months). This can be done using hooks. – https://certbot.eff.org/docs/using.html?highlight=hook#pre-and-post-validation-hooks
44 3 2 * * root certbot renew
And that’s it. Just like that the website is secure. You can also use this method to obtain a wildcard certificate for the domain that you can use across multiple applications.
Reference doc: https://www.jpaul.me/2020/09/how-to-use-a-cloudflare-api-token-for-letsencrypt-validation-on-ubuntu-20-04/