Alpacaguy hasn't officially launched yet, but trades are live. Found a bug or have a suggestion? Email [email protected] and we credit you 50 trumpets.Not launched yet, but trades are live. Bugs or ideas? Email [email protected]

For the nerds

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.

root@cluster:~# pvecm status | grep -E ‘Nodes|Quorate’
Nodes: 4
Quorate: Yes
root@cluster:~# pveversion
pve-manager/9.2 (running kernel: 7.0-pve)
4Proxmox VE nodes, one quorate cluster
46CPU threads
128 GBRAM across the cluster
5 × M2000NVIDIA Quadro GPUs, 20 GB VRAM total
~6 TiBusable NAS storage on spinning rust
24containers and VMs
0ports open to the internet
3 kWhof battery between the wall and the cluster

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.

NodeCPURAMBoot / VM storageExtras
Node 1 custom buildAMD Ryzen 9 5950X, 16 cores / 32 threads64 GB500 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 workstationIntel Core i5-8400, 6 cores16 GB240 GB SATA SSDLight services
Node 3 workstationIntel Core i5-6500, 4 cores32 GB128 GB SATA SSD2 × Quadro M2000 local AI language model
Node 4 workstationIntel Core i5-6500, 4 cores16 GB128 GB SATA SSD2 × 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).

ServiceWhat it does for the siteTypeSize
WordPressWhere 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.LXC2 vCPU · 16 GB
n8n automationThe daily 6 am repricing, the trade inbox (reads email, summarizes it, files it), Discord intake.LXC4 vCPU · 4 GB
Card data & price APIOur own Python service that identifies cards and pulls prices from TCGdex, PokéWallet, PokemonPriceTracker, and Cardmarket, with pacing and quotas.LXC2 vCPU · 2 GB
Ollama 2 GPUsA local Qwen3 8B language model for summaries, so private email never leaves the house.LXC4 vCPU · 12 GB
whisper.cpp GPUSpeech-to-text with CUDA for meeting notes and subtitles. FastAPI front end, whisper.cpp server behind it.LXC3 vCPU · 5 GB
TrueNASThe storage server: SMB shares for backups and ISO images on the spinning disks.VM4 vCPU · 16 GB
Prometheus + GrafanaMetrics 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.LXC2 vCPU · 4 GB
Home AssistantReads the Bluetti power station and pushes power alerts.LXC2 vCPU · 2 GB
ntfySelf-hosted push notifications to the phone: alerts, power events, Proxmox fencing.LXC1 vCPU · 512 MB
GiteaSelf-hosted Git. All the site code, plugins, and scripts are versioned here.LXC2 vCPU · 1 GB
BookStackThe runbook wiki: how every piece works and how to fix it.LXC2 vCPU · 2 GB
Cloud-drive mirrorNightly rclone copy of cloud files onto the NAS.LXC2 vCPU · 1 GB
JellyfinThe 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.LXC8 vCPU · 4 GB
HoneypotA 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.LXC1 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.VM6 vCPU · 8 GB
CPU crypto minersThree 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 ×42–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

1. PhotosCards go on the table in a grid, a photo of the fronts, flip, a photo of the backs. The Corral Upload web app on a phone sends full-resolution originals over the private network.
2. Find the cardsOpenCV finds every card on a dark table or white paper, matches fronts to backs by grid cell, and crops each one straight from the original pixels.
3. IdentifyEach front goes to Claude’s vision API (a cheaper model first, a stronger one when unsure) for name, set code, number, and language.
4. PriceThe price API averages TCGplayer and Cardmarket, drops outliers, and the site converts it: market × condition × 0.9 × 4 trumpets per dollar. Slabs are priced per grade from PriceCharting; singles under 5 trumpets are bundled into lots.
5. ReviewEverything lands as drafts with an emailed report. Approve with a Discord command.
6. PublishA Python crawler exports WordPress to static files, Wrangler deploys them to Cloudflare Pages, and the Discord bot announces the new cards.

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.

Scroll to Top