zsmith.io

Zach Smith — software & infrastructure


I build the software and run the machines it lives on.

Discipline
Full-stack + infrastructure
Site
Home rack, one hypervisor
Fleet
17 guests, 16 running
Stack
Debian · Node · Next.js · SQL Server · ZFS
Ingress
Cloudflare Tunnel — no forwarded ports
Method
Hand-rolled over appliance

Index

The fleet

Everything below runs on one Proxmox host in my house. Each line is a container or VM I provisioned, hardened, and still maintain. The marked ones are software I wrote myself.

9001meshcentralRemote management for the Windows machines
9002tunnelCloudflare connector — the only way in from the internet
9003nextermBrowser SSH gateway
9004hyperadminThe controller. Every change to the fleet starts here
9005pbsProxmox Backup Server — nightly, two datastores, separate spindle
9006grimoire-devNext.js + SQL Server 2025 — development
9007termixServer management platform, running my patched build
9008tailscaleSubnet router for off-network access
9010notifyNotification relay — apps hold scoped tokens, never webhooks
9011grimoireProduction build — parked, with the edge redirecting to dev
9013android-emuHeadless emulator with KVM passthrough, boots on demand
9014infisicalSecrets. Every host authenticates with its own scoped identity
9016bardMusic player and downloader I wrote from scratch
9018dashboardFleet control plane + uptime monitoring
9019nasZFS pool, Samba, Cockpit — built lean instead of installing TrueNAS
9020work-hyperadminSegregated controller for a separate fleet. No homelab reach
9021mediaJellyfin and friends, behind a VPN gateway

Public services front by Cloudflare Access · backups nightly · a host-side watchdog resets anything that wedges

Software

Things I built

9016 — in production since June 2026

Bard

A music player and downloader that thinks in songs.

The usual self-hosted music stack — Navidrome for playback, Lidarr for acquisition — is built around albums. I wanted individual songs, so I replaced the whole stack with one application.

Bard keeps a per-song wanted list. A worker searches Soulseek through a local slskd instance, ranks candidates by title match, format, duration and peer health, and falls back to YouTube when Soulseek comes up empty. Files get retagged on import from the metadata I asked for, not the metadata the peer happened to ship. Failures retry on a backoff ladder rather than disappearing.

It scrobbles to ListenBrainz and imports the weekly playlists ListenBrainz generates, queueing anything missing from the library. It speaks OpenSubsonic, so ordinary phone clients work against it. There's a podcast subsystem that streams episodes through a proxy, keeping private feed tokens server-side. The frontend uses no framework.

9006 / 9011 — dev and prod

Grimoire

One app for the things I track about myself.

Four modules behind a single sign-in. Golem plans training: it holds exercises, equipment and locations, tracks weekly volume against per-muscle landmarks, and generates sessions. Rune is spaced-repetition flashcards. Forage logs food against nutrient targets. Quest turns tasks and habits into a balance you spend on rewards.

It's split across two VMs — a development box on a feature branch and production on main, each with its own SQL Server. Production is parked right now and a redirect rule at the Cloudflare edge sends its traffic to dev, which costs nothing to run and means the public URL keeps working while the prod VM's memory goes to something I'm actually using. The whole surface is also exposed over MCP, so I can drive it conversationally instead of through the UI.

9018 — the control plane

Homelab dashboard

One pane for seventeen machines.

It reads fleet stats from the Proxmox API with a read-only token, host temperatures straight off hwmon and smartctl, and up/down state from Uptime Kuma. No agent runs on any monitored host.

The centerpiece is a live terminal per machine. Each tab is a named tmux session on the target box, reached through a forwarding-only SSH key, so a session survives a browser refresh and mirrors across devices — open it on a laptop, pick it up on a phone. Because that terminal is remote code execution behind a URL, it sits behind four layers: bound to localhost, reachable only through a key that can forward and nothing else, a token-gated same-origin proxy, and Cloudflare Access on top.

Open source — fork

Termix-shared

Upstream wouldn't share a session. So I made it.

Termix gives every browser tab its own SSH session, and hands the session over when a second client attaches — open the same host on your phone and the desktop drops. I wanted the opposite: one server-side PTY that any number of devices mirror live.

The fix is small and surgical. The session manager's single attached socket becomes a set; output broadcasts to all of them; the idle timer only arms when the last client leaves. Sharing keys on the session rather than the host, so two deliberate tabs to the same machine stay independent. It ships as a digest-pinned derived image with a test harness that runs against the deployed bytes, and the change is up as a fork of upstream.

The whole rack

The infrastructure

The part that has to work when I'm not looking.

Nothing is port-forwarded. Public services reach the internet through a Cloudflare tunnel and sit behind Access, and the few that machines need to reach get their own bypass with real authentication rather than an open hole. Secrets live in Infisical: every host authenticates as its own identity, scoped to the one project it needs — the work controller can read work secrets and gets a 403 on everything else, and I verified that rather than assuming it.

Backups run nightly to a spindle separate from the one the guests live on, with a slim SSD mirror alongside. A watchdog on the hypervisor watches for wedged VMs, resets them, rate-limits itself so it can't loop, and emails when it gives up. Certificates issue over DNS-01, so LAN-only boxes hold real certificates without ever being publicly reachable.

The honest part: the backups are still on one host. Until they're off it, they aren't really backups.

Contact

Let's talk

If you want to know how any of this is wired, ask. I'll show you the config.

Zach Smith · zsmith.io Set in Kirsty & JetBrains Mono