Skip to content
Frank, the Talos Cluster: Overview & Roadmap
Frank, the Talos Cluster: Overview & Roadmap

Frank, the Talos Cluster: Overview & Roadmap

The Frank, the Talos Cluster series is a walkthrough of building an AI-hybrid Kubernetes homelab from scratch, one layer per post. This post is not part of that walkthrough. It is the index to it: the roadmap, the capability map, the hardware, and a set of commands for checking whether any of it is still true.

Roadmap

1 Hardware — 7 Nodes, 3 Zones
3x Intel NUC (Core zone) 1x GPU tower — RTX 5070 1x Legacy desktop 2x Raspberry Pi 4
x86_64 arm64 heterogeneous
2 OS & Bootstrap
Talos Linux (immutable) Sidero Omni (lifecycle) Declarative machine config Rolling upgrades
no SSH API-driven reproducible
3 Networking — Cilium CNI
eBPF kube-proxy replacement L2 LoadBalancer (ARP) Hubble observability Network policy
eBPF 192.168.55.200-254
4 Storage — Longhorn
Distributed 3-replica block storage GPU-local StorageClass 2x 4TB SSD on gpu-1 iSCSI via Talos extensions
strict-local best-effort all 7 nodes
5 GPU Compute
NVIDIA GPU Operator (RTX 5070) Intel DRA driver (Arc iGPU) Dynamic Resource Allocation CDI device injection
K8s 1.35 DRA ResourceClaim DeviceClass
6 GitOps — ArgoCD
App-of-Apps pattern Multi-source Applications Self-healing + drift detection Zero-downtime adoption
single repo annotation tracking
7 Fun Stuff
OpenRGB via USB HID DaemonSet + ConfigMap Custom container build (GitHub Actions) IT5701 firmware lock (in progress)
completely unnecessary fans still rainbow
8 Observability
VictoriaMetrics (metrics + alerts) VictoriaLogs (log aggregation) Grafana dashboards Fluent Bit log shipping Blackbox Exporter (endpoint probes) Pushgateway (heartbeat ingestion) Telegram alerting Health Bridge (GitHub lifecycle) Edge Observability (blog analytics, edge security, AI alerts) metrics-server (metrics.k8s.io — kubectl top + CPU/mem HPA)
VMSingle Feature Health metrics.k8s.io health-bridge GoatCounter CrowdSec Falco ai-alert-helper 192.168.55.203
9 Backup
Longhorn → Cloudflare R2 Daily + weekly recurring jobs SOPS-encrypted credentials NAS target (pending Longhorn 1.13)
S3-compatible 7-day RPO
10 Secrets Management
Infisical (self-hosted vault) External Secrets Operator ClusterSecretStore ExternalSecret → K8s Secret
audit trail Universal Auth 192.168.55.204
11 Local Inference
Ollama (gpu-1, RTX 5070) LiteLLM (unified gateway) OpenRouter (free cloud models) OpenAI-compatible API
ollama litellm 192.168.55.206
12 Agentic Control Plane
Sympozium (K8s-native agents) n8n (per-user workflow automation) VK Remote (self-hosted kanban API) ElectricSQL real-time sync
agent=Pod n8n vibekanban 192.168.55.207 192.168.55.216
13 Unified Auth
Authentik IdP (OIDC + proxy) SSO for ArgoCD, Grafana, Infisical Forward auth for Longhorn, Hubble, Sympozium OIDC-backed kubectl via apiserver
OIDC forward-auth 192.168.55.211
14 Multi-tenancy
vCluster (K8s-in-K8s) Disposable experiment clusters Resource quotas + network policies GitOps-provisioned via ArgoCD
vcluster multi-tenant SQLite
15 AI Agent Orchestrator
Paperclip (org-chart agents) Virtual companies + budgets Delegation chains + governance LiteLLM gateway integration
paperclip company model 192.168.55.212
16 Media Generation
ComfyUI (diffusion models) LTX-2.3 video, SDXL image, Stable Audio GPU Switcher dashboard (Go) Time-sharing via replica scaling
comfyui gpu-switcher 192.168.55.213
17 Public Edge — Hop
Hetzner CX23 (single-node Talos) Headscale mesh + Tailscale Caddy reverse proxy + TLS Split-DNS (MagicDNS)
edge WireGuard blog.derio.net
18 Persistent Agent
Kali Linux workstation Always-on Claude Code agent SSH remote access 50Gi persistent /root
kali claude --remote 192.168.55.215
19 Progressive Delivery
Argo Rollouts controller LiteLLM canary (Cilium traffic split) Sympozium blue-green VictoriaMetrics analysis gates
canary blue-green workloadRef
21 Secure Agent Pod
Hardened non-root Kali container Cilium egress allowlist VibeKanban agent orchestration VK Relay (WebSocket tunnel to browser)
security vibekanban relay 192.168.55.215
24 In-Cluster Ingress
Traefik v3 on raspi edge nodes Wildcard TLS (*.cluster.derio.net) Authentik forward-auth (12 services) Homepage dashboard
traefik acme 192.168.55.220
25 CI/CD Platform
Gitea (GitHub mirror forge) Tekton Pipelines + Triggers Zot OCI registry (cosign signed) Webhook-driven CI on pc-1
gitea tekton zot 192.168.55.209
26 Agent Images and the VK-Local Sidecar
agent-images repo (shared base + children) Matrix CI with cross-repo repository_dispatch VK-local sidecar (shared /home/claude PVC) Lockstep bumper PR in frank
docker github-actions sidecar
29 Ruflo — Swarm Orchestrator
claude-flow / ruvocal (chaotic swarm) Hybrid pod: ruvocal + shell sidecar SSH+Mosh shell on 192.168.55.222 Zero frontier-LLM keys (LiteLLM-only egress)
ruflo claude-flow swarm ruflo.cluster.derio.net
30 The Frank Papers — Research Series
Third blog series (Building / Operating / Papers) Dossier gate (vendors, sources, gaps, counter-args) Mermaid Frank theme + .paper-post CSS scope Render-time cross-series backlinks (zero retrofit) Paper 00 prologue published 2026-05-18
hugo hextra mermaid research
32 Infrastructure Automation
AWX Ansible controller (operator + CR) Reaches non-Talos / external home-lab devices Native OIDC login via Authentik awx.cluster.derio.net (Traefik)
awx ansible automation
33 Hermes Agent Shell
Nous Research hermes CLI (dedicated pod, gpu-1) BYOK → LiteLLM (provider pinned in config.yaml) profile.d shim vs. sshd env-scrub SSH+Mosh shell on 192.168.55.226
hermes byok litellm
Virtual Machines — upcoming
KubeVirt (VMs as pods) CDI disk image import KubeVirt Manager UI Longhorn-backed DataVolumes
KVM 192.168.55.205

