Let's Encrypt with dehydrated on FreeBSD

Recently we wrote a post on Moving back to Lighttpd and Michael Dexter thought I could spend my time wisely and do a short write-up on our use of dehydrated with Lighttpd.

In order to start with dehydrated we of course need to install it:

# pkg install dehydrated

Once it's all installed you can find the dehydrated configration /usr/local/etc/dehydrated

Your hosts and domains you want to get certificates for need to be added to domains.txt. For example:

example.com www.example.com example1.com secure.example1.com

The first host/domain listed will be used as filename to store the keys and certificates. There are a number of examples in the file itself if you want to get funky.

Hooks

If you want to restart services or do anything special, for example in the case when new certificates are generated, there is a file called hooks.sh. This script allows you to hook into any part of the process and run commands during that part of the process.

The hook we are using is for deploy_cert(). We are going to use this hook for: – creating a PEM certificate for Lighttpd – change owner to www – restart Lighttpd

What that looks like is something like this:

deploy_cert() {
    cat "${KEYFILE}" "${CERTFILE}" > "${BASEDIR}/certs/${DOMAIN}/combined.pem"
    chown -R www "${KEYFILE}" "${FULLCHAINFILE}" "${BASEDIR}/certs/${DOMAIN}/combined.pem"
    service lighttpd restart
}

The last part that is needed is to make sure this is run every day with cron.

@daily  root /usr/local/bin/dehydrated -c

In most cases this will be all that is needed to get going with dehydrated.

Lighttpd

You will need to let Lighttpd know about dehydrated and point it to acme-challange in the .well-known directory. You can do this with an alias like:

alias.url += ("/.well-known/acme-challenge/" => "/usr/local/www/dehydrated/")

The Lighttpd config we are using for SSL/TLS is the following:

$SERVER["socket"] == ":443" {
  ssl.engine = "enable" 
  ssl.pemfile = "/usr/local/etc/dehydrated/certs/example.com/combined.pem"
  ssl.ca-file = "/usr/local/etc/dehydrated/certs/example.com/chain.pem"
  ssl.cipher-list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-
CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384"
  ssl.dh-file = "/usr/local/etc/ssl/dhparam.pem" 
  ssl.ec-curve = "secp384r1"
  setenv.add-response-header = (
    "Strict-Transport-Security" => "max-age=31536000; includeSubdomains",
    "X-Frame-Options" => "SAMEORIGIN",
    "X-XSS-Protection" => "1; mode=block",
    "X-Content-Type-Options" => "nosniff",
    "Referrer-Policy" => "no-referrer",
    "Feature-Policy" =>  "geolocation none; midi none; notifications none; push none; sync-xhr none; microphone none; camera none; magnetometer none; gyroscope none; speaker none; vibrate none; fullscreen self; payment none; usb none;"  
  )
}

To finish it all you can now run dehydrated, in most cases would be:

# dehydrated -c

The complete Lighttpd config can be found in our Git Repository.