Moving a Raspberry Pi Offsite: Everything That Went Wrong

The Plan Move pi-burg, my Raspberry Pi 3 running restic as an offsite backup target, from my house to my mom’s. Simple, right? It already had Tailscale, so once it was on her wifi it would just appear on the tailnet from wherever. Total estimated time: 15 minutes. Total actual time: ~6 hours. The Stack Raspberry Pi 3 running Raspberry Pi OS Lite 8TB USB drive with an existing restic repository Tailscale for tailnet connectivity (no static IPs, no port forwarding) A long drive to mom’s house What Was Supposed to Happen Configure wifi on the Pi for mom’s network before leaving home Drive to mom’s Plug in power, let Tailscale come up Profit What Actually Happened Chapter 1: Cloud-init Is a Liar The Pi was already provisioned, so I edited /boot/firmware/network-config from my Mac to add mom’s wifi. I even recomputed the WPA PSK hash because the stored one was for a different SSID. Saved, ejected, booted. ...

April 4, 2026 · 6 min · Adam Behn

Self-Hosting OpenMemory MCP on Proxmox with Tailscale

The Goal I wanted a persistent AI memory layer — something that stores context across conversations and tools, accessible from Claude Desktop, Claude Code, and eventually other MCP clients. The official mem0 platform exists, but I wanted to self-host it on my Proxmox cluster for control and privacy. The Stack The deployment runs on mem01 (LXC 3003, pve02) with three Docker containers: Ollama — LLM inference for embeddings (bge-m3) and chat (qwen3:8b) OpenMemory — the MCP server itself, using SQLite for vectors and metadata Open WebUI — optional web interface for testing I started with mem0-mcp-selfhosted (Neo4j + Qdrant + Python SDK) but it crashed repeatedly and had a painful dependency chain. OpenMemory — SQLite for everything, Node.js SDK — just worked. ...

March 31, 2026 · 4 min · Adam Behn

AdGuard Home on Proxmox with EdgeRouter X-SFP: DNS, Ad Blocking, and Reverse DNS

The Problem My homelab has multiple VLANs, a Tailscale overlay network, and no ad blocking. DNS was handled entirely by the EdgeRouter X-SFP forwarding to Cloudflare. I wanted: Network-wide ad blocking without per-device configuration Conditional DNS forwarding so LAN clients can resolve Tailscale hostnames Non-Tailscale devices (Rokus, smart TVs) able to reach Tailscale services like Jellyfin Client names on the DNS dashboard instead of raw IPs The Architecture 1 2 3 4 5 6 7 8 9 10 11 12 13 LAN Clients (10.150.10.0/24) │ ├─ DNS ──→ dns01 (AdGuard Home, 10.150.60.11) │ ├─ Upstream: Cloudflare DoH, Google DoH │ ├─ Conditional: *.<tailnet>.ts.net → 100.100.100.100 │ └─ Reverse DNS: PTR queries → EdgeRouter (10.150.10.1) │ ├─ DHCP ──→ EdgeRouter X-SFP (dnsmasq) │ ├─ Primary DNS: 10.150.60.11 (AdGuard) │ ├─ Secondary DNS: 10.150.10.1 (router fallback) │ └─ Search domain: <tailnet>.ts.net │ └─ 100.x.x.x traffic ──→ static route → dns01 → MASQUERADE → tailscale0 dns01 is an LXC container on pve01 running AdGuard Home and acting as a Tailscale subnet router advertising all four LAN subnets. ...

March 25, 2026 · 4 min · Adam Behn

Proxmox Node Onboarding Runbook

Step-by-step guide for adding a new Proxmox node to a cluster, including Ceph, Tailscale, and Ansible automation.

December 4, 2025 · 15 min · Adam Behn

Building a CI/CD Pipeline Over Tailscale VPN

One of those satisfying days where a pile of “almost working” became a fully operational CI/CD pipeline. The goal: get GitHub Actions runners to test Ansible playbooks against real infrastructure over Tailscale VPN. The Problem I had Ansible playbooks managing Proxmox hosts, but no automated testing. Every change was a manual ansible-playbook --check from my laptop. I wanted PRs to automatically lint and dry-run against the real cluster before merge. ...

October 18, 2025 · 4 min · Adam Behn