acme.sh with lighttpd on pihole


# 20220718 – updated with some things I’ve learned since I wrote the original post.

# 20240527 – I’m reinstalling pihole from scratch and finding a few things have changed… like lighthttpd not automatically loading mod_openssl and external.conf is not a thing anymore. Updating these instructions as I go along.

I’m going to assume you’ve already setup step-ca or some other acme server. This procedure could also be used for LetsEncrypt. You just wouldn’t use the –server switch when issuing the certificate.

I’ve got step-ca setup in my homelab for a private ACME server for certificate renewal automation. It’s been working fantastically well with Traefik in front of all my Docker containers. I’ve been meaning to automate the certificate renewal on my pihole and finally got around to doing it this week.

username: latte
acme ca: acme.guammie.lan
pihole: pihole.guammie.lan

# Get the root CA certificates and trust them
scp [email protected]:.step/certs/*.crt ./
sudo mv *.crt /usr/local/share/ca-certificates
sudo update-ca-certificates

# Add user to www-data in preparation for webroot mode
sudo usermod -a -G www-data latte

# logoff for the group modification to take effect and validate
logoff
id latte

# Allow the user to restart lighttpd without having to reauthenticate
# this is necessary for the reloadcmd to work in the cron job
echo "latte ALL=(ALL) NOPASSWD: /usr/sbin/service lighttpd restart" | sudo tee -a /etc/sudoers.d/latte-nopasswd

# My pihole isn't setup for internal name resolution at the OS level
# adding an entry for the CA
sudo sh -c 'echo "192.168.1.10 acme.guammie.lan" >> /etc/hosts'

# Setup the directory structure for where acme.sh will download certificates to
sudo mkdir -p /etc/pki/certs /etc/pki/keys /etc/pki/fullchain
sudo chown -R latte:www-data /etc/pki

# Clone acme.sh
git clone https://github.com/acmesh-official/acme.sh.git

# I initially did this in standalone mode and needed socat... 
# don't know if it's necessary for webroot mode.  Never bothered to check.
sudo apt install socat
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/socat

# Getting ready to install acme.sh in /opt
sudo mkdir /opt/acme.sh
sudo chown -R latte:latte /opt/acme.sh

# Install acme.sh to /opt
cd acme.sh
./acme.sh --install --home /opt/acme.sh --config-home /opt/acme.sh --cert-home /etc/pki

# If you skip the logging out and back then everything still goes to ~/.acme.sh
# the installer even says to do so: 
# "OK, Close and reopen your terminal to start using acme.sh"
logoff
log back in (duh)

# Get the certificates
cd /opt/acme.sh 
./acme.sh --issue --webroot /var/www/html -d $HOSTNAME.guammie.lan --server https://acme.guammie.lan/acme/guammie/directory --days 7

# Install the certificates to the previously setup directories
./acme.sh --install-cert --domain $HOSTNAME.guammie.lan --cert-file /etc/pki/certs/$HOSTNAME.guammie.lan.cer --key-file /etc/pki/keys/$HOSTNAME.guammie.lan.key --fullchain-file /etc/pki/fullchain/$HOSTNAME.guammie.lan.crt --reloadcmd "sudo service lighttpd restart"

# Even though we haven't setup lighttpd to use the certificates yet, it's
# important to specify the reloadcmd because it becomes part of the renewal cron
# job that gets setup during install

# Validate everything looks correct
./acme.sh --info -d $HOSTNAME.guammie.lan

# I'm putting this here just to remember to do it periodically
# I should setup a cron job for it
./acme.sh --upgrade --auto-upgrade

# It's 2024 and now we have to install mod_openssl manually
sudo apt install lighttpd-mod-openssl

# Now create the conf file for ssl and apply it.
sudo nano /etc/lighttpd/conf-available/15-guammie-ssl.conf                                                                                                          


# File contents of 15-guammie-ssl.conf
server.modules += ( "mod_openssl" )

$HTTP["host"] == "pihole.guammie.lan" { 
  # 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/pki/fullchain/pihole.guammie.lan.crt"
    ssl.privkey = "/etc/pki/keys/pihole.guammie.lan.key"
    ssl.honor-cipher-order = "enable"
    ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
    ssl.openssl.ssl-conf-cmd = ("Protocol" => "-TLSv1.1, -TLSv1, -SSLv3")
  }

  # Redirect HTTP to HTTPS
  $HTTP["scheme"] == "http" {
    $HTTP["host"] =~ ".*" {
      url.redirect = (".*" => "https://%0$0")
    }
  }
}

# Enable the conf file
sudo lighty-enable-mod guammie-ssl

# Reload lighthttpd
sudo service lighttpd force-reload 

That’s it.


Leave a Reply

Your email address will not be published. Required fields are marked *