Technology → Capability Map

TechnologyCapabilities Unlocked
Talos Linux + OmniImmutable OS, declarative machine config, secure bootstrap
Cilium (eBPF)Kube-proxy replacement, L2 LoadBalancer, Hubble UI (192.168.55.202)
LonghornDistributed block storage, GPU-local StorageClass, 3-replica High AvailabilityRunning enough redundant instances that losing one does not take the service down. Frank's three control-plane nodes are its HA tier., UI (192.168.55.201)
ArgoCDGitOps, App-of-Apps, self-healing, drift detection
NVIDIA GPU OperatorGPU scheduling, AI/ML workloads, container toolkit
Intel GPU Dynamic Resource AllocationThe Kubernetes API for requesting specialised hardware — GPUs and accelerators — with far more expressiveness than the older device-plugin counter model. DriveriGPU sharing via DRA, namespace-scoped GPU access
OpenRGBLED control from K8s (just for fun)
VictoriaMetrics + GrafanaCluster-wide metrics, alerting, dashboards, Grafana UI (192.168.55.203)
VictoriaLogs + Fluent BitCentralised log aggregation and querying
Longhorn Backup + Cloudflare R2PersistentVolumeClaimA Kubernetes request for durable storage. The pod names a claim and the storage layer — Longhorn on Frank — binds real disk behind it, so the data outlives the pod. backup/restore, daily + weekly schedules, offsite storage
Infisical + External Secrets OperatorSecret management with audit trail, ExternalSecret → K8s Secret sync (192.168.55.204)
OllamaLocal Large Language ModelA model trained to predict text, served behind a chat or completion endpoint. On Frank these run locally on the GPU node rather than against a hosted provider. inference on gpu-1’s RTX 5070 Ti (16GB). Six base models as of 2026-07-29: Mistral Small 3.2 24B (default), Gemma 4 12B and Qwen2.5-VL 7B (multimodal), Qwen2.5-Coder 14B, Qwen3 14B (reasoning), Qwen3.6 35B-A3B (MoE, partial CPU offload). Lineup lives in apps/litellm/values.yaml
LiteLLMUnified OpenAI-compatible gateway, virtual keys, spend tracking (192.168.55.206). Local-only since 2026-06-04 — no free-tier cloud aliases
SympoziumKubernetes-native agentic control plane — agent=Pod, policy=CustomResourceDefinitionThe object that teaches the Kubernetes API a new resource type. Install a CRD and the API server starts serving a kind it has never heard of, with validation and RBAC like any built-in., execution=Job (192.168.55.207)
cert-managerAutomated Transport Layer SecurityThe encryption under HTTPS and most other secure protocols. What a certificate is for, and what fails visibly when the certificate does not match the hostname. certificate lifecycle for webhooks and internal services
AuthentikUnified Single Sign-OnOne login across many applications. On Frank, Authentik holds the session and Traefik asks it before forwarding a request.OpenID ConnectAn identity layer on top of OAuth 2.0: it adds a token saying *who* the user is, not merely what the client may do. Frank's single sign-on speaks it, with Authentik as the provider. for ArgoCD, Grafana, Infisical; forward-auth proxy for 18 routes incl. Longhorn, Hubble, Tekton Dashboard (192.168.55.211)
vClusterVirtual K8s clusters inside Frank — disposable sandboxes with own API server, resource quotas, network policies
PaperclipAI agent orchestrator — virtual companies with org charts, budgets, and delegation chains; complements Sympozium (192.168.55.212)
ComfyUIDiffusion model serving — video (LTX-2.3), image (SDXL), audio (Stable Audio), node-based workflow editor (192.168.55.213)
GPU SwitcherCustom Go dashboard for GPU time-sharing — one-click switching between Ollama and ComfyUI (192.168.55.214)
Hop (Hetzner Edge)Public-facing single-node Talos cluster — Headscale mesh, Caddy reverse proxy, blog hosting, split-DNS
Headscale + TailscaleWireGuard mesh networking — remote homelab access from any device, MagicDNS for split-DNS
CaddyAutomatic TLS (Cloudflare DNS challenge), public/mesh routing, path rewriting
Secure Agent PodHardened non-root coding agent workstation — Cilium egress, dropped capabilities, VibeKanban orchestration, SSH (192.168.55.215) + UI (192.168.55.218)
Argo RolloutsProgressive delivery — canary (Cilium traffic splitting + VictoriaMetrics analysis) and blue-green (preview + atomic cutover)
n8nPer-user workflow automation — 400+ integrations, visual node editor, webhook triggers, Authentik forward-auth (192.168.55.216)
Blackbox Exporter + PushgatewayFeature-level health monitoring — HTTP endpoint probes, cron heartbeat ingestion, Grafana alerting to Telegram
Health BridgeGrafana alert → GitHub Project lifecycle state bridge — automatic degraded/dead/healthy transitions, issue comments, bug issue creation
Traefik (in-cluster)In-cluster ingress controller, wildcard TLS (*.cluster.derio.net), Automatic Certificate Management EnvironmentThe protocol Let's Encrypt uses to issue certificates to a server that can prove it controls a domain. Frank's edge proves it over DNS rather than HTTP, which is what lets it get certificates for hosts the internet cannot reach. via Cloudflare DNS-01, Authentik forward-auth (192.168.55.220)
VibeKanbanThe task board Frank dispatches agent work through — the queue between a written plan's phases and the agents that execute them. Remote (self-hosted)Self-hosted VibeKanban kanban API — PostgreSQL 16, ElectricSQL real-time sync, Rust/Axum server (vk.cluster.derio.net). Local JSON Web TokenA signed, self-describing token carrying claims — who you are, what you may do, when it expires. Readable by anyone holding it, so the expiry and signature are the only things protecting it. auth behind an IP allowlist, no forward-auth
VK RelayWebSocket relay sidecar tunneling browser API calls to local VK agent server via yamux multiplexing, Simple Password-Authenticated Key ExchangeA protocol that turns a short shared code into a strong mutual key without exposing the code to eavesdroppers. The enrolment codes are single-use — "please sign in again" usually means it was already spent. pairing, Ed25519 request signing
gethomepage.devCluster dashboard at master.cluster.derio.net — service catalog with HTTP health indicators, custom bookmarks
GiteaSelf-hosted git forge with GitHub pull-mirror, Authentik OIDC SSO (192.168.55.209)
TektonK8s-native CI/CD pipelines — webhook-driven clone, test, build, sign, report status on pc-1
ZotOpen Container InitiativeThe body behind the standard image and runtime formats. "OCI registry" means any registry speaking that standard, not a specific vendor's. container/artifact registry with cert-manager TLS and cosign image signing (192.168.55.210)
agent-imagesShared base image + per-pod children repo — agent-base toolchain + secure-agent-kali / vk-local children, matrix CI, cross-repo repository_dispatch, lockstep bumper PR
Ruflo (claude-flow + ruvocal)Swarm-style AI orchestrator — hybrid pod (ruvocal Server-Side RenderingBuilding the HTML on the server rather than in the browser. It means the page load can reach databases and APIs, so a "simple" health check on `/` may exercise the entire stack. + agent-shell-base sidecar), LiteLLM-only egress, SSH+Mosh shell on 192.168.55.222, web UI at ruflo.cluster.derio.net
The Frank PapersThird blog series — research-grade landscape reviews framed as decisions; dossier gate (validate-dossier.py + pre-commit hook), Mermaid Frank theme, five papers/ shortcodes, render-time cross-series backlinks. Prologue published 2026-05-18: Why Run Your Own Cluster in 2026?
GoatCounterCookieless blog analytics — public beacon via Hop’s Caddy at counter.derio.net, mesh-only admin at counter.cluster.derio.net with Authentik forward-auth (192.168.55.224)
CrowdSec + caddy-crowdsec-bouncerEdge HTTP security — agent tails Caddy logs on Hop, Caddy bouncer enforces decisions locally without round-tripping to Frank
Falco (modern_ebpf) + FalcosidekickContainer runtime security on Talos — Loki output to VictoriaLogs (Loki push protocol) + direct Telegram for priority:critical
alert-agentAutonomous claude agent on multi-agent-shell — daily blog digest, Grafana-alert triage, traffic-surge detection, inbound Telegram Q&A. HTTP-only, no kube credential; deterministic facts from a frank-facts CLI. Replaced the FastAPI ai-alert-helper on 2026-06-16
AWXAnsible automation controller — the imperative arm reaching non-Talos home-lab hosts over SSH; operator + AWX Custom ResourceAn object of a type Kubernetes did not ship with, added by a CRD. Frank's ArgoCD Applications, Rollouts and Tekton Pipelines are all CRs. (two-layer reconcile), native OIDC SSO via Authentik, Gitea-backed Job Templates
hermes (Nous Research)Terminal-native agent CLI in a dedicated agent-shell-base pod on gpu-1 — Bring Your Own KeyA tool that expects you to supply an API key for a model provider rather than brokering access itself. On Frank's agent shells these need a shim to re-export the key into login shells, because sshd scrubs container env. to LiteLLM (provider pinned via config.yaml mapping), profile.d shim defeating the sshd env-scrub, SSH+Mosh on 192.168.55.226
metrics-serverAggregated resource Metrics API (metrics.k8s.io) on Talos — restores kubectl top nodes/pods and unblocks CPU/memory HorizontalPodAutoscalerThe controller that adds and removes pod replicas based on a metric. It needs a metrics API to be serving, which is a separate component from the monitoring stack.; --kubelet-insecure-tls for self-signed kubelet certs. Custom/external metrics deferred to a VM-backed prometheus-adapter

