Introduction #
In order to secure the data transmitted between the webserver and the client, we need SSL. There are multiple types of SSL certificates and they mostly differ in the way the identity of the requester is verified. For example, banks will usually choose the strictest verification method as it will show prominently in the browsers searchbar or omnibox. Since these verification methods take time and effort, they are more costly the more work has to be put in.
The most basic form of authentication is the so-called domain-level verification: if you control the domain, you’re allowed to receive an SSL certificate. Let’s Encrypt is a project that allows domain owners to receive such a domain-level verified certificate for free and we’ll use their service in this tutorial.
You are expected to have root privileges for all commands below.
ACME Configuration #
First we need to edit the /etc/acme-client.conf file that is already present on the system:
- Comment in the section that was commented out
- Change example.com to the domain name you want to secure
- Add any alternative names like www.example.com
#
# $OpenBSD: acme-client.conf,v 1.6 2017/11/27 01:59:55 florian Exp $
#
authority letsencrypt {
api url "https://acme-v02.api.letsencrypt.org/directory"
account key "/etc/acme/letsencrypt-privkey.pem"
}
authority letsencrypt-staging {
api url "https://acme-staging.api.letsencrypt.org/directory"
account key "/etc/acme/letsencrypt-staging-privkey.pem"
}
domain example.com {
alternative names { www.example.com }
domain key "/etc/ssl/private/example.com.key"
domain certificate "/etc/ssl/example.com.crt"
domain full chain certificate "/etc/ssl/example.com.fullchain.pem"
sign with letsencrypt
}
Create the necessary directories
mkdir -p -m 700 /etc/acme
mkdir -p -m 700 /etc/ssl/acme/private
mkdir -p -m 755 /var/www/acme
Let’s Encrypt will make a verification request so we need to update /etc/httpd.conf to be able to handle these requests:
In OpenBSD 6.4 the syntax for stripping changed.
For OpenBSD version 6.4 and later
server "www.example.com" {
listen on * port 80
root "/htdocs/www.example.com"
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}
server "example.com" {
listen on * port 80
block return 301 "http://www.example.com$REQUEST_URI"
}
For previous OpenBSD versions
server "www.example.com" {
listen on * port 80
root "/htdocs/www.example.com"
location "/.well-known/acme-challenge/*" {
root { "/acme", strip 2 }
}
}
server "example.com" {
listen on * port 80
block return 301 "http://www.example.com$REQUEST_URI"
}
Next, we need to check the configuration and reload or restart the daemon
httpd -n && rcctl restart httpd
We now can run the acme-client to create a new account and a key
acme-client -v example.com
The final lines of the output should be something like:
acme-client: /etc/ssl/example.com.crt: created
acme-client: /etc/ssl/example.com.pem: created
The certificates are valid for 90 days to we need to setup a cronjob to renew. We will run it daily but only once the end of the validity comes in sight, will the certificates actually be renewed.
crontab -e
insert a line like:
05 3 * * * acme-client example.com && rcctl reload httpd
httpd configuration #
We now have everything we need to correctly configure httpd to run SSL. Change the httpd.conf file to look like this.
In OpenBSD 6.4 the syntax for stripping changed.
For OpenBSD version 6.4 and later
server "www.example.com" {
listen on * tls port 443
root "/htdocs/www.example.com"
tls {
certificate "/etc/ssl/example.com.fullchain.pem"
key "/etc/ssl/private/example.com.key"
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}
server "example.com" {
listen on * tls port 443
tls {
certificate "/etc/ssl/example.com.fullchain.pem"
key "/etc/ssl/private/example.com.key"
}
block return 301 "https://example.com$REQUEST_URI"
}
server "www.example.com" {
listen on * port 80
alias "example.com"
block return 301 "https://www.example.com$REQUEST_URI"
}
For previous OpenBSD versions
server "www.example.com" {
listen on * tls port 443
root "/htdocs/www.example.com"
tls {
certificate "/etc/ssl/example.com.fullchain.pem"
key "/etc/ssl/private/example.com.key"
}
location "/.well-known/acme-challenge/*" {
root { "/acme", strip 2 }
}
}
server "example.com" {
listen on * tls port 443
tls {
certificate "/etc/ssl/example.com.fullchain.pem"
key "/etc/ssl/private/example.com.key"
}
block return 301 "https://example.com$REQUEST_URI"
}
server "www.example.com" {
listen on * port 80
alias "example.com"
block return 301 "https://www.example.com$REQUEST_URI"
}
Restart httpd:
httpd -n && rcctl restart httpd
SSL verification #
- A quick test can be done directly in-browser or www.sslcheck.nl.
- A more extensive check can be done via ssllabs.com
Additional domains #
First, we need to move the existing certificate out of the way. Skipping this step will result in an error.
mv /etc/ssl/example.com.crt /etc/ssl/example.com.crt.bak
Edit /etc/acme-client.conf and add more alternative names
alternative names { www.example.com example1.com www.example1.com }
Update httpd.conf accordingly:
server "www.example1.com" {
listen on * tls port 443
root "/htdocs/www.example1.com"
tls {
certificate "/etc/ssl/example.com.pem"
key "/etc/ssl/private/example.com.key"
}
location "/.well-known/acme-challenge/*" {
root { "/acme", strip 2 }
}
}
Run the acme client again
acme-client -Fv example.com
And restart httpd
httpd -n && rcctl restart httpd