Setup Let's Encrypt on OpenBSD

Setting up a webserver was easy enough with the httpd daemon, but to bring your webserver into the 21st century you should configure it to serve web content over HTTPS, the secure version of HTTP. However, in order to do that you will need a certificate which is used to validate that your server is who it says it is - and thus that visitors to your site can trust that their connection to you is secure.

Traditionally, obtaining a valid certificate can be a somewhat complicated, and in some cases expensive, process meaning that many sites don't bother. Let's Encrypt is a service which automates the process and does it all for free. This means there's no reason not to set it up.

Install certbot

certbot is the OpenBSD package created for this purpose and is what you'll need to install to obtain and renew your certificate. At the time of writing, certbot is on version 0.22.2.

$ doas pkg_add certbot

Get a certificate

Now you can use certbot to obtain a certificate for your domain. At this time, certbot doesn't support wildcard certificates on OpenBSD so you'll have to explicitly request a certificate for each subdomain individually. In this example I'll be requesting a certificate for both and for a website served from a root of /var/www/htdocs/gridc0. If you have more subdomains than www, add them as additional options on the command line, prefacing each subdomain with the -d flag.

$ doas certbot certonly --webroot -w /var/www/htdocs/gridc0 -d -d

Enter in your contact e-mail, read the terms and enter "A" if you agree to them, and indicate whether or not you want to receive e-mails from the EFF. Once complete, certbot will place your certs in /etc/letsencrypt/live/<yourdomain>/.

If you'd like to use OCSP stapling then you can generate the staple file with the following command:

$ doas ocspcheck -N -o /etc/letsencrypt/live/<yourdomain>/staple.der /etc/letsencrypt/live/<yourdomain>/fullchain.pem

Re-configure httpd

If you're setting up HTTPS on your website then you'll generally want every visitor to end up at the same version of your site - namely the secure one. This means anyone who visits should automatically end up at (notice the 's' on the second URL). The proper way to accomplish this is to have the server perform the redirection, and this requires a configuration change to /etc/httpd.conf. We'll start where we left off in the last tutorial, with a basic configuration serving documents for a single domain:

server "default" {
    listen on * port 80
    root "/htdocs/default/"

As you can see, this only serves content over port 80 for HTTP. We'll need to redirect requests on port 80 to port 443 for HTTPS, and add a new server entry that serves documents on that same port. We'll be using the domain for this example as well.


server $domain {
    listen on * port 80
    block return 301 "https://$SERVER_NAME$REQUEST_URI"

server $domain {
    listen on * tls port 443
    root "/htdocs/gridc0/"
    tls {
        certificate "/etc/letsencrypt/live/"
        key "/etc/letsencrypt/live/"
        ocsp "/etc/letsencrypt/live/<yourdomain>/staple.der"
        ciphers "kEECDH:!aNULL:!eNULL:!RC4:!AES128:!3DES:!DES"
        ticket lifetime default

The first entry listens for HTTP requests to any subdomain and automatically redirects them to their HTTPS equivalent. The second entry listens for HTTPS requests and serves them with the specified certificate and key. Using the fullchain.pem rather than cert.pem results in higher security because clients can trace your certificate all the way back to the authority that issued it. The ciphers directive indicates which ciphers to include with a laundry list of ciphers not to be included. In addition, TLS session tickets are enabled with the default lifetime. To generate the list of ciphers I used Qualys SSL Labs and re-tested until the score wouldn't go higher. Generally, it's easy to tell which ciphers (or properties of ciphers) are pulling your score down. You can use the following command to determine which ciphers will be included to aid in paring them down.

$ openssl ciphers -v kEECDH:!aNULL:!eNULL:!RC4:!AES128:!3DES:!DES

This is the most likely part of the configuration you'll need to change in order to stay secure, so check your score once a month to ensure you're staying secure. Keep in mind as you reduce the number of supported ciphers, you also reduce the number of compatible browsers. Check the "Handshake Simulation" section to see which browsers are compatible.

You can use the following command to verify, but not load, the configuration file.

$ doas httpd -n

If you get back configuration OK then all that's left to do is restart httpd so it uses your new cert.

$ doas /etc/rc.d/http restart

Certificate Renewal

If you browse to your website and then look at the certificate, you'll see that it will expire in about 3 months. So, the final piece of the puzzle is automating the renewal process which can be done with a simple crontab entry. The certbot documentation recommends running renewal attempts twice per day in case your certificate is revoked for some reason. Open crontab with the following command

$ doas crontab -e

And add the following line to it:

0       6,18    *       *       *       sleep $((RANDOM \% 3600)) && certbot renew

This means that everyday at 6am and 6pm the crontab entry will be executed. This entry will sleep for a random number of seconds, up to 1 hour, and then attempt to renew your certs. You can run a trial renewal with the following command.

$ doas certbot renew --dry-run

That's it! Your website now has a valid cert that gets automatically renewed and which protects your visitors communication to your site. Plus, no matter what form of your URL they enter, they always get served over a secure connection.

For more detailed information on the configuration file, you can pass its name to man

$ man httpd.conf

Or visit the online man pages at the following link

Comments !