Homelab & Colocation Infrastructure

My "homelab" is a bit of a misnomer now — the hardware lives in a colocation cabinet with upstream BGP to a /27 of public IPv4 and a /64 of IPv6 delegated to me. It is the production backbone for Piedmont Hosting and runs everything on this page.

Physical Hardware

Dell PowerEdge R730 — Primary Hypervisor

Role: Customer VPS, game server host, CloudPanel web hosting VM, mailcow, reverse-proxy / Cloudflare Tunnel VM

  • CPU: Dual Intel Xeon E5-2650 v3 (20 cores / 40 threads @ 2.3 GHz)
  • RAM: 125 GB DDR4 ECC
  • Storage: 500 GB SSD boot, 4× 1 TB SSD in RAID 5 (~2.8 TB usable for VMs)
  • OS: Ubuntu Server 24.04 LTS with KVM/libvirt
  • Mgmt: iDRAC on VLAN 100 (out-of-band)

Custom tooling: mkvm (KVM + cloud-init provisioning), piedmont-firewall (per-VM nftables), piedmont-snapshot, piedmont-backup + nightly virtnbdbackup cron. A libvirt qemu hook applies QoS and firewall rules on VM start.

Dell PowerEdge R320 — Infrastructure Hypervisor

Role: Internal services — portal app, monitoring, docs, push notifications, Pterodactyl panel

  • CPU: Intel Xeon E5-2420 v2 (6 cores / 12 threads @ 2.2 GHz)
  • RAM: 96 GB DDR3 ECC
  • Storage: 3× 2 TB HDD RAID 5 (~4 TB primary), 2× 1 TB HDD RAID 1 (~1 TB backup target)
  • OS: Ubuntu Server 24.04 LTS with KVM/libvirt

Intentionally separated from customer workloads so an R730 reboot or migration doesn't affect the portal, monitoring, or docs.

Network Fabric

OPNsense Firewall / Router

  • Primary gateway, inter-VLAN routing, 1:1 NAT between private and public IP space
  • NDP proxy for IPv6 2607:1740:2000:9::/64 customer pool
  • Upstream BGP session for the 130.250.176.32/27 block

Juniper EX3400 Switch

  • VLAN trunking between the R730, R320, and OPNsense
  • LACP bonds to both hypervisors
  • SNMP monitored via Prometheus with per-port RX/TX, errors, and discards dashboards

VLAN Layout

  • VLAN 10 — 10.10.1.0/24: Infrastructure (portal app, monitoring, Pterodactyl, docs, ntfy)
  • VLAN 50 — 10.10.50.0/24: DMZ — customer VPS, web hosting, mail, reverse proxy. 1:1 NAT to the public /27.
  • VLAN 100 — 10.10.100.0/24: Management — iDRACs and hypervisor out-of-band
  • VPC — 10.68.X.0/24: Isolated Linux bridges on the R730 for customer private networks between their VPS instances

Public Addressing

  • IPv4: 130.250.176.32/27 (customer pool .40-.62, 22 available)
  • IPv6: 2607:1740:2000:9::/64 (customer pool ::100-::1ff)
  • NAT mapping: private octet equals public octet (10.10.50.40 ↔ 130.250.176.40)

Edge & TLS

Cloudflare Tunnel

  • All public portal domains (piedmonthosting.com, vps, game, ntfy, uptime, status) route through a cloudflared daemon on the reverse-proxy VM
  • Edge TLS terminated at Cloudflare; tunnel to origin nginx is localhost HTTP with X-Forwarded-Proto: https
  • Customer game servers and VPS connect directly — only the control plane is tunneled

Web Hosting TLS

  • CloudPanel VM handles Let's Encrypt SSL per customer domain automatically at site creation
  • Certificates auto-renew; no manual intervention

Infrastructure VMs (VLAN 10 — R320)

  • Portal app (10.10.1.3) — Next.js 14 + PostgreSQL + nginx for piedmonthosting.com
  • BookStack (10.10.1.5) — internal knowledge base for operational runbooks
  • Prometheus + Grafana (10.10.1.7) — metrics backbone, libvirt + Blackbox + SNMP + node exporters
  • Pterodactyl Panel (10.10.1.12) — game server control plane
  • Ntfy (10.10.1.16) — self-hosted push notifications for ops alerts
  • Uptime Kuma (internal) (10.10.1.17) — internal HTTP probing

Service VMs (VLAN 50 — R730)

  • Reverse Proxy (10.10.50.5 / .35) — nginx + cloudflared tunnel daemon
  • CloudPanel (10.10.50.36 / .36) — shared web hosting VM, WordPress / PHP / Node / Python / static sites
  • Mailcow (10.10.50.37 / .37) — full mail stack (Postfix, Dovecot, SOGo, DKIM, anti-spam)
  • Game Server (10.10.50.38 / .38) — Pterodactyl Wings node running customer game instances
  • Customer VPS pool (10.10.50.40-62) — 23 slots for individually provisioned KVM guests

Monitoring & Observability

Prometheus + Grafana Stack

  • libvirt exporter on the R730 for per-VM CPU, RAM, disk I/O, and network bytes
  • SNMP jobs for the Juniper EX3400, OPNsense firewall, and hypervisor iDRACs
  • Blackbox ICMP + HTTP probes for WAN gateway latency, DNS providers, and public websites
  • Node exporters on every VM for host-level metrics
  • Grafana dashboards for hypervisor health, customer VM usage, network, storage, backup status, and overall infrastructure

Uptime Kuma

  • Internal instance (10.10.1.17) for ops
  • External instance on a BisectHosting VPS (74.112.77.240) for the public status page at status.piedmonthosting.com — lives off-network so it can still alert when the cabinet is the problem

Ntfy Push Alerts

  • Self-hosted on 10.10.1.16, with an external vhost at ntfy.piedmonthosting.com
  • Fires to mobile for failed provisioning, stuck services, backup failures, and webhook errors

Automation & Tooling

R730 Scripts (/usr/local/bin)

  • mkvm — full VPS provisioning: parses specs (e.g. VR4x2x40), builds a qcow2 from a distro cloud image, generates a cloud-init NoCloud seed with SSH keys and network config, creates the domain, waits for cloud-init completion, and applies bandwidth QoS. Supports Ubuntu 22/24, Debian 12, Rocky 9, Alma 9, CentOS 9, Fedora 42, openSUSE 15.6, Arch.
  • piedmont-firewall — per-VM nftables rule generation from JSON policy files in /etc/piedmont/firewall/, applied via libvirt qemu hook on VM start
  • piedmont-snapshot — standalone full-copy VM snapshots, restore, delete
  • piedmont-backup + piedmont-backup-cron — nightly virtnbdbackup with retention policies
  • apply-bandwidth — traffic control (tc) QoS enforcement based on VM RAM tier

Portal-side Scripts

  • Stuck-service detector (marks provisioning past 1 hour as FAILED)
  • Dunning check (3-day payment reminder, 7-day auto-termination)
  • Renewal reminders (3 days before subscription renewal)
  • Metrics collector (per-VM RAM via virsh balloon stats, stored in PostgreSQL)

Docker Hub Pull-through Cache

  • Private registry on the R730 at 10.10.50.1:5000
  • Caches images for the 24-app marketplace, avoids Docker Hub rate limits

Documentation

  • BookStack at docs-internal — 7 books covering architecture, R730 tooling, application stack, provisioning, monitoring, runbooks, and REST API reference
  • Every significant change in production is reflected here before the session ends

What Runs Here