Linking the Swarm: Hub, Herdr, and an Ornith That Routes (Not Works)
Tailscale wasn't enough — I wired a private control plane, CLI dispatch, dual-GPU Ollama, and an orchestrator that picks the right worker.
- tailscale
- hermes
- herdr
- ollama
- homelab
- agents
Tailscale connects boxes — not workflows
I run agents across a MacBook, a Ryzen desktop (gnomadgaming), an MSI laptop, a home server (gnomad-server), and a Hostinger VPS. Tailscale made SSH work. Hermes on Telegram made ops alerts work. What I still lacked was a map, persistent agent sessions, and IDE paths that didn’t require remembering five hostnames and three CLIs.
Today’s push was to fix that without spinning up another $40/month GCP dashboard.
Three layers (not one mega-bot)
| Layer | What | Tools |
|---|---|---|
| Connectivity | Reach every machine | Tailscale, SSH mesh, swarm-dispatch.sh |
| Execution | Run work headlessly | agy on MSI, Cursor CLI on Ryzen, local-offload lanes |
| Control plane | See what’s up | Swarm Hub on gnomad-server (Tailscale-only) |
Hermes stays ops — email, site health, trading on the VPS. It is not my IDE and not my coding chat.
Herdr is not a chatbot either. It’s a terminal multiplexer for agent sessions — tmux with a sidebar that shows idle, working, or blocked. I start a long agy job on MSI, close the Mac, and reattach later with ssh msi herdr attach.
Swarm Hub — zero-cost control plane
I shut down the old GCP fleet-monitor stack (always-on Cloud Run was the cost leak). The replacement is a static hub on gnomad-server:
https://gnomad-server.tail9fac0c.ts.net:8080
Panels: fleet health, SSH targets, Hermes fleet map, Ollama endpoint, Jellyfin/Kun links. Status JSON aggregates from each node every few minutes.
Gotcha: MagicDNS must be on (tailscale set --accept-dns=true) or the hostname won’t resolve in the browser. I hit that twice today — Linux and Mac.
Mac SSH: one line was breaking everything
My Mac ~/.ssh/config had ProxyCommand tailscale nc for gnomadgaming. Non-interactive SSH couldn’t find tailscale in PATH — connections failed with opaque errors. Removing that line and using Tailscale IPs directly fixed Remote SSH to the Ryzen.
Ornith as orchestrator (not worker)
I wanted Ornith — DeepReinforce’s agentic coding model — but not as the thing that writes all my code. I want it as a router:
Your task → Ornith (or qwen 7b + router prompt) → JSON route → worker runs
Workers: fast | copy | code | reason | image | msi | cloud | status
GPU split on the Ryzen (24/7 now):
| GPU | Port | Role |
|---|---|---|
| RTX 4060 | Ollama :11434 | Router + qwen 7b (warm) |
| RTX 5060 Ti | Ollama :11435 | deepseek-r1, 14b, coder |
| 5060 Ti | image-gen.py | SDXL |
| 4060 | image-gen.py | FLUX (unload small Ollama first) |
CLI:
python3 scripts/context-stack/ornith-route.py run "generate hero image for tulsa.cloud"
Honest snag: Ornith-9B weights pulled fine, but my Ollama build doesn’t support the qwen35 architecture yet. Until I upgrade Ollama, routing uses qwen 7b with the Ornith router prompt on the 4060. Weights sit ready as ornith-9b for the day the runtime catches up.
Small homelab hygiene
The MSI was flashing a PowerShell window every minute — a Swarm status task I’d set to run too often with a visible window. Fixed: hidden task, every 5 minutes. The hub doesn’t need second-by-second telemetry.
What I’d do differently
- Stand up the hub before debugging SSH from three machines — one URL beats ten terminal tabs.
- Don’t route IDE work through Telegram. Ever.
- Treat Ornith as air traffic control, not the plane.
Next step
Wire a chat panel on the Swarm Hub that calls ornith-route.py — same routing contract, browser UI on the tailnet. Until then: swarm-dispatch from the Mac and Hermes for ops alerts on the phone.
AI-assisted architecture and implementation; human-verified on the live mesh.