Enabling HTTPS for your Pi-hole Web Interface


#1

How can I enable HTTPS (SSL/TLS) for my Pi-hole Web Interface?

Many users run their Pi-hole on Virtual Private Servers and such, meaning that they would need to access the Web Interface via insecure HTTP. Now, you are able to configure Pi-hole so you can securely access your Web Interface, and not cause issues with blocked HTTPS content.

What has changed to allow this?

With the release of v3.2, we have made changes to our default lighttpd config to not automatically enable the SSL engine if /etc/lighttpd/conf-enabled/letsencrypt.conf was detected, as your certificate of pihole.example.com will not match advertiser.com.

Blindly enabling HTTPS for your Pi-hole Web Interface via Let’s Encrypt or a Self-Signed certificate causes issues such as:

  • Browsing slowdowns on any site visited, as blocked content needed to time out (or load infinitely)
  • Web Browser errors, such as mismatched certificates
  • Operating system popups on macOS/iOS devices on every site containing blocked content

As you can imagine, that is not a very good end-user experience!

With the instructions below, you will be able to selectively enable HTTPS for your Fully Qualified Domain Name (FQDN), and have it not conflict with blocked HTTPS enabled domains.

How to get started

  • Ensure you have a standard fully qualified domain name (e.g: domain.com, pihole.example.com, etc) that allows you to access your Pi-hole
  • Deploy an SSL certificate for your FQDN
  • Configure lighttpd to only enable the SSL engine for your FQDN

Assisting users with the first two steps is outside the scope of this article, so you will need to find tutorials that suits your level of skill. Having said that, we’d suggest checking out Certbot by the EFF, which allows you to deploy a free SSL certificate issued by Let’s Encrypt. The Certbot site provides you with instructions as to how to install the package, and to generate your first certificate. You will also need to ensure you set up the auto renewal tool, so that your certificate does not expire after 90 days!

How to configure Pi-hole to use an SSL certificate

The lighttpd daemon will need a custom configuration to enable the SSL engine. Fortunately, you can configure all this from /etc/lighttpd/external.conf as this will not get overwritten when running a Pi-hole update.

To start, you will need to create a file called combined.pem as this is the ssl.pemfile that lighttpd expects to see. Run the following command (making sure to subsitute pihole.example.com for your FQDN):

  sudo cat /etc/letsencrypt/live/pihole.example.com/privkey.pem \
           /etc/letsencrypt/live/pihole.example.com/cert.pem | \
  sudo tee /etc/letsencrypt/live/pihole.example.com/combined.pem

Next, ensure the lighttpd user www-data can read the required certificates:

sudo chown www-data -R /etc/letsencrypt/live

Now, place the following into /etc/lighttpd/external.conf (again, making sure to subsitute pihole.example.com for your FQDN):

$HTTP["host"] == "pihole.example.com" {
  # 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/letsencrypt/live/pihole.example.com/combined.pem"
    ssl.ca-file =  "/etc/letsencrypt/live/pihole.example.com/fullchain.pem"
    ssl.honor-cipher-order = "enable"
    ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"
    ssl.use-sslv2 = "disable"
    ssl.use-sslv3 = "disable"       
  }

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

Finally, be sure to run sudo service lighttpd restart after this change has been made.

Postscript

You can now take advantage of a HTTPS-secured Web Interface! If you wish, you can also host content on your Pi-hole by using /var/www/html/landing.php as your /var/www/html/index.php equivalent.

16/07/18 Edit:
Removed ssl.use-compression = “disable” as per @person51’s post.


Admin Web interface over HTTPS
HTTPS for Pi-hole Web Interface
SSL for Blocked Pages?
Pi-hole Web Interface: The Next Generation
Disable SSL Apache vhost
Pihole & reverse proxy caddy for https
Lighttpd doesn't start with SSL enabled
#2

In going through your post/tutorial I had previously known that getting certbot up and going on raspbian can be very confusing/difficult for most users (especially on older versions of raspbian) so I wanted to share this link and suggest that you include it in the “How to get started” section so they can easily figure out how to get certbot up and going on raspbian:

