Homelab · 9 nodes · 3 sites

Homelab Architecture

Currently three sites, two tailnets, one cluster.

07

Applications

The things with users: public sites, a set of MCP servers that hand Claude real data, and a bot. Each is a small container on the cluster, reached by hostname through the edge.

Site
tracktires.io

Public site, served through the edge.

Site
dmf.dev

This site. Built into an image on every push, deployed from git.

MCP server
M2MCP

BMW ISTA service data, handed to Claude as tools.

MCP server
Barrys MCP

Barry’s Bootcamp schedules and bookings, as tools.

MCP server
Expert Flyer MCP

ExpertFlyer seat availability and flight status, as tools.

MCP server
Track Event MCP

Motorsport events from MotorsportReg and Speed District, as tools.

Bot
Phonebot

Small utility that answers my apartment building callbox and allows entering of access codes for door unlocking.

06

Media services

The library and its machinery

Viewers and the prober reach Plex through an edge cache, nearer to wherever they are. Around it: Seerr to ask for things, Tdarr to normalise them, and an exporter feeding the observability layer. The one workload with an audience that notices.

Viewers
Users
People watching, through the edge
Health
Plex Prober

Keeps checking that playback actually works, the same way a viewer would.

Edge
Plex Edge Cache

Intercedes on the end-users behalf to build a more localized buffer of media chunks during a playback session. Applies TCP tuning over high latency paths to maximize throughput.

Server
Plex

The library, and every stream out of it.

Around Plex
Requests
Seerr

Ask for a film or a series; the rest follows.

Transcoding
Tdarr

Normalises the library in the background, across the fleet.

Metrics
Plex Metrics

Exports what Plex is doing to the observability layer.

05

Observability & management

Watching and reaching all of it

Alloy ships metrics, traces and logs from every layer to Prometheus, Tempo and Loki; Pulumi declares the infrastructure below; and when the uplink or the rack is dark, a cellular link and a KVM still reach the metal.

Observability
Prometheus, Tempo, Loki

Metrics, traces and logs from every layer, collected by Alloy and kept in one place.

Infrastructure as code
Pulumi

Declares the cluster, the tailnets, DNS and the edge, so all of it is rebuildable from a repo.

Out of band
Cellular link

A way in that depends on neither the uplink nor the rack’s own network.

Out of band
GL.iNet KVM

Console into any server through a serial-controlled KVM switch, for the day a node will not boot.

04

Foundational services

What everything above stands on

Platform pieces the layers above take for granted: VMs and microVMs when a container is not enough, S3 on Ceph, a distributed database, a remote builder, and the operator that puts all of it on the tailnet.

Compute
KubeVirt

Virtual machines as cluster objects, with their disks on Ceph.

Compute
Firecracker microVMs

Kata Containers on Firecracker: pods with a VM boundary, for anything that shouldn’t share a kernel.

Storage
Object storage

S3 on Ceph. Used for any scenario where S3 is needed.

Platform
Tailscale operator

Puts in-cluster services on the tailnet without opening a port.

Platform
BuildKit

Remote builder for the fleet; amd64 images are built natively here.

Data
CockroachDB

Distributed SQL for anything above that needs a database.

03

Network

Two tailnets, one doorway

Two tailnets keep people and infrastructure apart. The Traefik edge faces the public internet and the users tailnet through the host’s kernel Tailscale, terminates TLS with certificates it fetches from ConfigFS, and forwards each hostname over the services tailnet — the backend — through a tsnet connector built into Traefik.

Internet
Public internet
Anyone, on public hostnames
Tailnet
Users tailnet
People and devices, on tailnet hostnames
Kernel Tailscale
Edge
Traefik edge

Terminates TLS and routes by hostname. The only way in.

tsnet
Backend · tailnet
Services tailnet
Nodes, workloads, the build sandbox

Where everything talks to everything. No people on it.

Config · fetched by the edge
ConfigFS

Routes and TLS certificates.

02

Logical

One cluster, one storage system

All nine machines join one cluster with a single control plane, at home. Rook runs Ceph across the rack’s seven nodes only; everything stateful — volumes, VM disks, buckets — lands there, and the Fly.io nodes hold none of it.

microk8s
Kubernetes
9 nodes · 3 sites
Home
control plane
workerworkerworkerworkerworkerworker
Rook / Ceph
blockfilesystembucket
Every volume, VM disk and bucket
SJC
worker
SYD
worker
01

Physical

A rack at home, Fly.io abroad

Seven servers in a rack at home on a 10 Gbps network, five of them full of disks, and a Fly.io machine each in San Jose and Sydney. The rack reaches them over the public internet on a symmetric 5 Gbps uplink; everything above this line is indifferent to which side of it a workload lands on.

Home 7 machines
Home rack

Bare-metal servers on a 10 Gbps switched network.

5 of 7 nodes · 2 × 1 TB NVMe · 5 × 12 TB HDD 310 TB raw
SJC 1 machine
San Jose Fly.io

A Fly.io machine on the US west coast.

SYD 1 machine
Sydney Fly.io

A Fly.io machine on the Australian east coast.

9 machines in 3 sites