Pi-hole uses lighttpd by default, but you can switch to nginx if you prefer.

Here’s a Pi-hole running with lighttpd, serving DNS queries and its web interface:

# Example of a DNS query being blocked and logged
# User requests ad.example.com
# Pi-hole blocks it, shows a 0.0.0.0 IP in logs

# Web interface shows blocked queries graph
# This is lighttpd serving the HTML, CSS, and JS for the dashboard

The core problem Pi-hole solves is ad blocking at the network level. Instead of installing ad blockers on every device, you configure your router to use Pi-hole as its DNS server. Pi-hole then intercepts DNS requests and, based on its blocklists, either resolves the domain to a real IP address or returns a null IP (like 0.0.0.0) for blocked domains. The web server is responsible for the dashboard that lets you manage Pi-hole, view stats, and whitelist/blacklist domains.

By default, Pi-hole ships with lighttpd, a lightweight web server known for its speed and low resource usage. It’s configured to serve the Pi-hole web interface, which is a collection of HTML, CSS, and JavaScript files. lighttpd also acts as a proxy for the Pi-hole API, allowing the dashboard to fetch real-time statistics and interact with the Pi-hole core.

The configuration for lighttpd is typically found in /etc/lighttpd/lighttpd.conf. Key directives include:

  • server.document-root: Specifies the directory where the web server looks for files to serve. For Pi-hole, this is /var/www/html/admin/.
  • server.port: The port the web server listens on, usually 80 for HTTP.
  • proxy.server: Configures the reverse proxy. Pi-hole uses this to forward API requests (e.g., /admin/api.php) to the pihole-FTL service, which handles DNS logging and statistics.

A common lighttpd configuration snippet for Pi-hole’s API proxy looks like this:

# /etc/lighttpd/lighttpd.conf
proxy.server = (
    "/admin/api.php" => (
        "host" => "127.0.0.1",
        "port" => 4711
    )
)

This tells lighttpd that any requests starting with /admin/api.php should be forwarded to pihole-FTL listening on 127.0.0.1:4711.

You can switch to nginx by running pihole -r and selecting "Reconfigure". During the reconfiguration process, you’ll be prompted to choose your web server. If you choose nginx, Pi-hole will install and configure it.

The nginx configuration for Pi-hole is usually placed in /etc/nginx/sites-available/pihole.conf. It will contain directives similar to lighttpd’s, but with nginx syntax.

An example nginx configuration for Pi-hole might look like this:

# /etc/nginx/sites-available/pihole.conf
server {
    listen 80;
    server_name pi.hole your.domain.com; # Replace with your actual domain or IP

    root /var/www/html/admin;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~ ^/admin/api.php {
        proxy_pass http://127.0.0.1:4711;
        proxy_set_header Host $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;
    }

    # ... other locations for static assets ...
}

Here, proxy_pass http://127.0.0.1:4711; achieves the same goal as lighttpd’s proxy configuration, directing API requests to pihole-FTL.

The most surprising thing about Pi-hole’s web server setup is that even though it’s a relatively simple web interface, it relies on a robust reverse proxy configuration to dynamically serve statistics and allow control actions without directly exposing the pihole-FTL service to the internet. This separation of concerns is crucial for security and stability.

The core difference in how lighttpd and nginx handle the API proxy comes down to their internal event loops and how they manage connections. lighttpd uses an event-driven architecture with a focus on simplicity and efficiency, often using select() or poll() for I/O multiplexing. nginx, on the other hand, is also event-driven but is renowned for its asynchronous, non-blocking architecture, which allows it to handle a massive number of concurrent connections with very low memory overhead. For Pi-hole’s relatively low-traffic API, both perform admirably, but nginx might offer a slight edge in handling very high volumes of dashboard requests or concurrent API calls, though this is rarely a bottleneck for typical home users.

When configuring Pi-hole, especially if you’re setting up a custom domain or SSL, you’ll need to ensure your chosen web server is correctly configured to serve both the static admin files and proxy requests to pihole-FTL.

The next concept you’ll likely explore is setting up Pi-hole with HTTPS for secure access to the web interface.

Want structured learning?

Take the full Pihole course →