bsdbox

let's encrypt https with acme-client on openbsd

<2018-03-21>

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:

  1. ensure +both instances of the agreement url contain the most up-to-date link+=api-url= references Let's Encrypt's v02 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.

Tags: openbsd
send comments to mark AT jamsek DOT net

Generated by emacs org mode

Copyright © 2023 Mark Jamsek