Pi-hole.net is a self-hosted DNS service that you can install on your own machine (such as in a USD5 per month VPS) and let us create a black hole for internet advertisers. While there are other free DNS services available on the internet, such as Google DNS, Cloudflare, Quad9, none of them offer us a way to block particular domains (such as google-analytics.com). Pi-hole.net (shortly pi-hole) itself depends on Google DNS, Cloudflare or Quad9 to upstream its DNS requests. I am not going to write about the benefits of using pi-hole, since that information is already available and is covered by a lot more people who have adapted pi-hole much earlier than me.

I am going to write a bit about how I run pi-hole on my VPS that hosts other sites too. While, it takes only a single-line of code to isntall it (curl -sSL https://install.pi-hole.net | bash), I have set it up in a particular way, such as running it behind Nginx (along with other sites), administrating it using a non-existing domain name(!), SSL for that domain(!!) and a few more. Let’s dive into my setup.


Pi-hole is meant to be run on its own tiny server, probably in a raspberry pi server. But, it doesn’t prevent you to run along with other sites in a VPS. I put it alongside other sites in my Vultr VPS.

Pi-hole is a complete package. It installs a DNS server, HTTP web server (lighttpd), firewall, setup upstream DNS server, etc. Except for the HTTP server (that is lighttpd), other services wouldn’t create conflict. The web server is used to administer pi-hole via server IP. The HTTP web server (tries to) take over port 80. Since, my VPS already has a web server (Nginx) running on port 80, lighttpd server would never take over port 80. So, we can’t use a URL to manage pi-hole?! No, we can. The solution is to keep lighttpd running on an alternate port (such as 88) and let Nginx proxy all requests to pi-hole to that port.

Here’s the complete config for clarity…

server {
    listen 80;
    listen [::]:80;
    server_name pi.hole;
    return https://$host$request_uri;
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name pi.hole;

    ssl_certificate 'ssl/pi.hole.crt';
    ssl_certificate_key 'ssl/pi.hole.key';

    location / {
        proxy_pass http://localhost:8888;
        include proxy.conf;

    # let's go directly to the login page
    location = / {
        return $scheme://$host/admin/index.php?login;

The proxy.conf file contains the following lines…

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

So, we solved one issue now. We installed pi-hole in a VPS that hosts other sites using a different web server (Nginx). This could be easily migrated to Apache or another web server.

Non-existing Domain!

When using the defaults, pi-hole installs lighttpd and the admin dashboard for pi-hole can be accessed using the IP of the server, such as (this is a local IP, though). Since, internet is full of bad bots, anyone can get to this link easily. In order to access it via a domain, we only need to point the domain such as pi.example.com to the IP of the server. The rest of the things are taken care by the web server. We still do not want anyone to have the data of the site, if they came across the URL pi.example.com somehow. Pi-hole displays some data for non-logged-in users too. Just minimal data… total queries, queries blocked, etc. When logged-in, we can see much more useful information and we would get the ability to fine-tune the whole pi-hole setup.

As you may have noticed from the Nginx config line has pi.hole as the server_name. Pi-hole, when being installed, points pi.hole to the server itself. But, if we need to access pi-hole (or https://pi.hole site) even if we do not use pi-hole for DNS, we could edit our own machine’s hosts file to have this domain pointed to the server where pi-hole is installed. Accessing pi-hole using this non-existing domain could be considered as an improvement to the security too. Remember that we can use any non-existing domain in this way. Not just https://pi.hole.


SSL part is actually very easy (for me). I already run on my own SSL CA for developing sites under the extension .dev (for example, example.dev). I also have a script that generates SSL for these local domains (or for any domain to be precise). How to run your own SSL CA and how to automate the generation of SSL is for another post, though. The point is that you can secure the connection between your browser and pi-hole admin backend, if you run your own SSL CA.

Other Tweaks:

There are other small tweaks are done in my pi-hole configuration. As you may have noticed from the Nginx configuration above, whenever I visit https://pi.hole, it redirects to https://pi.hole/admin/index.php?login which is the login page for pi-hole admin dashboard. So, I save a click using a simple redirect in Nginx.

Do you have any tips and tricks for your pi-hole setup? Please share it in the comments!