Introduction
Since OpenBSD 5.9, the base system comes with acme-client
: an open source
implementation in C that requests a free HTTPS certificate from the Let’s
Encrypt Certificate Authority. It is super simple to setup and even easier to
use. And once your certificate is issued, the acme-renew script
will ensure your website stays TLS encrypted for the remainder of its lifetime.
The following assumes OpenBSD +6.2+6.7, please refer to the relevant
man pages
for other releases as the syntax of acme-client
commands and acme-client.conf
has changed.
Setup acme-client
Open /etc/acme-client.conf
to perform the following:
- ensure +both instances of the
agreement url
contain the most up-to-date link+=api-url= references Let's Encrypt'sv02
API;
#. provide the domain(s) and any subdomains to be covered by the certificate(s);
#. specify the path to output generated key and certificate files;
#. designate absolute path to
challengedir
where challenges should be sent
to the web server.
# $OpenBSD: acme-client.conf,v 1.4 2017/03/22 11:14:14 benno Exp $ # authority letsencrypt { # agreement url "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf" # api url "https://acme-v01.api.letsencrypt.org/directory" api url "https://acme-v02.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-privkey.pem" } authority letsencrypt-staging { # agreement url "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf" api url "https://acme-staging.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-staging-privkey.pem" } domain domain.tld { alternative names { www.domain.tld sub.domain.tld sub2.domain.tld } domain key "/etc/ssl/private/domain.tld.key" domain certificate "/etc/ssl/domain.tld.crt" domain full chain certificate "/etc/ssl/domain.tld.fullchain.pem" sign with letsencrypt # challengedir "/var/www/acme" }
n.b. Commented lines are preserved for posterity; they belong to previous versions of this article that correspond to previous versions of OpenBSD.
Setup httpd
Edit /etc/httpd.conf
so that the web server is able to handle challenges
issued by Let’s Encrypt to determine that you are in control of the domains
covered by the requested certificate(s). Ensure the relative
/root
path
matches the absolute challengedir
path provided in acme-client.conf
.
server "domain.tld" { alias www.domain.tld listen on * port http listen on :: port http location "/.well-known/acme-challenge/*" { root "/acme" root strip 2 } }
Lines 5 to 7 are all that is needed to handle requests from the Certificate
Authority. +Before restarting the daemon, if it doesn't already exist, make,
and bestow ownership to the web server, /var/www/acme
; the directory in the
httpd
chroot where challenges issued by Let's Encrypt will be processed.+
Certificate Request
Before submitting the certificate signing request to Let’s Encrypt, ensure that
any subdomains listed in acme-client.conf
have properly setup A
or CNAME
records with your nameserver or registrar; that is, requests to
sub.domain.tld are actually directed to your web server. If all is in order,
issue the request (as root or with doas
).
$ doas acme-client -vv domain.tld # OpenBSD 6.7 $ doas acme-client -vvAD www.domain.tld # older OpenBSD versions (e.g., 6.(2,3,4}) acme-client: /etc/acme/letsencrypt-privkey.pem: account key exists (not creating) acme-client: /etc/acme/letsencrypt-privkey.pem: loaded RSA account key acme-client: /etc/ssl/private/domain.tld.key: generated RSA domain key acme-client: https://acme-v01.api.letsencrypt.org/directory: directories acme-client: acme-v01.api.letsencrypt.org: DNS: 172.65.32.248 ... N(Q????Z???j?j?>W#????b???? H????eb??T??*? DNosz(???n{L}???D???4[?B] (1174 bytes) acme-client: /etc/ssl/domain.tld.crt: created acme-client: /etc/ssl/domain.tld.fullchain.pem: created
A successful result will output the public certificate, full chain of trust,
and private key into the /etc/ssl
directory as specified in
acme-client.conf
:
# ls -lR /etc/ssl -r--r--r-- 1 root wheel 2.3K Mar 2 01:31:03 2018 domain.tld.crt -r--r--r-- 1 root wheel 3.9K Mar 2 01:31:03 2018 domain.tld.fullchain.pem /etc/ssl/private: -r-------- 1 root wheel 3.2K Mar 2 01:31:03 2018 domain.tld.key
httpd
TLS Configuration
With the free Let's Encrypt certificate, we can now configure httpd
to
redirect all insecure, unencrypted, plaintext HTTP requests to HTTPS. A minor
addition to the previous server
section along with an entirely new one are
all that needs to be added to the httpd.conf
configuration file. If you also
want to continue serving HTTP requests, elide the second location
directive
in the first server
section.
server "domain.tld" { alias www.domain.tld listen on * port http listen on :: port http root "/htdocs/domain.tld" location "/.well-known/acme-challenge/*" { root "/acme" request strip 2 } location * { block return 301 "https://$HTTP_HOST$REQUEST_URI" } } server "domain.tld" { alias www.domain.tld listen on * tls port https listen on :: tls port https root "/htdocs/domain.tld" tls { certificate "/etc/ssl/domain.tld.fullchain.pem" key "/etc/ssl/private/domain.tld.key" } location "/.well-known/acme-challenge/*" { root "/acme" root strip 2 } }
And with that—it's a wrap! Your site is now serving TLS-encrypted sessions to protect the privacy of you and your visitors.
Further Reading
History
2020-06-21
Updated to reflect the process on OpenBSD 6.7. Commands,
configuration, and pertinent details related to previous versions are preserved
with strikethrough text.