Under the Hood
alpacaguy.com looks like a simple website, but behind it is a four-node Proxmox cluster: one custom-built Proxmox node and three retired desktop workstations, with five secondhand Quadro GPUs, a self-hosted AI stack, and a stack of automation. The public site is plain static HTML on Cloudflare Pages. Everything that builds it lives at home. This is the tour.
Nodes: 4
Quorate: Yes
root@cluster:~# pveversion
pve-manager/9.2 (running kernel: 7.0-pve)
The hardware
No rack, no enterprise gear. The heart of the cluster is a custom-built Proxmox node: a mid-tier performance machine, built for the job, that does the heavy lifting and hosts the NAS. Around it are three retired desktop workstations that were headed for recycling. They carry the GPUs and the lighter services.
| Node | CPU | RAM | Boot / VM storage | Extras |
|---|---|---|---|---|
| Node 1 custom build | AMD Ryzen 9 5950X, 16 cores / 32 threads | 64 GB | 500 GB NVMe (LVM-thin) | 1 × Quadro M2000 6 spinning disks (5 × 2 TB SAS, 1 × 1 TB SATA) passed through to the NAS VM |
| Node 2 workstation | Intel Core i5-8400, 6 cores | 16 GB | 240 GB SATA SSD | Light services |
| Node 3 workstation | Intel Core i5-6500, 4 cores | 32 GB | 128 GB SATA SSD | 2 × Quadro M2000 local AI language model |
| Node 4 workstation | Intel Core i5-6500, 4 cores | 16 GB | 128 GB SATA SSD | 2 × Quadro M2000 speech-to-text |
The Quadro M2000 is a 2016 Maxwell card: 4 GB of VRAM, 75 W, single slot, no power connector. They’re cheap, quiet, and still plenty for an 8-billion-parameter model or whisper.cpp with CUDA. Every GPU node runs the same NVIDIA 580-series driver through DKMS, and containers get the card through device passthrough with a matching userspace driver.
Power and network
Internet
Starlink feeds a GL.iNet GL-AX1800 router (OpenWrt-based firmware). The router handles local DNS (every service has a .lan name) and DHCP, with fixed reservations for every server and a pool kept clear of the static range. A small managed switch sits between the router’s one wired port and the desk, so the nodes get their own ports instead of sharing a hub.
Nothing exposed
There are no port forwards, and since late October there is no tunnel either. The card photo inbox, the automation webhooks and the analytics now live only on the private network, reachable over a private mesh VPN (Tailscale). The public sites are static copies on Cloudflare Pages, and a probe raises an alert if a retired public name ever answers again. Admin access is SSH keys only (passwords are disabled).
Battery backup
The wall feeds a Bluetti Elite 300 (3 kWh LiFePO4, about 2.4 kW, run in UPS mode with a surge strip ahead of it, grid input capped at 10 A, charge limited to 95%). The Bluetti feeds two APC UPSs: a Back-UPS XS 1050M under the main node, and a Back-UPS ES 650 on the third node. All four nodes, the router, and the Starlink dish sit on their battery sides; monitors and docks go on the surge-only side so they don’t eat runtime. At the cluster’s usual 600 W the Bluetti alone is good for about five hours.
If the lights stay off
apcupsd on the main node watches the XS 1050M over USB. After 90 seconds on battery it shuts the whole cluster down in order: the three workstation nodes in parallel, then the main node’s containers, the retired-laptop VM, the NAS VM, and finally itself, with the UPS told to cut power at the end. It was rehearsed with a dry-run mode. The second UPS is monitored only until we know exactly what hangs off it.
Watching the watts
A Home Assistant container reads the Bluetti through its official cloud integration (the Elite 300 has no local API): battery level, grid input and output watts. The numbers flow into Prometheus and a Grafana dashboard, and seven automations push to a phone when the grid drops, the battery runs low, or the data goes quiet.
What runs on it
Almost everything is an LXC container: lighter than a VM, with near-native speed. Only two guests are full VMs: the NAS and an old laptop (more on that below).
| Service | What it does for the site | Type | Size |
|---|---|---|---|
| WordPress | Where pages and Card Corral listings are written. Never seen by the public: it’s exported to static HTML. Also hosts the Discord bot and the card photo inbox. | LXC | 2 vCPU · 16 GB |
| n8n automation | The daily 6 am repricing, the trade inbox (reads email, summarizes it, files it), Discord intake. | LXC | 4 vCPU · 4 GB |
| Card data & price API | Our own Python service that identifies cards and pulls prices from TCGdex, PokéWallet, PokemonPriceTracker, and Cardmarket, with pacing and quotas. | LXC | 2 vCPU · 2 GB |
| Ollama 2 GPUs | A local Qwen3 8B language model for summaries, so private email never leaves the house. | LXC | 4 vCPU · 12 GB |
| whisper.cpp GPU | Speech-to-text with CUDA for meeting notes and subtitles. FastAPI front end, whisper.cpp server behind it. | LXC | 3 vCPU · 5 GB |
| TrueNAS | The storage server: SMB shares for backups and ISO images on the spinning disks. | VM | 4 vCPU · 16 GB |
| Prometheus + Grafana | Metrics and dashboards for every node: temperatures, load, GPU use, disk, NAS health, both UPSs and the Bluetti. Alert rules feed Alertmanager; critical ones push to a phone through ntfy, the rest wait for the daily HTML digest email. | LXC | 2 vCPU · 4 GB |
| Home Assistant | Reads the Bluetti power station and pushes power alerts. | LXC | 2 vCPU · 2 GB |
| ntfy | Self-hosted push notifications to the phone: alerts, power events, Proxmox fencing. | LXC | 1 vCPU · 512 MB |
| Gitea | Self-hosted Git. All the site code, plugins, and scripts are versioned here. | LXC | 2 vCPU · 1 GB |
| BookStack | The runbook wiki: how every piece works and how to fix it. | LXC | 2 vCPU · 2 GB |
| Cloud-drive mirror | Nightly rclone copy of cloud files onto the NAS. | LXC | 2 vCPU · 1 GB |
| Jellyfin | The household media server, streaming the library to TVs and phones, plus a few live channels relayed in. A small media-automation stack runs alongside it. | LXC | 8 vCPU · 4 GB |
| Honeypot | A decoy that sits on the network looking like an easy target, with fake login services that nothing legitimate ever touches. Any connection to it raises an alert, so it’s an early warning if anything on the network starts poking around. | LXC | 1 vCPU · 512 MB |
| Retired laptop (P2V) | An old laptop converted physical-to-virtual: its disk was imaged into a VM, so the machine lives on with everything intact and the hardware could be retired. | VM | 6 vCPU · 8 GB |
| CPU crypto miners | Three small containers that mine a CPU-friendly coin on idle cores, plus a wallet container. The thermal guard pauses them when anything runs hot, and they have been switched off since the UPS swap to keep the power budget sane. | LXC ×4 | 2–6 vCPU each |
The command center
The admin laptop
Everything is run from a Lenovo ThinkPad T14 (Ryzen 7 PRO 4750U, 14 GB) on two DisplayLink docks driving a 3 × 2 wall of six screens. Proxmox, Grafana, the wiki, and the site sit on the big monitors, with terminals and Claude Code on the laptop panel in the middle.
Why Omarchy
The laptop runs Omarchy, an opinionated Arch Linux setup built on the Hyprland tiling window manager. It has been one of the best decisions in this whole project:
- Everything is a keystroke: workspaces, terminals, and apps open and tile instantly, which matters when you’re juggling a dozen SSH sessions.
- Its configs are plain text files, so Claude can tweak the desktop the same way it manages the servers: monitor layouts, keybindings, even a hotkey meeting recorder that transcribes on the cluster’s GPUs.
- It came ready to use (sensible defaults, themes, a fingerprint login) instead of a weekend of setup.
How a card gets onto the site
Keeping it alive
Backups
- Every container and VM is backed up nightly at 2 am (vzdump, zstd) to the NAS.
- A snapshot is taken before any package or config change, named so it’s obvious what it was for.
Heat and health
- A thermal guard on every node pauses heavy work when CPUs or GPUs run hot.
- Grafana dashboards for temperature, disk, load, GPU use and power.
- Alert rules push the urgent things to a phone; a daily HTML digest at 7 am covers backups, updates, storage, certificates, NAS health and the UPSs.
- Valid Let’s Encrypt certificates on every Proxmox web UI.
- Idle GPUs sleep at about 5 W each thanks to the NVIDIA persistence daemon (they used to sit at 20 W).
Who runs it
One human, and an AI. Claude (in Claude Code) does most of the administration over SSH, under written rules: verify with evidence, snapshot first, never run sudo on the owner’s laptop, and document everything in the wiki. Read more on About Us.
Details are kept general on purpose: no addresses, hostnames, or anything that would help someone poke at the network. Questions from fellow homelabbers are welcome on the Discord.
