Data Center & Virtualization
The compute side of the Rocknet Lab: a three-node Proxmox VE cluster, the physical and virtual fabric that ties it together, the guests it runs, and the production website it hosts. Everything here is the real system, with live telemetry pulled straight from the cluster.
Cluster Topology
How traffic and metrics actually move through the lab — the public site path, the monitoring path that feeds the live telemetry panel further down, and the isolated SDN overlay riding on top of it all. No IP addresses are shown by design; this is the shape of the system, not its addressing. Full write-ups of what each box does and how each flow works follow the diagram.
What Each Box Represents
A quick reference for the diagram above — what each piece is, and the role it plays.
Internet & Cloudflare Tunnel
The only path in from the public internet. The tunnel is opened outbound from VM 100 — the router never has an inbound rule pointed at the cluster, so there's nothing on the WAN side to scan or brute-force.
PVEServer
One of the three Dell OptiPlex 9020 nodes. Hosts the monitoring stack that watches the whole cluster and the control node that provisions it, plus a personal project: a ham radio band-conditions and DX-spot dashboard. Amateur radio's been a hobby of mine outside of work since 1995, and this node is where I get to experiment with new ways of engaging with it — building my own tools instead of just using someone else's app.
LXC 102 monitoring · LXC 104 tf-ansible · LXC 107 hamdash · LXC 111 r1 · LXC 115 routerdashPVE2
Runs the guest that matters most: the Debian VM serving this website. Its small cluster-api reads a Prometheus snapshot and republishes it here, so the telemetry panel above updates without exposing Prometheus itself. Alongside it, a Debian desktop VM doubles as a sandbox and the lab's flashing station — writing OS images from the cluster's shared ISO library to SD cards and USB drives.
VM 100 Debian (production) · VM 101 Debian2 · LXC 112 r2PVE3
Hosts the agentic dev environment used to build and maintain this cluster and site — Claude Code running in its own container — along with two of the routing lab's FRR routers.
LXC 103 claude-code · LXC 113 r3 · LXC 114 r4Physical LAN & Cluster Fabric
One TP-Link ER605 router, a 12-port patch panel, and two TL-SG105 switches carry everything: node-to-node cluster traffic (corosync), storage traffic, and the monitoring scrapes. It's also the transport the SDN overlay rides on.
Storage
Each node has its own local local-lvm thin pool for guest disks — not shared, by design. The only storage that's actually shared cluster-wide is usb-share: a 931GB USB drive physically attached to PVEServer, exported over NFS and mounted on all three nodes. It holds the cluster's ISO templates and backups — VM 100 gets full daily vzdump backups, every other guest gets nightly config-only backups.
usb-share (NFS, shared) · local-lvm (per-node)Proxmox SDN · labnet0
A VXLAN overlay layered on top of the physical LAN via Proxmox's SDN stack — one private layer-2 network stretched across all three nodes, with its own address range, no gateway or path in from outside, and no VLAN or switch port of its own. Every container has a second interface on it for private container-to-container traffic, while its primary LAN interface is left untouched. Built and torn down with Terraform. More on the SDN & Routing page.
Data Flow, Step by Step
-
Public Web Request
A browser requests this page over HTTPS. The request never touches the router directly — it's picked up by Cloudflare's edge and handed to VM 100 over a tunnel that VM 100 itself opened outbound. Nginx on that VM serves the page.
Internet → Cloudflare Tunnel → VM 100 (nginx) — inbound ports opened: none -
Live Telemetry Request
This page's JavaScript calls a small read-only API running alongside nginx on VM 100. That API is the only thing allowed to reach into the monitoring stack — nothing about Prometheus or Grafana is exposed to the browser directly.
Browser → VM 100 cluster-api (/api/cluster) -
Telemetry Read-Back
VM 100's cluster-api queries the monitoring container on PVEServer over the physical LAN and gets back the latest cluster snapshot, which it republishes to the page above every 10 seconds.
VM 100 → LXC 102 (monitoring), read-only, over the LAN -
Monitoring Scrape
The monitoring container doesn't wait to be asked — it continuously scrapes node_exporter and the Proxmox API on all three nodes over the LAN, so CPU, memory, and quorum state are always current by the time step 3 asks for them.
LXC 102 → PVEServer, PVE2, PVE3, over the LAN -
Cluster Fabric
Underneath all of the above, the three nodes stay joined by Proxmox clustering (corosync heartbeats) and the cluster's real shared storage — an NFS export mounted on all three nodes — carried over the router, patch panel, and switches, so guests can be managed or migrated between hosts as one cluster.
PVEServer ↔ PVE2 ↔ PVE3, corosync + usb-share (NFS) -
SDN Overlay
A separate, private network is layered on top of that same physical LAN — each node tunnels overlay traffic to the others as VXLAN, so containers can talk to each other on their own address space whichever node they live on. No gateway, no VLAN tag or switch port of its own, nothing reachable from outside. It's provisioned, changed, and torn down entirely with Terraform.
labnet0 · VXLAN mesh across all 3 nodes · every LXC attached · zero inbound
Live Cluster Telemetry
Metrics below are pulled straight from a Prometheus instance running on the cluster and refreshed every 10 seconds — no static screenshots. A small read-only API on this web server queries Prometheus and republishes a curated snapshot; the monitoring stack itself stays off the public internet.
That monitoring stack has grown past a single dashboard. Grafana on LXC 102 now runs three: a full Node Exporter view per host, a Proxmox-via-Prometheus dashboard covering cluster-wide CPU, memory, and storage, and a VM/LXC fleet dashboard that breaks out guest counts, vCPU and memory allocation, and per-guest CPU, memory, network, and disk usage. None of it is exposed publicly — the panel below is the slice of that data safe to hand to a browser.
What's Running on It
The cluster does double duty: some VMs exist purely to experiment and learn, others are in active production use — including the one serving this website.
| Guest | Type | Node | Role |
|---|---|---|---|
| Debian | VM 100 | PVE2 | Production web server for this site (Nginx) |
| Debian2 | VM 101 | PVE2 | Sandbox & SD/USB flashing station (Debian 13 Xfce, balenaEtcher, read-only ISO library) |
| monitoring | LXC 102 | PVEServer | Prometheus, Grafana (3 dashboards), node/pve exporters |
| claude-code | LXC 103 | PVE3 | Agentic dev environment |
| tf-ansible | LXC 104 | PVEServer | Terraform / Ansible control node |
| hamdash | LXC 107 | PVEServer | Ham radio band-conditions & DX-spot dashboard personal project |
| r1 | LXC 111 | PVEServer | FRR router — BGP / BFD / IS-IS lab (route reflector) |
| r2 | LXC 112 | PVE2 | FRR router — BGP / BFD / IS-IS lab (AS 65001 edge) |
| r3 | LXC 113 | PVE3 | FRR router — BGP / BFD / IS-IS lab (internal) |
| r4 | LXC 114 | PVE3 | FRR router — BGP / BFD / IS-IS lab (AS 65002 peer) |
| routerdash | LXC 115 | PVEServer | Live dashboard for the routing lab — routers, SDN links, event log |
One of these — hamdash — isn't production infrastructure. Ham radio is a hobby of mine outside of work, and the lab gives me a place to experiment with new ways of enjoying it — building my own tools instead of just using someone else's app — without any risk to the production guests.
Hosting This Site
This site is served directly from a VM on the Rocknet cluster — Nginx runs on that node and serves the static files you're looking at right now. A Cloudflare Tunnel connects it out to the public internet, so the site is reachable without opening a single inbound port on the router.