Infrastructure

A homelab run like production

A Proxmox VE node run with production discipline. Not a pile of containers that happen to work, but infrastructure with backups that get restored, traffic that cannot leak, and services that heal themselves after a reboot.

  • Proxmox
  • ZFS
  • nftables
  • Network namespaces
  • Caddy
  • Linux ops
13
containers and VMs
2
mirrored ZFS pools
nightly
backups
restore
tested, not assumed
homelab · live topology sanitized
The map

Architecture

This is what actually runs on it. Friday and Jarvis live here, one trusted and one deliberately not, and so does my Mealie fork. The GPU does double duty: NVENC transcoding for playback and CUDA for the assistants' speech stack.

Click any component for what it runs and the decision behind it. Or drive traffic through it: trace an egress path, then try to break the isolation two different ways.

homelab · traffic map trace it
Internet VPN provider endpoint sole egress path LAN gateway no route from namespace Hypervisor · Proxmox VE Proxy VM Caddy · TLS terminates here Container host (LXC) egress-controlled namespace VPN tunnel Isolated workloads no default route Mealie my fork, own CI Jarvis public bot · no HA Media VM RTX 3070 passed through Playback NVENC transcoding Voice stack Whisper · Kokoro one GPU, both jobs Friday Home Assistant · private assistant Requests user-facing intake Dashboard stack overview Monitoring Netdata → Friday over MCP ZFS storage mirrored vdevs · nightly restore-tested backups

Click a box, or focus it and press Enter.

Select a component, or trace a path, to see how egress is controlled.

Internet

Two egress paths reach it, and they are not interchangeable. Ordinary services leave through the LAN gateway. Isolated workloads can only leave through the VPN provider, because inside their namespace no other route exists.

VPN provider endpoint

The single egress for the isolated namespace. The tunnel interface is the only interface those workloads can see, so this is not the preferred path out. It is the only path out.

LAN gateway

The normal route to the internet for ordinary services. The isolated workloads cannot reach it: their namespace has no interface attached to the LAN and no default route pointing at it, so there is nothing for a misconfigured app to fall back to.

Hypervisor · Proxmox VE

The single host everything runs on, carved into VMs and LXC containers. Each guest carries its own default-deny firewall rather than relying on the cluster firewall, so the host is not the only thing between a service and the network, and guests stay portable.

Container host (LXC)

Runs the containerized workloads. It holds the egress-controlled network namespace, which is what makes the isolation structural instead of a setting somebody could toggle off.

VPN tunnel

Owns the only interface inside the namespace. Everything the isolated workloads send leaves through here. If it drops, they do not fall back to the LAN, they simply lose connectivity, which is the correct failure mode.

Isolated workloads

Containers that need internet access but must never touch it directly. They run inside the namespace with no default route of their own. A leak would require a route that does not exist, so there is no configuration mistake available to make.

Proxy VM · Caddy

All TLS terminates here and every service sits behind it. Nothing is exposed directly, so there is one front door to harden instead of a dozen.

Requests LXC

The user-facing intake, kept separate from the workloads that act on what it receives. A blast-radius decision: the part strangers touch is not the part with credentials and disk access.

Media VM · GPU passthrough

The RTX 3070 is passed through to this VM alone, and it does two jobs at once: NVENC transcoding for playback, and CUDA for the voice assistants' speech stack. One card, two workloads, no contention in practice because they peak at different times.

Playback · NVENC

Hardware transcoding on the 3070. This is the workload the GPU was bought for; the voice stack moved in later and fits alongside it.

Voice stack · Whisper + Kokoro

Speech-to-text and the synthesized voice for both assistants, sharing the same GPU as transcoding. Measuring this pipeline is what showed that text-to-speech, the stage that sounds like it should be slow, is the fastest part of a response.

Friday · the private assistant

Runs on Home Assistant in its own container. It knows the infrastructure, can act on it, and reads live host sensors from monitoring rather than guessing at them. Only I talk to it, which is exactly why it's allowed to know all of this.

Jarvis · the public bot

The Discord bot my friends talk to. It runs here on the container host, holds no Home Assistant token, and has no code path to Friday. Its entire capability is three functions. It cannot leak a homelab it was never told about.

Mealie · my fork

A fork of the recipe manager I build in my own CI and deploy here as nightly images. Running what I build is the point: every regression I ship lands on the machine I use at dinner.

Dashboard LXC

A single overview of the stack's health and quick links, so checking on things does not mean remembering ports and addresses.

Monitoring · Netdata

Per-second metrics across the node, wired into LLM tooling over MCP. I can ask about the infrastructure's health in plain English and get real numbers back instead of guessing.

ZFS storage · mirrored vdevs

Mirrored vdevs rather than RAIDZ: expansion by matched pairs and faster resilvering. Backups run nightly and get restore-tested, because a backup that has never been restored is a hope, not a backup.

Decisions

Design decisions

Each of these was a choice with a reason, not a default I inherited.

  • Mirrored ZFS vdevs over RAIDZ. Expansion by matched pairs and faster resilver, which matters more to me than raw capacity efficiency.
  • Backups are restore-tested. A backup that has never been restored is a hope, not a backup.
  • Default-deny nftables inside each guest instead of the cluster firewall. One landmine avoided, and the guests stay portable.
  • Egress isolation by network namespace, not by configuration. The workloads that must not leak have no route that bypasses the tunnel. Fail-closed is a property of the topology, so it holds even when the tunnel dies.
  • TLS terminates at a dedicated reverse proxy. Services are never exposed directly.
  • systemd recovery units, so a reboot heals the stack without a human in the loop.
  • Netdata monitoring wired into LLM tooling over MCP. The infrastructure is queryable in plain English.

what it demonstrates

Virtualization, storage design, network segmentation, backup discipline, Linux operations, and AI-augmented operations. Same control mindset as the day job, applied at home.