This works well, thanks for the write-up. However, I have a few concerns with the steps presented, one being very serious:
Insecure permissions on private keys.
Like Apache and nginx (and, I suspect, most other web servers), lighttpd reads cert and key files with root permissions, before dropping privileges after launch. Therefore, according to the lighttpd docs:
Be careful to keep your .pem file private! Lighttpd reads all pemfiles at startup, before dropping privileges. It is therefore best to make the pem file owned by root and readable by root only
Unnecessary use of tee
There's absolutely no reason to use tee
in the cat
command that creates combined.pem
(which itself isn't necessary since lighttpd 1.4.53). A simple cat file1 file2 > file3
does the job just fine. This doesn't hurt anything, but just unnecessarily complicates the command.
Incorrect ca-file
The external.conf
file has the ssl.ca-file
pointing to fullchain.pem
, which contains both the "leaf" certificate and the intermediate signing certificate. Again, this isn't likely to break anything, but it'll probably result in an unnecessary cert being sent for every TLS negotiation. The correct file would be chain.pem
.
So, for anyone who might care, here's how I modified/updated these instructions to suit my system:
Like another poster up-thread, I use acme.sh for my ACME client for most purposes. It generally separates the action of issuing the cert and installing it, like this:
acme.sh --issue --dns dns_acmedns --dnssleep 5 -d pihole.yourdomain
acme.sh --install-cert -d pihole.yourdomain --cert-file /etc/ssl/certs/cert.pem --ca-file /etc/ssl/certs/ca.pem --key-file /etc/ssl/private/privkey.pem --reloadcmd "cat /etc/ssl/certs/cert.pem /etc/ssl/private/privkey.pem > /etc/ssl/private/combined.pem && systemctl restart lighttpd"
I'm placing the certs and key in /etc/ssl
, which is the "default" location for them under Ubuntu. CentOS, IIRC, places them in /etc/pki/tls
, other OSs may do otherwise. But it's lately being seen as a "best practice" to put your cert files where the OS would generally expect them to be, rather than directly using your ACME client's cert store.
Now, make combined.pem
readable by root only:
chmod 600 /etc/ssl/private/combined.pem
Download DH parameters recommended by the Mozilla config generator:
curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/ssl/certs/dhparam
Then, given these changes, the external.conf
file looks like this:
$HTTP["host"] == "pihole.yourdomain" {
# Ensure the Pi-hole Block Page knows that this is not a blocked domain
setenv.add-environment = ("fqdn" => "true")
# Enable the SSL engine with a LE cert, only for this specific host
$SERVER["socket"] == ":443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/ssl/private/combined.pem"
ssl.ca-file = "/etc/ssl/certs/ca.pem"
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
ssl.dh-file = "/etc/ssl/certs/dhparam"
# intermediate configuration
ssl.openssl.ssl-conf-cmd = ("Protocol" => "ALL, -SSLv2, -SSLv3, -TLSv1, -TLSv1.1")
ssl.cipher-list = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
ssl.honor-cipher-order = "disable"
}
# Redirect HTTP to HTTPS
$HTTP["scheme"] == "http" {
$HTTP["host"] =~ ".*" {
url.redirect = (".*" => "https://%0$0")
}
}
}