When I started using OpenBSD for my web servers a couple months back I had some difficultly getting certificates from acme-client
to be signed by Let’s Encrypt.
This is a short tutorial on how to get everything running.
We’ll work through this webpage’s configuration as an example.
CAA Records
First, you need to make sure you have CAA records for your domain. You’ll need to login to your domain registrar and add something like the following:
maxbtroeger.com. 300 IN CAA 0 issue "letsencrypt.org" www.maxbtroeger.com. 300 IN CAA 0 issue "letsencrypt.org"Check your domain registrar’s documentation on how to add CAA records.
Initial httpd setup
With that out of the way we can move on to the server-side of things.
Note: all commands need to be run by root or a privileged user with doas
.
In /etc/httpd.conf
add the following:
server "www.maxbtroeger.com" { listen on * port 80 root "/htdocs/www.maxbtroeger.com" location "/.well-known/acme-challenge/*" { root "/acme" request strip 2 } } server "maxbtroeger.com" { listen on * port 80 block return 301 "https://www.maxbtroeger.com$REQUEST_URI" } # Include additional MIME types types { include "/usr/share/misc/mime.types" }this will give you an http page at
www.maxbtroeger.com
and all traffic from maxbtroeger.com
will be redirected to it.
Having your bare url redirect to a www.
subdomain isn’t necessary, but it’s a good convention.
These server blocks also tell Let’s Encrypt how to handle verification requests.
Give everything a test with httpd -n
:
# httpd -n configuration OKand, if all is well, enable the
httpd
daemon
# rcctl enable httpd # rcctl start httpd
Although our webserver is running, we need to tell acme-client
how to generate certificates so that httpd
can serve the webpage over https.
acme-client setup
First, we’ll make the relevant directories and set their permissions:
# mkdir -p -m 700 /etc/ssl/private # mkdir -p -m 755 /var/www/acme
And in /etc/acme-client.conf
we’ll add the following:
authority letsencrypt { api url "https://acme-v02.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-privkey.pem" } domain www.maxbtroeger.com { alternative names { maxbtroeger.com } domain key "/etc/ssl/private/www.maxbtroeger.com.key" domain certificate "/etc/ssl/www.maxbtroeger.com.crt" domain full chain certificate "/etc/ssl/www.maxbtroeger.com.pem" sign with letsencrypt }This tells
acme-client
that we want a certificate for a primary domain www.maxbtroeger.com
aliased to maxbtroeger.com
, signed by Let’s Encrypt, and stored in /etc/ssl
.
If you’re not using a separate www.
subdomain like I am, you can remove the alternative names
line.
All we need to do now is generate our certificate:
# acme-client -v www.maxbtroeger.comIf all goes well we should see our certificates and keys stored in
/etc/ssl
# ls /etc/ssl ... www.maxbtroeger.com.crt www.maxbtroeger.com.pem private/www.maxbtroeger.com.key ...
Final httpd setup
To enable https we need to point incoming traffic to port 443 and tell httpd
where our certificate is stored.
Make the following changes to /etc/httpd.conf
:
server "www.maxbtroeger.com" { - listen on * port 80 + listen on * tls port 443 root "/htdocs/www.maxbtroeger.com" location "/.well-known/acme-challenge/*" { root "/acme" request strip 2 } + tls { + certificate "/etc/ssl/www.maxbtroeger.com.pem" + key "/etc/ssl/private/www.maxbtroeger.com.key" + } } server "maxbtroeger.com" { - listen on * port 80 + listen on * tls port 443 + tls { + certificate "/etc/ssl/www.maxbtroeger.com.pem" + key "/etc/ssl/private/www.maxbtroeger.com.key" + } block return 301 "https://www.maxbtroeger.com$REQUEST_URI" } +server "www.maxbtroeger.com" { + listen on * port 80 + alias "maxbtroeger.com" + block return 301 "https://www.maxbtroeger.com$REQUEST_URI" +} # Include additional MIME types types { include "/usr/share/misc/mime.types" }The new block at the end of
/etc/httpd.conf
redirects all unencrypted http traffic to https.
After checking that all is well with our configuration
# httpd -n configuration OKwe can restart
httpd
and see if our web browser recognizes the certificate
# rcctl restart httpd httpd(ok) httpd(ok)
Automating renewal
With https working we’ll want to automate certificate renewal.
One of the perks of using OpenBSD’s native acme-client
over something outside of the base install like certbot
is that we don’t need to stop httpd
to renew our certificates.
As root add the following to your crontab (run # crontab -e
):
0 0 * * * acme-client www.maxbtroeger.com && rcctl reload httpd
Conclusion
Hopefully everything should be running hands-free.
If you encounter any difficulty, read the relevant manuals (man httpd.conf
and man acme-client.conf
) and consider checking out other tutorials: