Skip to main content
· Homelab · 3 min read

Your Old Raspberry Pi Is Still Useful: DNS + VPN in 20 Minutes

Before upgrading to k3s and declarative manifests, the first incarnation of my home server was simpler: Pi-hole for ad blocking and PiVPN (WireGuard) for remote access. Two services, one Pi, zero subscription fees. Here’s the minimal setup that actually works.

The Two Services

%%{ init: { 'look': 'handDrawn' } }%%
graph LR
    A[Remote client<br/>Laptop/Phone] -->|WireGuard VPN| B[Raspberry Pi<br/>PiVPN:51820]
    B --> C[Pi-hole DNS:53]
    C -->|Clean queries| D[Upstream DNS<br/>1.1.1.1]
    C -->|Blocked| E[0.0.0.0<br/>No response]
    A -->|DNS query<br/>through VPN| B
    F[Local device] -->|DNS| C

Pi-hole: Network-wide ad blocking at the DNS level. Every device on your LAN gets ad-free browsing without per-app configuration.

WireGuard: A modern VPN that takes 5 minutes to set up and uses ~4000 lines of code (vs OpenVPN’s ~100,000). Generates a QR code for mobile clients.

Install Pi-hole

curl -sSL https://install.pi-hole.net | bash

During setup:

  • Set a strong admin password
  • Choose eth0 as the interface
  • Enable the web interface
  • Write down the admin URL: http://pi.hole/admin

After install, access the dashboard and add blocklists from firebog.net:

# Via the pihole command line
pihole -b https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
pihole -b https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt
pihole -b https://v.firebog.net/hosts/AdguardDNS.txt

Configure Router DHCP

%%{ init: { 'look': 'handDrawn' } }%%
graph TD
    A[Router DHCP settings] -->|DNS server 1| B[Pi-hole IP<br/>e.g. 192.168.1.100]
    A -->|DNS server 2| C[1.1.1.1<br/>Fallback]
    D[Device connects to WiFi] --> E[Gets IP from DHCP<br/>DNS = Pi-hole]
    E --> F[All DNS queries<br/>go to Pi-hole]
    F --> G[Ad domains<br/>resolve to 0.0.0.0]
    G --> H[No ad server reached]

In your router’s DHCP settings, set the primary DNS to the Pi’s static IP. Every device on the network will now use Pi-hole automatically.

Install WireGuard via PiVPN

pivpn add

Follow the prompts — give the client a name (e.g., phone, laptop). The script generates:

  • A private key (server)
  • A public key (server)
  • A preshared key (optional, for extra security)
  • A client config file

For mobile, PiVPN prints a QR code:

pivpn qr

Scan it with the WireGuard app. Done.

Client WireGuard Config

[Interface]
PrivateKey = <client-private-key>
Address = 10.6.0.2/24
DNS = 10.6.0.1

[Peer]
PublicKey = <server-public-key>
PresharedKey = <preshared-key>
Endpoint = your-home-ip:51820
AllowedIPs = 0.0.0.0/0  # Route all traffic through VPN
PersistentKeepalive = 25

AllowedIPs = 0.0.0.0/0 routes all traffic through the VPN when connected — useful on untrusted networks. For split tunnel (only access home network), use 10.6.0.0/24.

Persistence and Auto-Start

Both services start on boot and run as long as the Pi is running. No systemd configuration needed — the PiVPN installer handles that.

Why This Is Worth Doing

  • Pi-hole: Faster page loads (DNS caching), no ads on YouTube app and smart TVs (where browser extensions don’t work), privacy (no ad trackers reaching your devices)
  • WireGuard: Access your home network from anywhere, route traffic through your home connection on untrusted WiFi, no recurring VPN subscription

Total time to set up both: about 20 minutes. The Pi runs headless, draws ~3W, and fits in a drawer.

Even if you eventually migrate to k3s and declarative manifests, starting here teaches you the operational basics: static IPs, DNS configuration, firewall rules, and service persistence.

I did eventually migrate — an SD card died and took all of this hand-configured state with it, which is how the same services ended up rebuilt on k3s with everything in git. And if you want the VPN half without a Pi at home, the same WireGuard config works on a $5 VPS — the difference is which side of your router the tunnel terminates on.