logo

tested on openbsd 6.6

enable https with acme-client(1) and let's encrypt on openbsd

configure httpd(8).

to use let's encrypt as a certificate authority for tls encryption add or update your caa records for your domain.

    example.com. 300 IN   CAA   0 issue "letsencrypt.org"
www.example.com. 300 IN   CAA   0 issue "letsencrypt.org"

to configure acme-client(1), add these sections to /etc/acme-client.conf:

authority letsencrypt {
  api url "https://acme-v02.api.letsencrypt.org/directory"
  account key "/etc/ssl/private/letsencrypt.key"
}
domain www.example.com {
  alternative names { example.com }
  domain key "/etc/ssl/private/www.example.com.key"
  domain certificate "/etc/ssl/www.example.com.crt"
  domain full chain certificate "/etc/ssl/www.example.com.pem"
  sign with letsencrypt
}

create directories:

# mkdir -p -m 700 /etc/ssl/private
# mkdir -p -m 755 /var/www/acme
#

update /etc/httpd.conf to handle verification requests from let's encrypt. it should look like this:

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"
}

check this configuration and restart httpd:

# httpd -n
configuration ok
# rcctl restart httpd
httpd(ok)
httpd(ok)
#

let's run acme-client to create new account and domain keys.

# acme-client -v www.example.com
...
acme-client: /etc/ssl/www.example.com.crt: created
acme-client: /etc/ssl/www.example.com.pem: created
#

to renew certificates automatically edit the current crontab:

# crontab -e

append this line:

0 0 * * * acme-client www.example.com && rcctl reload httpd

save and exit:

crontab: installing new crontab
#

enable https and restart the daemon

now we have the new certificate and domain key, so we can re-configure httpd to handle https requests. add two server sections to /etc/httpd.conf for tls. the result should look like this:

server "www.example.com" {
  listen on * tls port 443
  root "/htdocs/www.example.com"
  tls {
    certificate "/etc/ssl/www.example.com.pem"
    key "/etc/ssl/private/www.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/www.example.com.pem"
    key "/etc/ssl/private/www.example.com.key"
  }
  block return 301 "https://www.example.com$REQUEST_URI"
}

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"
}

test this configuration and restart httpd:

# httpd -n
configuration ok
# rcctl restart httpd
httpd (ok)
httpd (ok)
#

to verify your setup run ssl server test.

congratulation! your website and its visitors are now secured.

add domains

backup and remove the certificate

# mv /etc/ssl/www.example.com.crt /etc/ssl/www.example.com.crt.bak
#

add a new alternative name to /etc/acme-client.conf:

...
alternative names { example.com new.example.com }
...

add a new server section to /etc/httpd.conf. use the same certificate and key.

...
server "new.example.com" {
  listen on * tls port 443
  root "/htdocs/new.example.com"
  tls {
    certificate "/etc/ssl/www.example.com.pem"
    key "/etc/ssl/private/www.example.com.key"
  }
  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
  }
}
...

request a new certificate with the new alternative in it. verify httpd.conf and restart httpd(8):

# acme-client -vF www.example.com
...
acme-client: /etc/ssl/www.example.com.crt: created
acme-client: /etc/ssl/www.example.com.pem: created
# httpd -n
configuration ok
# rcctl restart httpd
httpd(ok)
httpd(ok)
#