Lego – Automatic SSL Certificates and HTTPS for everyone and everywhere

Lego - Automatic Certificates and HTTPS for everyone.

Lego is a Let’s Encrypt client written in Go, hence the name. It serves as an alternative to Let’s Encrypt’s own client certbot which can be found in many Linux distribution repositories to install. It is relatively simple to handle and manages SSL certificates just fine, as long as the domain is publically reachable, meaning you can reach it from anywhere by just putting it in your browser. So using certbot is usually fine and works for the occasion.

But what about domains that are not public? Like for your own local development? Usually, these domains look like wordpress.local for example and you won’t get SSL certificates for them. That is because they only exist in your local network and certbot can’t reach them for its DNS challenge. In other words, certbot can’t verify them and cannot create an SSL certificate for them.

Sure, you can try to trick certbot a bit by using a subdomain of your live domain for example and use certbot with the --certonly option. That works somehow, but the SSL certificate generated this way can’t be renewed automatically and you have to do this dance every 3 months. Pretty annoying, trust me, been there, done that.

Now wouldn’t it be nice if there is a way to get proper SSL certificates for your local domains as well and renew them automatically? Yes, it would, and there is! Lego to the rescue!

First off, some assumptions and preparations. This still will not work with a .local domain. You need a valid live domain, in my case ppfeufer.de. And this domain needs to be with a provider that is in Logo’s list of DNS Providers. Because what Lego does is, query your DNS provider and obtain the certificate for you.

So, let’s play this step by step on an example in my case. My local WordPress development is wp-local.ppfeufer.de and I like to have an SSL certificate for it. Why? Because I’d like to test if everything works with SSL, simple as that. Also, it’s 2022, no reason not to have SSL certificates, even for local domains :-P

Another assumption we have to make is that you are working on a Linux system. I have no idea how and even if this all will work on Windows at all. Sorry.

Install Lego

First, you need to install Lego. This can be done by simply cloning their GitHub repository and installing it from there.
Make sure you have Golang (>=1.17) installed as well, it’s needed, we’re installing a piece of software written in Go after all.

Clone the GitHub repository into a directory of your choice with:

git clone git@github.com:go-acme/lego.git

Now let’s change into the repository and compile the Lego client.

cd lego
make build

This will take a while. This command pulls all the needed Go modules and compiled the Lego client, which can be found in the dist directory when done.

Now that the Lego client has been compiled, you’ll find it in the dist directory inside the git repository. Go ahead and make the file executable if it isn’t already (Seems to be depending on the distribution)

chmod +x lego

Making it available on the system

After successfully compiling the Lego client, it needs to be made available to the command prompt. This means we have to move it somewhere where it can be executed by simply typing lego in our console. I for once have it in /usr/bin/, just a personal preference.

cd /usr/bin/
ln -s /path/to/the/legorepository/dist/lego .

As you can see, I’m not moving the file, I just link it. This has the advantage that when I update the Lego client, I don’t have to copy or move the file again. It’s linked and with that, it will always be the up-to-date version.

Usage

Now that the preparations are done, time to use the Lego client.

Pick your DNS provider from this list right here, the one I use in this example is Hetzner and as you can see, there is already an example given on how to obtain the SSL certificate.

Example:

cd /home/your_username

HETZNER_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
lego --email your@email.com --dns hetzner --domains your.domain.com run

Of course, you need an API key from Hetzner first, which you can create in your DNS console on Hetzner’s website. Make sure to never share this key with anyone!

Now you’ve got an SSL certificate which you can configure your web server with.

All you need to do is add an entry to your /etc/hosts file, to make sure your local machine doesn’t bother your ISP’s DNS server for the domain name and resolves it locally.

My example:

127.0.0.1    your.domain.com

From now on, every time your local machine queries this domain it resolves to its local address where your web server is listening.

Renew the certificate

Let’s Encrypt SSL certificates are valid for 3 months, so it needs to be renewed regularly. For this it’s best to make use of a cron task.

Add the following to your crontab:

##
# Certbot for renewing SSL certificates
##
0 */6 * * * /home/your_username/.lego/renew-scripts/01_your.domain.com

As you can see, we make use of a shell script here. Change the file name to whatever you think is best.

The shell script we call with the cron task looks like this:

#!/bin/bash

LEGO_ACCOUNT_EMAIL=your@email.com
LEGO_CERT_DOMAIN=your.domain.com

cd /home/your_username

HETZNER_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
/usr/bin/lego -email ${LEGO_ACCOUNT_EMAIL} --dns hetzner --domains ${LEGO_CERT_DOMAIN} renew --days 10 --renew-hook /home/your_username/.lego/hooks/renew/01_your.domain.com

And the last thing needed is to let Lego know what to do when the certificate has been renewed. For this, a renew-hook (File: /home/your_username/.lego/hooks/renew/01_your.domain.com) needs to be created.

#!/bin/bash

systemctl restart apache2 # example for restarting Apache2 web server

Both script files need to be executable, so run:

chmod +x /home/your_username/.lego/renew-scripts/01_your.domain.com
chmod +x /home/your_username/.lego/hooks/renew/01_your.domain.com

Update the Lego Client

Updating the Lego client is pretty straightforward. All you need to do is pull the latest from GitHub and compile it again.

cd /path/to/the/legorepository/
git pull
make build

That’s it.

Leave a Reply