Image

I’ve been running Pi-hole in a container on my TrueNAS Scale box for a while and had unfortunately experienced a number of upgrades that required deploying the container from scratch. This was due to incompatibilities in the Helm chart settings, which broke in-place upgrades and required reconfiguration. This probably happened 3-4 times over the last two years. Being a bit of a tinkerer, I decided to grab a Raspberry Pi, throw Pi-hle on it, and just plug it in and be done. The process to do that is pretty simple; I was able to get the configuration from the TrueNAS container imported into Pi-hole on the Pi, and presto — done.

While I know that it’s running on my internal network and the odds of needing to care about TLS connections to the administrative web service are probably pretty small, I set out to get TLS enabled on it anyways for a few simple reasons. First, it’s something new to tinker with and figure out. Second, I’m a security guy so encryption probably matters. Third, LetsEncrypt is free so it’s no cost. And probably most importantly, I dislike seeing Chrome give me a “Not Secure” warning every time I go to the web page. It just stirs up a certain level of disappointment within me.

So in this post I’ve detailed the way that I put it all together to use LetsEncrypt for SSL certificates to enable TLS connections to the Pi-hole administrative web site.

Obtain LetsEncrypt certificates

Before making any other changes, we want to install the acme.sh client that will obtain the LetsEncrypt certificates. This can be done by cloning the git repository and installing it:

$ sudo su -
# cd /root
# git clone https://github.com/Neilpang/acme.sh.git
# cd acme.sh
# ./acme.sh --install
# exit

There are a few choices for hostname verification, I prefer to use CloudFlare and DNS. We can use the environment that the installation setup, grab the CloudFlare API key, and then configure acme.sh. In this example we’ll use the hostname “pihole.hostname.com” as our FQDN.

If you don’t have a ZeroSSL account, you will need to create that first which is something new in the later version of acme.sh, apparently. First time I’ve heard of or run into this.

# sudo su -
# ./acme.sh --register-account -m [email protected] --server zerossl

Once this is complete, save your CloudFlare API key and email address to the account.conf file and get the certificate:

# echo "SAVED_CF_Key='[API key from CloudFlare]'" >>/root/.acme.sh/account.conf
# echo "SAVED_CF_Email='[CloudFlare login email address]'" >>/root/.acme.sh/account.conf
# cd /root/.acme.sh
# ./acme.sh --issue --dns dns_cf -d pihole.hostname.com --server zerossl

Once this is complete, your certificates will be saved in the /root/.acme.sh/pihole.hostname.com_ecc/ directory. At this point, we have to configure lighttpd which is the web server that Pi-hole uses for its administrative interface.

Enable SSL in lighttpd

The first step is to create the directory to store the SSL certificate:

# mkdir -p /etc/lighttpd/ssl/pihole.hostname.com

Make sure that SSL support for lighttpd is installed:

# apt-get install lighttpd-mod-openssl

Create symlinks to make your certificate and key file available for lighttpd without exposing the /root/.acme.sh/ directory. The key file by default is mode 0600 and owned by the root user and group. We need to make a slight change so lighttpd, running as the www-data user, can read it:

# cd /etc/lighttpd/ssl/pihole.hostname.com
# ln -s /root/.acme.sh/pihole.hostname.com_ecc/fullchain.cer .
# ln -s /root/.acme.sh/pihole.hostname.com_ecc/pihole.hostname.com.key .
# chmod 640 /root/.acme.sh/pihole.hostname.com_ecc/pihole.hostname.com.key
# chown root:www-data /root/.acme.sh/pihole.hostname.com_ecc/pihole.hostname.com.key

Configure lighttpd to enable TLS

Next, create the /etc/lighttpd/conf-enabled/10-ssl.conf file with the following contents:

server.modules += ( "mod_openssl" )

setenv.add-environment = ("fqdn" => "true")

$SERVER["socket"] == ":443" {
    ssl.engine = "enable"
    ssl.pemfile = "/etc/lighttpd/ssl/pihole.hostname.com/fullchain.cer"
    ssl.privkey = "/etc/lighttpd/ssl/pihole.hostname.com/pihole.hostname.com.key"
    ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.3", "Options" => "-ServerPreference")
}

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

At this point you need to restart lighttpd:

# systemctl restart lighttpd

Optional convenient redirect

You can also create a convenient redirect from https://pihole.hostname.com/ to https://pihole.hostname.com/admin/ by creating /var/www/html/index.html with the contents:

<!DOCTYPE HTML>

<meta charset="UTF-8">
<meta https-equiv="refresh" content="1; url=https://pihole.hostname.com/admin/">

<script>
  window.location.href = "https://pihole.hostname.com/admin/"
</script>

<title>Page Redirection</title>

<!-- Note: don't tell people to `click` the link, just tell them that it is a link. -->
If you are not redirected automatically, follow the <a href='https://pihole.hostname.com/admin/'>link to admin</a>

There are a number of different ways to get Pi-hle running under SSL on a Raspberry Pi; this worked for me and hopefully it will work for you as well.

Share on: TwitterLinkedIn


Related Posts


Published

Category

Linux

Tags

Stay in touch