Enabling HTTPS for your Pi-hole Web Interface


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-compression = "disable"
    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.


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.

Admin Web interface over HTTPS
SSL for Blocked Pages?
HTTPS for Pi-hole Web Interface
Pi-hole Web Interface: The Next Generation
Disable SSL Apache vhost

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!


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?


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:


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:


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?


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.


Thanks for the guide, works perfect :smiley:


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?



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


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”


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


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