lighttp, https and cert renewal
2023-05-26
Add this to /etc/lighttpd/mod_ssl.conf
:
url.redirect = (
"^/\.well-known/acme-challenge/.*" => "",
"" => "https://${url.authority}${url.path}${qsa}"
)
This website currently uses lighttpd to serve it’s web pages.
I also use letsencrypt for the TLS certificate.
I enable https and force all http traffic to https, which I achived by following this guide:
How to redirect HTTP requests to HTTPS
I also wanted the certificate to renew automatically without intervention on my part. This is where things fell apart and prompted this post.
As letsencrypt certs expire every 90 days, I didn’t want to manually log on and renew them.
There are two ways to have letsencrypt authenticate the server that I could use:
Stand alone opens a temporary webserver on port 80 so the letsencrypt servers can check a temporary file created by certbot
and confirm the website is who it says it is. The only problem with this is it means the webserver needs to be stopped to free up port 80. I wasn’t keen on this, not because I have a high traffic website that can’t handle an outage, but I’d prefer not to stop a service that I didn’t need to and there’s always a risk it wont be able to start without intervention on my part.
Something like this would have worked in the crontab, even if it’s not elegant:
rc-service lighttpd stop ; \
/usr/bin/certbot renew --quiet ; \
rc-service lighttpd start
The other way I wanted to try to have letsencrypt authenticate my server was using webroot. Webroot places a temporary file in the /.well-known/acme-challenge/
directory of the webserver and provides the file via the http server that’s already running.
This means the webserver doesn’t need to be stopped to free up port 80 for the temporary file check.
This allows me to have just the revew entry in the crontab:
/usr/bin/certbot renew --quiet
In the end I went with the webroot solution, as I didn’t want to stop and start the webserver and risk it not starting and me not noticing.
There are three lines that need some explaining:
"^/\.well-known/acme-challenge/.*" => "",
The above line takes precedence, and means that when letsencrypt tries to get the files from the website, it won’t be redirected to the SSL site. This makes sense as there’s no point using a certificate as it’s trying to generate one.
"" => "https://${url.authority}${url.path}${qsa}"
The above line then takes any request that aren’t for the acme-challange files and redirect them to https.
url.redirect-code = 308
The above line uses the newer [308 redirect code].
Here’s how the full /etc/lighttpd/mod_ssl.conf
config file looks like:
server.modules += ("mod_openssl")
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/letsencrypt/live/rdm.sh/fullchain.pem"
ssl.privkey = "/etc/letsencrypt/live/rdm.sh/privkey.pem"
}
$HTTP["host"] == "www.rdm.sh" {
ssl.pemfile = "/etc/letsencrypt/live/www.rdm.sh/fullchain.pem"
ssl.privkey = "/etc/letsencrypt/live/www.rdm.sh/privkey.pem"
}
$HTTP["scheme"] == "http" {
$HTTP["host"] =~ ".*" {
url.redirect = (
"^/\.well-known/acme-challenge/.*" => "",
"" => "https://${url.authority}${url.path}${qsa}"
)
url.redirect-code = 308
}
}
Running certbot renew --dry-run
now gives me:
rdm:~# certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/rdm.sh.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for rdm.sh
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/www.rdm.sh.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simulating renewal of an existing certificate for www.rdm.sh
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/rdm.sh/fullchain.pem (success)
/etc/letsencrypt/live/www.rdm.sh/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Here’s the full crontab:
17 10/23 * * * /usr/bin/certbot renew --quiet