Thanks for this tutorial!


#3

This is confusing, do you mean that if I’m using HTTPS this is some of the issues that I can samble up on?
I don’t get if you have been fixing this issues or if this issues will appear if you activate HTTPS?


#4

do you mean that if I’m using HTTPS this is some of the issues that I can samble up on?

If you’re enabling HTTPS without using the $HTTP["host"] == "pihole.example.com" conditional, then yes, you can run into those issues I’ve mentioned.

I’ve updated the post to better clarify that enabling HTTPS using this tutorial will not cause the aforementioned issues :smile:


#5

As the most of us are using Pi-hole inside our own network and not outside let’s encrypt will not work good if your not opening the ports in the gateway.
I should be good if you also writting a guide with a self signed cert :slight_smile:


#6

This works as expected. I do have a question though. Is there a way to mark the “secure” flag (as well as httponly) on the session cookie once you’re serving the admin interface on https?


#7

I’m using an internal cert for this purpose. I had to comment out the “ca” line in the config since I had no file by that name. SSL works wonderfully.


#8

Thanks for the guide, works perfect :smiley:


#9

Has anyone been able to add to their lighttpd.conf a location for the let’s encrypt files, like so:

$HTTP[“url”] =~ “^/.well-known/” {
server.document-root = “/var/www/letsencrypt/.well-known/”
alias.url = ( “/.well-known/” => “/var/www/letsencrypt/.well-known/” )
dir-listing.activate = “enable”
}

Unfortunately, the “^/admin/” thing seems to cause an error 500 and require authorization, so the certbot fails to get a cert. Is there a way to make this work so that pihole can run and certbot renew certs in the future?

Thanks


#10

I use https://github.com/Neilpang/acme.sh whit the DNS and not webroot


#11

To automatically renew the certs, add the following cronjob:

47 5 * * * root /root/certbot-auto renew --quiet --no-self-upgrade --renew-hook “cat $RENEWED_LINEAGE/privkey.pem $RENEWED_LINEAGE/cert.pem > $RENEWED_LINEAGE/combined.pem;systemctl reload-or-try-restart lighttpd”


#12

I have followed this whole guide, made the cert, used certbot, but I get stuck at the end.
After I edit the lighttpd external.conf file, i can no longer access my /admin/ of my pihole, and I tried that with all the ports.
Nuking that file fixes it for me.
Yes, I replaced all the example.com with my own fqdm


#13

Thanks for this solution. I need it because i want to acces an other raspberry pi with domoticz on my netwerk via https. But… (and sorry i am new)

I did step 1 and 2 but in the beginning of step 3 i am stuck
An error is shown if i copy and paste the first line of step 3:
pi@raspberrypi:~ $ sudo cat /etc/letsencrypt/live/mplace.nl/privkey.pemcat: /etc/letsencrypt/live/myfqdn.nl/privkey.pem: No such file or directory

What am i doing wrong?

Greets Gijs


#14

And for those who would like a ‘key-in-hand’ script, I found that:
Let’s Encrypt renewal for Lighttpd
It turns as a service.

Edit:

Certbot is EFF’s tool to obtain certs from Let’s Encrypt and (optionally) auto-enable HTTPS on your server. It can also act as a client for any other CA that uses the ACME protocol.


The easiest way to install Certbot is by visiting certbot.eff.org, where you can find the correct installation instructions for many web server and OS combinations.


#15

@WaLLy3K I ran into the following errors when following the instructions. I created a bug and it was suggested that a fix can be done by changing the instructions here. This is the bug I reported https://github.com/pi-hole/pi-hole/issues/2248

The errors I am getting are:

(server.c.1295) WARNING: unknown config-key: alias.url (ignored)
I am also getting unknown config-key for ssl.use-compression

The solution I found:

fixed it by mod_alias in /etc/lighttpd/lighttpd.conf

so it looks like below:

