Hosting this site on my own hardware: the home server plan
· self-hosting, raspberry-pi, cloudflare, tailscale, homelab
This very site runs on hardware sitting in my home — two Raspberry Pi 4s, no cloud bill, no open ports on my router. Here’s the plan I followed and the architecture that makes it both public and private at the same time.
Goal: run a public portfolio/blog on my own hardware, manage everything privately from anywhere over a VPN, using free services wherever possible.
Hardware: 2× Raspberry Pi 4 (8GB RAM)
Domain: luckyganesh.in
Total ongoing cost: ₹0/year — the domain was already paid for, and every
service below has a free tier.
The core principle
The whole design comes down to one rule:
The public site and the private admin never share a door.
Anyone on the internet can reach the blog. But SSH and the admin dashboards are only reachable by me, over a VPN. Those two paths never touch.
Architecture
Internet (anyone) Me, from anywhere
│ │
Cloudflare network Tailscale app
(DDoS + caching) (WireGuard VPN)
│ │
outbound-only tunnel encrypted mesh
│ │
┌──────────────────────▼─────────────────────────────────────▼──────────┐
│ HOME NETWORK (no open ports on the router!) │
│ │
│ Pi #1 "apollo" Pi #2 "vault" │
│ ├─ cloudflared (tunnel) ├─ Pi-hole (DNS adblock) │
│ ├─ Caddy reverse proxy ├─ backups (restic) │
│ ├─ Astro portfolio+blog (public) ├─ Uptime Kuma (monitoring) │
│ └─ admin apps (VPN-only) └─ Tailscale (VPN node) │
└────────────────────────────────────────────────────────────────────────┘
- Public traffic enters via a Cloudflare Tunnel — an outbound connection from the Pi to Cloudflare. That means zero router ports opened, my home IP stays hidden, and I get free DDoS protection.
- My own access goes over Tailscale, a WireGuard mesh VPN. SSH and admin
apps are never exposed to the internet — with MagicDNS I just
ssh apollofrom anywhere.
Two Pis, two jobs
- Pi #1 —
apollo: the website host. Runscloudflared, a Caddy reverse proxy, and the Astro site you’re reading right now. - Pi #2 —
vault: the helper. Handles backups, monitoring, ad-blocking DNS, and acts as a Tailscale node on the home network.
The free-services stack
Everything is open source or has a genuinely free tier:
| Need | Tool |
|---|---|
| VPN (access from anywhere) | Tailscale |
| Public exposure (no port forwarding) | Cloudflare Tunnel |
| DNS + CDN | Cloudflare DNS |
| Website + blog | Astro |
| Reverse proxy + auto-HTTPS | Caddy |
| Containers | Docker + Compose |
| Ad-block DNS | Pi-hole |
| Monitoring / uptime | Uptime Kuma + Glances |
| Backups | restic |
Why Astro
For the website itself I picked Astro: a static-site
generator that’s fast, secure, and uses almost no RAM — ideal for a Raspberry
Pi. Publishing a post is just: write Markdown, git push, and the Pi rebuilds
the static site automatically.
The publishing workflow
Posting is delightfully boring:
- Create a Markdown file under
src/content/blog/. - Write the post.
git push.- The Pi pulls, rebuilds, and the new post goes live.
That’s the same flow that published this post. More to come as I build each phase out — next up: getting the tunnel and VPN wired together so the whole thing is reachable (and only by the right people).