May 30, 2026·7 min read

Replacing Google Fiber's Router with a Proper Network

Replacing Google Fiber's router with UniFi, and everything running on top — Pi-hole, Caddy, WireGuard, and a stack of self-hosted services.

Google Fiber is great internet. The router it ships with is not a great router.

It works fine if all you need is basic connectivity. But once you start running servers at home — anything that needs port forwarding, VLANs, a custom DNS resolver, an actual VPN, or any visibility into what's happening on your network — you hit a wall pretty quickly.

I finally replaced it. Here's what I switched to, why, and how everything fits together.

Problems with the Google Fiber setup

Before getting into what I replaced it with, it's worth being specific about what was broken, because each of these was its own daily friction point.

Management is app-only. The only way to configure the Google Fiber router is through the Google Fiber app (or Google Home app, depending on when you set it up). No web UI, no SSH, no local API. If you want to change a setting, you open your phone, wait for the app to connect, and navigate a consumer-facing mobile interface. For a device sitting at the center of a homelab, that's unworkable.

No VLAN support. There's no way to segment the network. IoT devices, servers, workstations, and guests all share the same subnet. That means a compromised smart plug theoretically has direct access to the hypervisor.

No custom DNS distribution. Pi-hole existed on the network, but there was no way to tell every device to use it automatically. Every device needed manual DNS configuration. New devices defaulted to Google's DNS. The result was an inconsistent, manually-maintained mess.

No real fixed IP assignment. DHCP reservations existed, sort of, but they were unreliable and only manageable through the app. Anything that needed a stable IP had to be configured statically at the OS level and hope nothing conflicted.

No built-in VPN. WireGuard ran as a Docker container on the server with its own port-forwarding rules, its own maintenance overhead, and a dependency chain where the VPN going down meant losing remote access to fix the VPN.

No IDS/IPS. No visibility into what's actually happening on the network. No traffic identification, no anomaly detection, no way to know if something was phoning home aggressively.

Port forwarding was tedious. Any time something needed to be reachable from outside, it meant opening the app, navigating to the forwarding section, and adding a rule through a mobile UI clearly designed for forwarding a single gaming port, not managing a homelab's worth of services.

The hardware

I went with the UniFi UCG-Fiber as the gateway, a USW-Lite-8-PoE switch, and a UniFi U7 Pro access point. The UCG-Fiber handles routing, DHCP, firewall, IDS/IPS, and WireGuard VPN natively. The PoE switch powers the access point directly over Ethernet — no power adapter needed. The U7 Pro handles WiFi 7.

The whole stack is managed through the UniFi console. It's the same software interface regardless of how many sites or devices you have, which matters when the network grows.

The network

The trusted LAN is where servers, workstations, and anything that needs to talk to the homelab lives. The IoT VLAN is isolated — Sonos, smart devices, anything that phones home goes there and can't initiate connections to the trusted network. Each VLAN gets its own subnet and firewall rules.

DHCP runs on the UCG-Fiber with Pi-hole distributed as the DNS server to every device on both VLANs. That's the key piece: every device on the network uses Pi-hole for DNS automatically, without any per-device configuration.

For IoT specifically, I intentionally don't set a DNS fallback. If Pi-hole goes down, IoT devices lose DNS — they can't quietly bypass it and start resolving tracking domains directly. That's an acceptable tradeoff.

WireGuard runs natively on the UCG-Fiber — no more Docker container on the server just for VPN (I wrote about the old Docker setup here). IDS/IPS is running in notify mode while I build a baseline of what normal traffic looks like. DPI is enabled for device and traffic identification.

Pi-hole

Pi-hole runs on a dedicated VM. It's the DNS resolver for the entire network.

The UCG-Fiber distributes the Pi-hole VM's IP as the DNS server via DHCP, so every device — workstations, phones, Sonos, IoT — queries Pi-hole for every DNS lookup. This gives you two things at once: ad and tracker blocking across all devices without any browser extension or per-app configuration, and a central place to manage internal DNS records.

For ad blocking, Pi-hole maintains a gravity database of blocklists. My current lists:

https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://raw.githubusercontent.com/hagezi/dns-blocklists/main/adblock/pro.txt
https://github.com/hagezi/dns-blocklists
https://v.firebog.net/hosts/Easylist.txt
https://big.oisd.nl

For internal DNS, I use Pi-hole v6's native dns.hosts feature. Every self-hosted service has an internal hostname — service.dop-amine.com — and Pi-hole resolves it to the right server on the LAN. From any device on the network, those hostnames just work. From outside (over WireGuard), they also work because VPN clients use the same Pi-hole.

This is managed by Ansible. The list of internal hostnames is defined in a task file, and Pi-hole is converged to that state idempotently.

Fixed IPs and server addressing

All servers and VMs have static IPs. Not DHCP reservations — actually static, assigned at the OS level. This matters because Pi-hole, Caddy, and every service reference each other by IP. DHCP leases expiring or getting reassigned would break things.

The network is organized so each VM type sits in a predictable part of the address space. Proxmox (the hypervisor) is at a fixed address, and each VM has its own fixed address. There's no ambiguity about where anything is.

Caddy as the reverse proxy

Every web UI running on the network is behind Caddy. Caddy terminates TLS, handles certificate provisioning automatically, and reverse proxies to whatever's running on each VM.

Certificates are issued via Let's Encrypt's DNS-01 challenge using Route 53. DNS-01 doesn't require exposing port 80 — Caddy writes a TXT record to Route 53 to prove domain ownership, then discards it after the cert issues. This means the entire homelab is HTTPS with real certificates, no self-signed certs, no browser warnings, and no ports open that don't need to be.

There are three Caddy instances — one per VM that hosts web services (Hub, Jarvis, Lab). Each manages a subdomain tree:

  • Hub: *.dop-amine.com — all the shared Docker services
  • Jarvis: *.jarvis.dop-amine.com — the AI assistant and Home Assistant
  • Lab: *.lab.dop-amine.com — development environments

All web ports on these VMs bind to 127.0.0.1 — they're not reachable from the LAN directly. Caddy on port 443 is the only entry point. Caddy also enforces a source IP check that aborts requests from outside RFC 1918 space.

The VMs

Everything runs on Proxmox, a bare-metal hypervisor, on a server in the homelab. There are five VMs:

  • Hub — Docker host running all the shared containerized services
  • Plex — media server with GPU passthrough for hardware transcoding
  • Jarvis — AI assistant, Home Assistant, local LLM inference via Ollama
  • Pi-hole — DNS resolver and ad blocker
  • Lab — cloud development environment with isolated workspaces

All VM configuration is managed by Ansible. The repo is the source of truth — if a VM needs to be rebuilt, ansible-playbook main.yml gets it back to the correct state. Network config, installed packages, systemd services, SSH hardening, Caddy config, and Docker compose stacks all converge automatically.

What changed with the UniFi switch

Before the migration, every workaround lived in software — Pi-hole couldn't be distributed automatically, WireGuard ran in a Docker container with port-forwarding chaos, there were no VLANs, and there was no visibility into the network. The Google Fiber router was a black box in the middle of infrastructure that needed to be transparent.

Post-migration: the router manages the network, Pi-hole manages DNS, Caddy manages TLS, and Ansible manages everything else. The layers have cleaner responsibilities, and the whole thing is documented and reproducible.

← All posts