pat@pve:~$ qm list

Homelab infrastructure

A small environment that forces me to think about the whole stack: virtualization, storage, Linux, networks, service exposure, monitoring, failure recovery, and the people actually using it.

architecture

What’s running

The current setup is centered on a Proxmox VE host. A Debian 13 VM carries the general server workload while Home Assistant OS stays isolated in its own VM. Bulk data lives on dedicated NAS-class hard drives rather than being mixed into the VM system disk.

Conceptual diagram of the current homelab: PLDT Fiber to home router, then Proxmox VE, Debian 13 and Home Assistant VMs, storage drives and self-hosted services.
I intentionally left public IPs, internal addresses, and administrative ports out of the diagram. A portfolio should demonstrate architecture without publishing an attack checklist.
ComputeRyzen 5 2600 · 32 GB DDR4 · Proxmox VE
General workloadDebian 13 VM · Docker · Nginx
Storage2 TB IronWolf + 4 TB WD Red

Why I moved to virtualization

Running everything directly on one Linux install works until the machine becomes both infrastructure and experiment. Moving the host role to Proxmox gave me a cleaner boundary: the hypervisor owns compute and VM lifecycle; Debian owns general services; Home Assistant gets its own appliance-style VM.

The benefit is less about “having a hypervisor” and more about reducing blast radius. I can reboot, resize, snapshot, or replace one workload without treating the entire server as one indivisible machine.

What I actually operate

The Debian VM runs the services I use day to day: reverse proxying, identity, monitoring, Git, documents, photos, media, DNS, VPN tooling, and Minecraft servers. Some workloads are boring until something goes wrong, which is exactly why they’re useful learning environments.

  • Identity: Pocket ID and OIDC-aware services.
  • Observability: Beszel plus service/system logs.
  • Media & data: Jellyfin, Navidrome, Immich, Paperless-ngx.
  • Developer tooling: Gitea, SSH, Docker Compose, Nginx.
  • Network services: AdGuard Home, WireGuard/Tailscale-style private access, IPv6-aware reverse proxying.

Problems that taught me more than setup guides

1. Storage disappeared after the Proxmox migration

Moving Debian from bare metal into a VM changed who owned the physical disks. The drives existing on the host did not mean the guest could magically see them. That forced me to reason about the boundary between hypervisor storage, VM virtual disks, and device passthrough/mount strategy.

2. IPv6 made “port forwarding” the wrong mental model

With globally routed IPv6, the service already had a globally routable address. The real control point was inbound firewall policy and the application listener, not NAT. Debugging it meant checking address assignment, router firewall behavior, DNS AAAA records, and whether Nginx was listening on IPv6.

ip -6 addr show scope global
ss -tlnp | grep :443
dig AAAA service.example.com
curl -6 -vk https://service.example.com/

3. A 404 that was really permissions

A static asset existed in the expected Nginx web root but still returned 404. The useful lesson was to stop staring at the URI and test the filesystem path as the web-server user: directory traversal permissions can make an existing file effectively nonexistent to Nginx.

How I think about changes

I prefer small, reversible changes with a way to verify each layer. For Nginx that means testing configuration before reload. For networking it means checking local listeners before blaming DNS. For storage it means understanding which layer owns the device before changing mounts.

sudo nginx -t && sudo systemctl reload nginx
systemctl status <service>
journalctl -u <service> --since today
ss -tulpn

What I’d improve next

The next meaningful upgrades are network segmentation, cleaner infrastructure-as-code for repeatable service deployment, stronger backup verification, and more deliberate alerting. I’m more interested in making the environment recoverable and understandable than endlessly adding services.

>
No matching command.