Beginner~30 minRaspberry Pi
Host a website on a Raspberry Pi
A static site (plain HTML, CSS and JS) is the easiest thing to self-host: there’s no database and almost nothing to attack. Caddy is a web server that gets and renews HTTPS certificates for you automatically.
1. Install Caddy
sudo apt update
sudo apt install -y caddy
caddy version
2. Copy your site over
sudo mkdir -p /var/www/site
# from your computer:
rsync -av --delete ./dist/ pi@<pi-address>:/tmp/site/
# on the Pi:
sudo rsync -av --delete /tmp/site/ /var/www/site/
3. Point Caddy at it
Edit /etc/caddy/Caddyfile. Before you have a domain, serve on port 80 on your LAN:
:80 {
root * /var/www/site
encode zstd gzip
file_server
}
Once you own a domain and its DNS points at you, replace :80 with the domain name. Caddy will fetch a certificate on its own.
sudo systemctl reload caddy
4. Put it on the internet
Two common options:
- Cloudflare Tunnel. The Pi makes an outbound connection to Cloudflare, so you don’t open any ports and your home IP stays hidden.
- Port forwarding. Forward TCP 80 and 443 on your router to the Pi and point the domain’s A record at your public IP. Simple, but your home IP is public.
Intermediate~45 minPrivacy
Pi-hole + Unbound
Pi-hole blocks ads and trackers for every device on your network by refusing to look up their domains. Unbound turns your server into its own recursive DNS resolver, so lookups go straight to the authoritative servers instead of through Google or Cloudflare.
1. Install Pi-hole
curl -sSL https://install.pi-hole.net | bash
2. Install Unbound
sudo apt install -y unbound
Create /etc/unbound/unbound.conf.d/pi-hole.conf:
server:
verbosity: 0
interface: 127.0.0.1
port: 5335
do-ip4: yes
do-udp: yes
do-tcp: yes
do-ip6: no
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: no
edns-buffer-size: 1232
prefetch: yes
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
sudo systemctl restart unbound
dig pi-hole.net @127.0.0.1 -p 5335
3. Connect them
In the Pi-hole admin page under Settings → DNS, untick every upstream provider and add a custom upstream of 127.0.0.1#5335. Then set your router’s DHCP DNS server to the Pi-hole’s address.
Intermediate~45 minNetworking
WireGuard VPN server
A VPN back into your home network lets you reach your server, NAS and Pi-hole from anywhere. WireGuard is fast, modern, and has a small, easy-to-read config.
1. Install and make keys
sudo apt install -y wireguard
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee phone.key | wg pubkey > phone.pub
2. Server config
/etc/wireguard/wg0.conf (replace eth0 with your LAN interface):
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of server.key>
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <contents of phone.pub>
AllowedIPs = 10.8.0.2/32
3. Turn it on
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sudo systemctl enable --now wg-quick@wg0
Forward UDP 51820 on your router to the server. On the phone, create a tunnel with phone.key as its private key, address 10.8.0.2/32, DNS set to your Pi-hole, and the server’s public key and your public IP as the peer.
Keep *.key files private. Anyone with a private key can join your network.
Intermediate~30 minAI
Local AI with Ollama + Open WebUI
Run the model on the machine with the GPU, and the chat interface on a Pi so it’s always up.
1. On the GPU machine
curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen3-coder:30b
# let other machines on your LAN reach it:
sudo systemctl edit ollama
# [Service]
# Environment="OLLAMA_HOST=0.0.0.0"
sudo systemctl restart ollama
2. On the Pi
With Docker installed:
docker run -d --name open-webui --restart always \
-p 3000:8080 \
-e OLLAMA_BASE_URL=http://<gpu-machine-ip>:11434 \
-v open-webui:/app/backend/data \
ghcr.io/open-webui/open-webui:main
Open http://<pi-address>:3000 and create the admin account.
Don’t expose port 11434 to the internet. Ollama has no authentication. Reach it over your VPN instead.
AdvancedHardware
SSD + Bluetooth iPod mod
[Draft: parts list, opening the case without bending it, installing the storage adapter, battery swap, Bluetooth board and where it fits, restoring and loading music.]