TL;DR: A Raspberry Pi can run your entire privacy infrastructure: Pi-hole blocks ads and trackers for every device on your network, WireGuard provides a VPN to access your home network securely from anywhere, and Nextcloud gives you private cloud storage. Total cost: under $100 for hardware that runs 24/7 on about 5 watts. This guide walks through setting up all three services using Docker.
What We're Building
A single Raspberry Pi running three privacy-enhancing services:
| Service | What It Does |
|---|---|
| Pi-hole | Network-wide ad and tracker blocking via DNS |
| WireGuard | VPN server for secure remote access |
| Nextcloud | Private cloud storage (Google Drive alternative) |
Why This Matters
- Pi-hole: Blocks ads, trackers, and malware domains before they load, on every device, including smart TVs and IoT devices that can't run ad blockers
- WireGuard: Access your home network from anywhere without exposing services to the internet. Your data stays out of commercial VPN providers' hands
- Nextcloud: Your files, on your hardware. No scanning, no AI training, no terms of service changes
Hardware Requirements
Recommended Setup
| Component | Recommendation | Approx. Cost |
|---|---|---|
| Raspberry Pi | Pi 5 (4GB+) or Pi 4 (4GB+) | $60-80 |
| MicroSD Card | 32GB+ high endurance | $10-15 |
| Power Supply | Official USB-C (5V 5A for Pi 5) | $12 |
| Case | With cooling (passive or active) | $10-20 |
| Ethernet Cable | Wired connection recommended | $5 |
Optional but recommended: USB SSD for Nextcloud storage (much faster and more reliable than SD card).
Minimum Viable Setup
A Raspberry Pi 4 with 2GB RAM can run Pi-hole and WireGuard. Add Nextcloud only with 4GB+ RAM.
Initial Raspberry Pi Setup
Step 1: Flash Raspberry Pi OS
- Download Raspberry Pi Imager
- Choose "Raspberry Pi OS Lite (64-bit)", no desktop needed
- Click the gear icon for advanced options:
- Enable SSH
- Set username and password
- Configure WiFi (if not using Ethernet)
- Set locale/timezone
- Flash to SD card
Step 2: First Boot and Update
# Find your Pi's IP address from your router, then SSH in
ssh pi@YOUR_PI_IP
# Update everything
sudo apt update && sudo apt upgrade -y
# Set a static IP (recommended)
sudo nmtui
# Select "Edit a connection" > Your interface > IPv4 > Manual
# Set your desired static IP, gateway, and DNS
Step 3: Install Docker
# Install Docker
curl -sSL https://get.docker.com | sh
# Add your user to docker group
sudo usermod -aG docker $USER
# Log out and back in
exit
ssh pi@YOUR_PI_IP
# Verify Docker works
docker --version
Service 1: Pi-hole (Ad Blocking)
Pi-hole acts as a DNS sinkhole, blocking requests to known advertising, tracking, and malware domains before they reach your devices.
Create Directory Structure
mkdir -p ~/docker/pihole
cd ~/docker/pihole
Create Docker Compose File
Create docker-compose.yml:
version: "3"
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
environment:
TZ: 'America/New_York'
WEBPASSWORD: 'YOUR_SECURE_PASSWORD'
volumes:
- './etc-pihole:/etc/pihole'
- './etc-dnsmasq.d:/etc/dnsmasq.d'
restart: unless-stopped
Start Pi-hole
docker compose up -d
# Check it's running
docker ps
Configure Your Network
Option A: Router-level (recommended)
- Log into your router's admin panel
- Find DHCP settings
- Set DNS server to your Pi's IP address
- All devices will automatically use Pi-hole
Option B: Per-device
Manually set DNS on each device to your Pi's IP address.
Access Pi-hole Dashboard
Navigate to http://YOUR_PI_IP/admin
Add More Blocklists
In the Pi-hole admin panel, go to Adlists and add:
https://raw.githubusercontent.com/StevenBlack/hosts/master/hostshttps://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txthttps://someonewhocares.org/hosts/zero/hosts
Service 2: WireGuard (VPN)
WireGuard lets you securely access your home network from anywhere. When connected, you'll also use Pi-hole for DNS, ad blocking on the go.
Create Directory and Compose File
mkdir -p ~/docker/wireguard
cd ~/docker/wireguard
Create docker-compose.yml:
version: "3"
services:
wireguard:
image: linuxserver/wireguard:latest
container_name: wireguard
cap_add:
- NET_ADMIN
- SYS_MODULE
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- SERVERURL=YOUR_DDNS_OR_PUBLIC_IP
- SERVERPORT=51820
- PEERS=phone,laptop,tablet
- PEERDNS=YOUR_PI_LOCAL_IP
- INTERNAL_SUBNET=10.13.13.0
volumes:
- ./config:/config
- /lib/modules:/lib/modules
ports:
- 51820:51820/udp
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
restart: unless-stopped
Replace:
YOUR_DDNS_OR_PUBLIC_IPwith your public IP or dynamic DNS hostnameYOUR_PI_LOCAL_IPwith your Pi's local IP (e.g., 192.168.1.50)
Start WireGuard
docker compose up -d
# View generated QR codes for mobile setup
docker logs wireguard
Router Configuration
Forward UDP port 51820 from your router to your Pi's IP address.
Dynamic DNS (If Needed)
If your ISP changes your IP, use a free DDNS service:
Connect Clients
Download WireGuard app on your phone/laptop and scan the QR code from the logs, or copy the config files from ~/docker/wireguard/config/peer_*/.
Service 3: Nextcloud (Private Cloud)
Nextcloud provides file storage, calendar, contacts, and more, all under your control.
Create Directory Structure
mkdir -p ~/docker/nextcloud
cd ~/docker/nextcloud
Create Docker Compose File
version: "3"
services:
nextcloud:
image: nextcloud:latest
container_name: nextcloud
ports:
- "8080:80"
volumes:
- ./nextcloud:/var/www/html
- ./data:/var/www/html/data
environment:
- MYSQL_HOST=db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=YOUR_DB_PASSWORD
depends_on:
- db
restart: unless-stopped
db:
image: mariadb:10
container_name: nextcloud-db
environment:
- MYSQL_ROOT_PASSWORD=YOUR_ROOT_PASSWORD
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=YOUR_DB_PASSWORD
volumes:
- ./db:/var/lib/mysql
restart: unless-stopped
Start Nextcloud
docker compose up -d
Initial Setup
- Navigate to
http://YOUR_PI_IP:8080 - Create admin account
- Database is already configured via environment variables
External Storage (Recommended)
For better performance and longevity, mount a USB SSD:
# Find your drive
lsblk
# Format if needed (WARNING: erases data)
sudo mkfs.ext4 /dev/sda1
# Create mount point
sudo mkdir /mnt/nextcloud-data
# Mount
sudo mount /dev/sda1 /mnt/nextcloud-data
# Add to fstab for auto-mount
echo '/dev/sda1 /mnt/nextcloud-data ext4 defaults 0 2' | sudo tee -a /etc/fstab
# Update docker-compose.yml data volume:
# - /mnt/nextcloud-data:/var/www/html/data
Access via VPN
With WireGuard running, you can access Nextcloud from anywhere through your VPN, no need to expose it to the public internet.
Security Hardening
Firewall
sudo apt install ufw -y
# Allow SSH
sudo ufw allow 22/tcp
# Allow DNS (Pi-hole)
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
# Allow Pi-hole web interface (local only)
sudo ufw allow from 192.168.1.0/24 to any port 80
# Allow WireGuard
sudo ufw allow 51820/udp
# Allow Nextcloud (local only)
sudo ufw allow from 192.168.1.0/24 to any port 8080
# Enable firewall
sudo ufw enable
Fail2ban
See our dedicated Fail2ban Setup Guide for protecting SSH and services from brute force attacks.
Automatic Updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure unattended-upgrades
Docker Container Updates
# Update all containers
cd ~/docker/pihole && docker compose pull && docker compose up -d
cd ~/docker/wireguard && docker compose pull && docker compose up -d
cd ~/docker/nextcloud && docker compose pull && docker compose up -d
Optional: Portainer (Web Management)
Portainer provides a web interface for managing Docker containers.
docker volume create portainer_data
docker run -d -p 9000:9000 --name=portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Access at http://YOUR_PI_IP:9000
Troubleshooting
Pi-hole Not Blocking Ads
- Verify your device is using the Pi as DNS:
nslookup google.com - Check Pi-hole is running:
docker ps - Clear browser DNS cache and restart
WireGuard Won't Connect
- Verify port 51820/UDP is forwarded on your router
- Check your public IP or DDNS is correct in config
- View logs:
docker logs wireguard
Nextcloud Slow
- Use USB SSD instead of SD card
- Enable Redis caching (requires additional container)
- Check Pi temperature:
vcgencmd measure_temp
General Docker Issues
# View logs
docker logs container_name
# Restart container
docker restart container_name
# Check resource usage
docker stats
The Bottom Line
For under $100 in hardware and a few hours of setup, you have:
- Network-wide ad and tracker blocking for every device
- A personal VPN that doesn't log your data
- Private cloud storage under your complete control
The Pi runs 24/7 on about 5 watts, less than a night light. Maintenance is minimal: occasional updates and backups. The privacy benefits are permanent: your data stays in your home, not on corporate servers.