server.modules = (
“mod_access”,
“mod_accesslog”,
“mod_auth”,
“mod_expire”,
“mod_compress”,
“mod_redirect”,
“mod_setenv”,
“mod_rewrite”,
“mod_alias”
)

so to fix this I comment it out ssl.use-compression = “disable” on /etc/lighttpd/external.conf

I am running:

lighttpd -v
lighttpd/1.4.45 (ssl) - a light and fast webserver
Build-Date: Jan 14 2017 21:07:19

I made sure I was up to date with pihole and raspberry pi 3. I hope this helps anyone out there.


#16

I have done everything as in the example, only that I run my own root CA, which certifies me the certificates. I have been doing this for quite some time, with various services in my private network. This also works quite well with pihole, but I got a warning, does anyone know anything about it?

pi@rpi15:~ $ sudo service lighttpd status
● lighttpd.service - Lighttpd Daemon
   Loaded: loaded (/lib/systemd/system/lighttpd.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2018-07-15 13:21:00 CEST; 22s ago
  Process: 5200 ExecStartPre=/usr/sbin/lighttpd -tt -f /etc/lighttpd/lighttpd.conf (code=exited, status=0/SUCCESS)
 Main PID: 5210 (lighttpd)
   CGroup: /system.slice/lighttpd.service
           ├─5210 /usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.conf
           ├─5223 /usr/bin/php-cgi
           ├─5224 /usr/bin/php-cgi
           ├─5225 /usr/bin/php-cgi
           ├─5226 /usr/bin/php-cgi
           └─5227 /usr/bin/php-cgi

Jul 15 13:21:00 rpi15 systemd[1]: Starting Lighttpd Daemon...
Jul 15 13:21:00 rpi15 lighttpd[5200]: 2018-07-15 13:21:00: (server.c.1295) WARNING: unknown config-key: ssl.use-compression (ignored)
Jul 15 13:21:00 rpi15 systemd[1]: Started Lighttpd Daemon.

#17

mitag - I get same error message. Search resulted with it’s default since lighttpd 1.4.28
Remove the ssl.use-compression = “disable” from /etc/lighttpd/external.conf and it will go away.

  • @WaLLy3K
    Like mitag, I used my own CA - however, it fails to serve the page over SSL/TLS. I tried using @fidelito17 method and modifying/adding the “mod_alias” to lighttpd.conf as well as commenting/removing the ssl.use-compression = “disable”

This site can’t be reached
dns1.domain.com refused to connect.

Over Chrome (version 67.0.3396.99) hit F12 - Security :

Certificate - valid and trusted
The connection to this site is using a valid, trusted server certificate issued by unknown name.

Resources - all served securely
All resources on this page are served securely.

The certificates do not seem to be the issue. Not sure what I’m missing here.
Please let me know if you have any ideas.

Steps taken :

  1. Modifying the [“host”] section /etc/lighttpd/external.conf file to dns1.domain.com
  1. Pointing the ssl.pemfile and ssl.ca-file to the respective directory
  • ssl.pemfile = “/home/pi/Downloads/dns1.pem”
  • ssl.ca-file = “/home/pi/Downloads/root.pem”
  1. Note - have tried RSA and ECDSA based CA’s, and tried changing the ssl.cipher-list; always shows the error of refusing to connect. The FQDN does have an A record, and the certificate does have the SAN for the FQDN. Created the dns1.pem via cat server.crt server.key > dns1.pem

Permissions :
pi@dns1:~/Downloads$ ls -l
total 16
-rw-r–r-- 1 pi pi 8387 Jul 15 08:46 dns1.pem
-rw-r–r-- 1 pi pi 1838 Jul 15 07:46 root.pem

lighttpd -v : lighttpd/1.4.45 (ssl) - a light and fast webserver Build-Date: Jan 14 2017 21:07:19

openssl version : OpenSSL 1.1.0f 25 May 2017

Raspbian version : Linux version 4.14.52-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1123 SMP Wed Jun 27 17:35:49 BST 2018


#18

Yes, that helped, thank you!