Many of you know the problem: you just want to make a small adjustment on your VPS or homelab and than you stumble upon this unsolved problem you dont have the motivation to tackle for the last couple of months.
That happened to me today, i just wanted to test a new piece of software for which i needed a TLS certificate. No big deal, but than i have seen that the Certbot on my Debian Bookworm stull suffers a nasty bug and does not cleanup the TXT records for the DNS-01 challange after retrieving a new cert: https://github.com/certbot/certbot/issues/10492
Yes i know, that is only a cosmetic problem. But it is not the only problem i had with certbot in the last couple of months. In march i had the problem of the broken OVH DNS Addon in Debian Trixie.
To solve the problem i could have switch over to the certbot docker install, like i have done on my Debian Trixie machine, but that introduces another problem. One of my domain is managed via desec.io, a cool free german DNS hosting service. The problem is there is no official docker for their DNS-01 addon, which means i would have to maintain my own docker image for that. Sorry i but i dont want to do that.
So what to do now? I didnt wanna mess with Python virtual environments so a native install of certbot is a nogo. I remembered that in march someone told me about Lego an acme client written in Go, with a massive amount of supported DNS-01 capeable DNS providers. One thing i really like about it is that it is only one static go binary. Really easy to update without messing with the package management. Maybe in the foreseeable future i will craft a small bash script that does the updates.
At the first glimpse it seemed rather complicated to work with the config file, but when you break it down it is really good structured and easy.
In my case i have two providers that verify via DNS-01 and one that verifies via http-01 webroot challenge. So the acme client never has to bind to port 80 which means not interruption while getting new certs.
Getting it running is quite easy. Download the Lego binary from github, unpack it, move it to a suitable location (i chose /usr/local/sbin) and make it executeable. After that i created the folder /etc/lego to hold all the configs and the certificates.
What you can directly do is generating an account:
lego accounts register --email johndoe@example.com -a --path /etc/lego
How to proceed depends on the verification challenges you need to use. Just an example what i did for my OVH domains which i use with DNS-01. I am working with .env- Files for storing credentials of my DNS Provider. So generate a file called /etc/lego/.env.ovh and fill it with the credentials described in the Lego wiki in my case Application Key, Application Secret, Consumer Key and the endpoint: https://go-acme.github.io/lego/dns/ovh/index.html
Now i can get my first certificate:
lego run --email johndoe@example.com --path /etc/lego -a --dns ovh -d test.example.ovh --env-file /etc/lego/.env.ovh
Lego will store the certs in /etc/lego/certificates
But now i want to automate that so i will craft a lego.yaml in /etc/lego which tells Lego how to handle multiple domains verification methods etc. Mine looks like this:
storage: /etc/lego/
accounts:
johndoe@example.com:
email: johndoe@example.com
acceptsTermsOfService: true
challenges:
desec:
dns:
provider: desec
envFile: /etc/lego/.env.desec
resolvers:
- 1.1.1.1:53
ovh:
dns:
provider: ovh
envFile: /etc/lego/.env.ovh
resolvers:
- 1.1.1.1:53
webroot:
http:
webroot: /var/www/lego # Needs to be deliverd by webserver
certificates:
test.example.desec: #Free name to choose, will be the name of certifcate file
challenge: desec
domains:
- test.example.desec
test.example.ovh:
challenge: ovh
domains:
- test.example.ovh
- www.test.example.ovh
test.example.webroot:
challenge: webroot
domains:
- test.example.webroot
This is just an example, definately have a look into the Wiki, and remember its yaml, so only spaces, no tabs etc.
If you have setup the config file like this you can simply get or renew certificates colling lego only with the config as argument:
lego --config /etc/lego/lego.yaml
For me in my case i have than just created a systemd timer and a service unit so Lego runs periodically. They are stored in /etc/systemd/system/lego-renew.timer and /etc/systemd/system/lego-renew.service:
[Unit]
Description=Lego Certificate Renewal Timer
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
and
[Unit]
Description=Lego Certificate Renewal
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/lego --config /etc/lego/lego.yaml
ExecStartPost=systemctl reload nginx
Now we reload the systemd daemon, start and enable the timer:
systemctl daemon-reload
systemctl enable lego-renew.timer
systemctl start lego-renew.timer
And that it. Now Lego should take care of your certificates. Of course you now have to change your nginx etc. config files to point to the new location of the certificates, yeah there was a reason why i postponed that task so long.
I hope this post could help someone or is at least interesting. If not: at least i know what i have done here in six months.