Cluster State

Four zones, lettered A to D. Zone A is management and has no row here on purpose: it lives outside the cluster, so it has no node to appear as. The other three are the cluster.

NodeZoneRoleHardware
mini-1/2/3B — Core HAControl-plane + WorkerIntel Ultra 5, 64GB RAM, 1TB NVMe, Arc iGPU
gpu-1C — AI ComputeWorkeri9, 128GB RAM, RTX 5070 Ti (16GB GDDR7), 2x4TB SSD
pc-1D — EdgeWorkerLegacy desktop, 64GB SSD + 3x HDD
raspi-1/2D — EdgeWorkerRaspberry Pi 4, 32GB SD

Verify this page against a live cluster

Everything in the Technology → Capability Map arrives as an ArgoCD Application, so the table is checkable rather than a claim you have to take on trust. The kubectl lines below want a kubeconfig for a cluster; the grep lines want a clone of derio-net/frank and run from its root.

Every number below was captured on 2026-07-29 and will have moved since. The command is the durable part; the digits are a sample so you can tell whether you typed it right. Start with the count:

$ kubectl -n argocd get applications --no-headers | wc -l
      69

Sixty-eight of those are templated by the App-of-Apps. The sixty-ninth is root itself, applied by hand once at bootstrap, because at that moment nothing exists yet to apply it:

