My Home Lab: Cloudflare Tunnels, NAS, and AI at the Edge
I’ve spent the last few months building out my home infrastructure with a simple thesis: own your data, own your compute, minimize cloud dependency for personal stuff. Here’s what that looks like in practice.
The Hardware
At the center is a QNAP TS-664 — a 6-bay NAS running Intel Celeron N5105 with 8GB RAM. It handles file storage, media serving, and acts as the gateway for remote access to my home network. Nothing exotic, but reliable and quiet.
For power resilience, I run three Anker SOLIX battery stations in a tiered failover design:
- Two F3800 units (3,840 Wh each) handle whole-home power during outages
- One F1200 (1,229 Wh) is dedicated to the network station — router, switch, NAS, and Mac Studio
The failover sequence: grid drops → F3800s power the entire house. If those deplete before the generator kicks in (tri-fuel, manual start), the F1200 takes over for just the critical network/compute stack. This guarantees internet, NAS, and AI inference stay online even in extended outages. Total capacity: 8,909 Wh. Full power setup is a separate article.
Cloudflare Tunnels: Zero Port Forwarding
The traditional approach to exposing home services is port forwarding — punch holes in your firewall, pray your ISP doesn’t block ports, deal with dynamic DNS. It’s fragile and insecure.
Cloudflare Tunnel flips this model. The tunnel daemon (cloudflared) runs on your NAS and establishes an outbound-only connection to Cloudflare’s edge. Traffic flows: internet → Cloudflare edge → tunnel → your NAS. No inbound ports. No firewall rules. Your NAS’s IP never touches the public internet.
Here’s my tunnel config (sanitized):
tunnel: <tunnel-uuid>
credentials-file: /share/homes/<user>/.cloudflared/<tunnel-uuid>.json
ingress:
- hostname: storage.yourdomain.com
service: https://localhost:443
originRequest:
noTLSVerify: true
- hostname: admin.yourdomain.com
service: https://localhost:443
originRequest:
noTLSVerify: true
- service: http_status:404
The noTLSVerify: true is necessary because QNAP’s admin UI uses a self-signed cert on port 443. The tunnel terminates TLS at Cloudflare’s edge with a real cert, then connects to the NAS over the local loopback — security is maintained.
QNAP quirks I discovered the hard way:
- QNAP’s shell has no
nohupcommand. Usesetsid cloudflared tunnel run &followed bydisownto daemonize. - The admin UI runs on port 443, not 8443 as some docs suggest.
/etc/config/qnap/autorun.shdoesn’t exist on newer models (TS-664). Persistence on reboot requires either an init.d script or a QPKG wrapper — both of which may get wiped on firmware updates. This is an unsolved problem in the QNAP ecosystem.- Always use
--overwrite-dnswhen creating DNS routes if the CNAME already exists.
Zero Trust Access: Per-Path Authentication
Raw tunnel exposure isn’t enough. I gate everything behind Cloudflare Access (part of Zero Trust, free tier).
The setup:
- Authentication: Google OAuth. One click to sign in with my Google account.
- Per-path policies: Some paths are owner-only (my admin panels, lab experiments). Others are shared with my wife (photo albums, shared documents). Each gets its own Access Application with distinct email allowlists.
- No VPN required: Access works from any device, any network. Phone, laptop, tablet — authenticate once, get a session cookie, done.
The mental model: Cloudflare Access is a reverse proxy that sits in front of your tunnel and challenges unauthenticated requests. It’s like having an identity-aware firewall at the edge without running anything locally.
The Website Stack
My personal site (karmapatel.com) runs on:
- Astro — static site generator with MDX support for blog posts like this one
- Tailwind CSS — utility-first styling
- Cloudflare Pages — free hosting with automatic deploys from a private GitHub repo
The repo is private (no portfolio data leaking), and the site has auth-gated sections:
/portal— authenticated hub with identity-aware cards/vault— shared private space (both my wife and I can access)/lab— owner-only experiments
A floating nav pill appears when you’re authenticated, showing only the sections your identity grants access to. The auth check uses a JS-readable cookie set by gated pages (Cloudflare’s native cookies are HttpOnly, so you need a workaround for client-side UI logic).
Cost: $0/month. Cloudflare Pages free tier includes unlimited bandwidth, 500 builds/month, and custom domains. Zero Trust free tier covers up to 50 users. For a personal setup, you’ll never hit these limits.
AI at the Edge: Local Inference
This is the next frontier. I’m planning a Mac Studio M4 Max with 128GB unified memory specifically for running large language models locally.
Why local?
- Privacy: My notes, documents, and personal data never leave my network. No API calls shipping context to third-party servers.
- Cost: After the hardware investment breaks even (~3 months at my usage level vs. cloud API costs), inference is essentially free.
- Latency: Local inference on Apple Silicon with 400 GB/s memory bandwidth gives 25-35 tokens/second on 70B parameter models. That’s faster than most API round-trips.
- Availability: No rate limits, no outages, no deprecation notices. The model runs when I need it.
The stack will be Ollama for model serving, with models like Qwen 2.5 70B and Llama 3.1 for different tasks. Embeddings run on nomic-embed-text for semantic search over my personal knowledge base.
The Mac Studio’s 128GB unified memory is the key constraint — it determines the largest model you can run without swapping. 70B models at Q4 quantization need ~40GB, leaving headroom for KV cache and concurrent requests.
(The M4 Max 128GB configs have been unavailable since April due to DRAM shortages. Monitoring for restock.)
The Philosophy
I use cloud infrastructure professionally every day. It’s the right choice for production systems that need global scale, managed services, and team collaboration.
But for personal infrastructure — my files, my photos, my notes, my AI assistants — I want:
- Data sovereignty: My family photos aren’t training data. My financial documents aren’t in someone else’s S3 bucket.
- Longevity: Services shut down. APIs deprecate. Hardware you own keeps running.
- Control: I decide the access policies, the retention rules, the backup strategy.
- Cost predictability: One-time hardware purchases vs. recurring subscriptions that compound forever.
This isn’t anti-cloud dogma. It’s portfolio diversification applied to infrastructure. Use cloud where it excels (collaboration, scale, managed complexity). Use local where it excels (privacy, cost amortization, independence).
Practical Tips
If you’re building something similar:
-
Start with Cloudflare’s free tier. Tunnels, Access, Pages, DNS — all free for personal use. It’s absurdly generous. You get enterprise-grade zero trust without spending a dollar.
-
Budget for QNAP quirks. The hardware is solid but the software ecosystem assumes you’ll use their GUI for everything. Shell access works but you’ll hit missing utilities (
nohup), undocumented paths, and persistence mechanisms that vary by model. -
Tunnel persistence is the hardest part. Getting a tunnel running takes 10 minutes. Keeping it running across reboots, firmware updates, and power cycles is an ongoing battle on consumer NAS hardware. Consider running
cloudflaredon a Raspberry Pi instead if your NAS doesn’t cooperate. -
Separate your domains. I use subdomains (
files.,nas.,media.) with different Access policies rather than path-based routing. Cleaner separation, easier to reason about security boundaries. -
Power backup isn’t optional. If your infrastructure depends on always-on hardware at home, a UPS or battery station is table stakes. A NAS with a tunnel that dies every time the power flickers isn’t infrastructure — it’s a hobby.
The home lab is never “done.” Next up: the Mac Studio for local AI, a proper init system for the tunnel daemon, and maybe a dedicated 10GbE link between the NAS and compute nodes. But the foundation — secure remote access, authenticated services, resilient power — is solid.
Own your stack. It’s worth the weekend.