💾 Archived View for bgp.rocks › openbsd-httpd-and-lets-encrypt.gmi captured on 2021-11-30 at 20:18:30. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
Published on 2021-04-23.
Before we do anything with httpd the DNS settings should already be done. There is no standard way of doing this, it all depends on the server administrator, who is running the DNS servers and what the end result should be. I have decided to use these settings:
bgp.rocks. A 46.23.94.208
bgp.rocks. AAAA 2a03:6000:6f69:605::208
bgp.rocks. CAA 0 issue "letsencrypt.org"
www.bgp.rocks. A 46.23.94.208
www.bgp.rocks. AAAA 2a03:6000:6f69:605::208
The [CAA entry](https://tools.ietf.org/html/rfc8659) is specifying that only [Let's Encrypt](https://letsencrypt.org/) is authorized to issue certificates for the bgp.rocks domain. It's not a necessary record to add, but I can do it so why not? :)
We will do this in a few steps. The first step is to get httpd up and running with a very basic configuration. I recommend taking a quick look at /etc/examples/httpd.conf and reading through the manual pages for [httpd](https://man.openbsd.org/httpd.8) and [httpd.conf](https://man.openbsd.org/httpd.conf.5).
Add the following into httpd.conf:
server "bgp.rocks" {
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}
Verify that the configuration is good, and if so enable and start httpd:
# httpd -n
configuration OK
# rcctl enable httpd
# rcctl start httpd
httpd(ok)
That's all we have to in httpd.conf for now.
The [ACME protocol](https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment) is the magic that in the end enables us to get the certificates we want. There is a client included in OpenBSD base so no extra software needs to be installed.
cp /etc/examples/acme-client.conf /etc
mkdir -p -m 700 /etc/ssl/private
mkdir -p -m 755 /var/www/acme
Add the following into acme-client.conf:
domain bgp.rocks {
alternative names { www.bgp.rocks }
domain key "/etc/ssl/private/bgp.rocks.key"
domain full chain certificate "/etc/ssl/bgp.rocks.fullchain.pem"
sign with letsencrypt
}
Let's try and get those certificates we've been waiting for so long:
# acme-client -v bgp.rocks
[...]
acme-client: /etc/ssl/bgp.rocks.fullchain.pem: created
Common issues I ran into was DNS issues (A and AAAA record not updated) and forgetting to either open up port 80 in the firewall or forgetting to start httpd.
Now we can do the final configuration in httpd.conf and enable our website with TLS! Create the directory /var/www/htdocs/bgp.rocks and modify the httpd.conf file to contain the following:
server "bgp.rocks" {
alias www.bgp.rocks
listen on * port 80
block return 301 "https://bgp.rocks$REQUEST_URI"
}
server "bgp.rocks" {
listen on * tls port 443
# Not a typo, we're chroot'ed to /var/www
root "/htdocs/bgp.rocks"
tls {
certificate "/etc/ssl/bgp.rocks.fullchain.pem"
key "/etc/ssl/private/bgp.rocks.key"
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}
server "www.bgp.rocks" {
listen on * tls port 443
tls {
certificate "/etc/ssl/bgp.rocks.fullchain.pem"
key "/etc/ssl/private/bgp.rocks.key"
}
block return 301 "https://bgp.rocks$REQUEST_URI"
}
This config will enable TLS on https://bgp.rocks and redirect non-secure HTTP connections and https://www.bgp.rocks to the non-www variant.
Let's see if it works:
$ curl -s --head http://www.bgp.rocks | grep Location
Location: https://bgp.rocks/
$ curl -s --head http://bgp.rocks | grep Location
Location: https://bgp.rocks/
$ curl -s --head https://www.bgp.rocks | grep Location
Location: https://bgp.rocks/
$ curl -s --head https://bgp.rocks | grep Location
(no output)
Success! We receive the Location header in return, redirecting us to the correct URL.
All that's left is to run crontab -e and add the following to the bottom:
# Let's Encrypt
~ acme-client bgp.rocks && rcctl reload httpd
The ~ means "a random value (within the legal range)" ([src](https://man.openbsd.org/crontab.5)), which I didn't know about! The crontab entry can be trimmed to not run as often but acme-client will check the certificate and abort if it's not up for renewal, so no extra load is put on the Let's Encrypt servers.
If everything works as it should you should now have a httpd server up and running, with certificates from Let's Encrypt automatically being renewed when necessary. And oh, if you got some extra cash, have a think about [donating to Let's Encrypt](https://letsencrypt.org/donate/) for the service they're providing.