$ grep -l 'kind: Application' apps/root/templates/*.yaml | wc -l
      68

That arithmetic is the whole GitOps claim in one line. When the two numbers stop agreeing, something on the cluster was made outside git.

Existing and converged are different questions, so ask the second one separately:

$ kubectl -n argocd get applications \
    -o jsonpath='{range .items[*]}{.status.sync.status}{" "}{.status.health.status}{"\n"}{end}' \
  | sort | uniq -c | sort -rn
  62 Synced Healthy
   5 OutOfSync Healthy
   1 Synced Suspended
   1 OutOfSync Missing

Sixty-two green out of sixty-nine, on an ordinary afternoon. Suspended is a canary parked at a manual promotion gate — Argo Rollouts doing its job, not a fault. OutOfSync is live state disagreeing with git. Neither is an emergency, and a cluster reporting all green all the time is usually one nobody is asking hard questions of.

The roadmap at the top is numbered by published post. The layer codes that plan filenames and commit messages use are a separate registry:

$ grep -c '^  - code:' docs/layers.yaml
22

Twenty-one numbered capability layers, plus repo for meta-work that is not a cluster capability at all. The two sequences match through Layer 17 and diverge after it, because layers stopped shipping in the order they were planned. If you are looking for the post that covers a layer, follow the roadmap; if you are looking for the plan that built it, follow the code.

Missteps

Three forks where the obvious choice was the wrong one.

The forkWhy the obvious branch was wrongWhat Frank does nowEvidence
Maintain the index by hand, or derive it from the pagesHand-maintained indexes drift silently — nothing fails when you forget, and reordering means editing every entryLayer registry in docs/layers.yaml; {{< roadmap >}} and {{< series-index >}} derive their cards from page frontmatterd7678b9e, cfb7dd1e
One series or twoBuild narrative and runbook have different readers and different half-lives. A build post is a dated story and should age; a runbook has to stay trueSplit into building/ and operating/, cross-linked at render time7f5ff73f, fc274975
relref or a plain path for cross-post linksrelref validates targets at build time, but a missing /docs/ prefix is not a warning — it is REF_NOT_FOUND and a dead build-pages jobPrefix every relref with the full section path; escape any shortcode you are only quoting as {{<>}}2840cce7