DEV Community

Cover image for 🇺🇸 How I built my Proxmox homelab by talking to Claude
Jackson Pires for Vídeos de Ti

Posted on

🇺🇸 How I built my Proxmox homelab by talking to Claude

One week, a server forgotten in a corner, and not a single line of configuration typed by hand.


I had a mini PC running Proxmox VE. In practice, it was one of those projects you start full of excitement and abandon halfway: installed on an old network, with a 4 TB NVMe full of experiment volumes I no longer remembered, a 1.4 TB USB drive holding an abandoned Bitcoin VM, and a Windows VM I used now and then without really knowing how it was set up.

This time I tried something different. Instead of spending weekends reading forums, mounting disks and editing config files, I decided to do everything by talking to Claude Code. I described what I wanted in plain Portuguese, and it did the rest over SSH: it inspected, planned, executed, tested and documented.

This post is the story of how that went.


Chapter 1: first, understand the house

The first thing Claude did was not change anything. It looked. It logged into the server over SSH and took a full inventory: hardware, Proxmox version, disks, network, VMs and containers. And it stored everything in a place that became the backbone of the project: a knowledge bundle in markdown using the OKF (Open Knowledge Format), one file per topic, versioned alongside everything else. To manage these documents we used the OKF gem, a gem that helps you create, validate and maintain OKF documents. I recommend it to anyone who wants documentation that humans and AI agents read from the same source.

Right away it found six problems I didn't even know I had:

  • The server couldn't resolve names. DNS still pointed to the old network's router (10.0.0.1), which is why apt update hung.
  • /etc/hosts claimed the server had an IP address that no longer existed.
  • The Pi-hole container had a gateway outside its subnet.
  • Proxmox's enterprise repositories were enabled without a subscription.
  • And ~3.6 TB of disk sat outside Proxmox, in orphaned volumes.

In one afternoon, DNS and /etc/hosts were fixed, the repositories were switched to the free ones and the system was upgraded (182 packages and a reboot). Every fix was verified and recorded in the bundle, with a dated log.

What struck me: Claude doesn't guess. Before wiping the NVMe, it showed me what was inside each volume (old Docker and Transmission containers, an entire Umbrel VM) and waited for me to say it could all go.

Chapter 2: the disks

With my approval, the 4 TB Kingston NVMe was wiped and turned into a 3.57 TB lvmthin storage called vmdata. All VMs and containers were migrated to it.

The Windows VM put up a fight. After the migration its disk ended up 100% allocated, because discard wasn't enabled. Claude turned it on and tried the normal route (a Windows retrim), which didn't work with that version of the VirtIO driver. Instead of giving up, it did an offline round-trip copy through the other storage, and the disk dropped from 100% to 28.65% usage.

I just watched.

Chapter 3: an Ubuntu VM I could actually use

I had created an Ubuntu 26.04 VM and asked for two things: a static IP and remote desktop access.

The static IP seemed trivial. Claude configured NetworkManager and, while testing, noticed the VM now had two IPs: the installer's config file was still keeping DHCP on underneath. Once fixed, the VM answered only on 192.168.0.103. I picked the 103 ending because that's its ID in Proxmox, which makes it easy to remember.

RDP turned into a little saga:

  1. Claude enabled GNOME's Remote Login. From my Mac, Microsoft's Windows App got stuck on "Securing connection".
  2. Reading the server logs, it found that authentication worked, but during the hand-off to the session, Microsoft's Mac client re-sent the wrong credentials. It's a known bug.
  3. We switched to FreeRDP, which also failed, this time before even leaving the Mac. macOS blocks non-Apple binaries from reaching the local network, and they don't even show up in the permissions list.
  4. The fix was an SSH tunnel: FreeRDP connects to localhost, and the tunnel carries it to the VM.
  5. So I wouldn't have to remember commands, Claude wrote an rdp-ubuntu script (opens the tunnel, pulls the password from the macOS Keychain, connects, and tears everything down on exit) and then an app with an icon in the Applications folder.

Today I click an icon and I'm in Ubuntu.

Chapter 4: the USB drive becomes a torrent server

I asked for the 1.4 TB USB drive to be used only for torrent downloads, with a web interface. The first thing Claude noticed: the drive was plugged into a USB 2.0 port. I moved it, Claude measured the read speed (117 MB/s at the start of the disk), and we moved on.

Here something came up that I wouldn't have planned for on my own: the drive can be unplugged. So the whole design was built around that:

  • The drive is passed through to the VM as a USB device, not as a disk, so the VM boots even without it.
  • qBittorrent only runs while the drive is mounted. If the drive goes away, it stops on its own, and nothing is ever written to the system disk.
  • An ejetar-torrents ("eject torrents") command stops everything safely before you pull the cable.
  • When the drive is plugged back in, it mounts and qBittorrent comes back by itself.

We tested all of it: a real download with a verified checksum, a simulated unplug, a replug, and booting with and without the drive.

Chapter 5: getting to the files from anywhere

I wanted to upload, download and delete files from the web, and also see the folders directly in the Finder.

For the web, the plan was File Browser. Claude installed it and, when the service started, read the warning the program itself printed: the project had been archived a month earlier, with unpatched security flaws. One of them deleted folders when an upload failed. Claude stopped, explained the risk and offered me three actively maintained alternatives. I chose copyparty, which was validated with a 6 GB upload and download, checksum verified, resume-after-interruption and all.

For the Finder, in came Samba. The server shows up on its own in the Mac's sidebar. And then came the tensest moment of the week: in the middle of the 6 GB copy test, the entire server dropped off the network. I had to power-cycle it with the button.

When it came back, Claude read the logs and found the cause within minutes: the mini PC's Intel I219 network card had hung (Detected Hardware Unit Hang), a known bug in that chip under heavy traffic. The fix was to turn off two of the card's offloads (TSO/GSO). For good measure, it set up a watchdog that resets the card automatically if it ever hangs again. The same 6 GB test then passed without a single hang.

The same day it found another subtle problem: ejetar-torrents sometimes re-mounted the drive on its own right after unmounting it. The cause was an interaction between systemd and fstab, triggered by a timer that runs every 10 minutes. One option (noauto) fixed it for good.

Chapter 6: one dashboard to see it all

To wrap up the server side, I asked for a dashboard. Claude installed Glance at http://192.168.0.103, no port needed:

  • icons and status for every service;
  • disk usage, CPU and RAM for the VM;
  • torrent speeds;
  • a summary of the Proxmox host, with CPU, RAM and the state of each VM, read through a read-only token. It tested that the token can't shut anything down.

In the test with the drive ejected, the dashboard showed "13 GB of 128 GB" for the USB drive. It was reading the empty folder on the system disk. Claude didn't accept the wrong number: it wrote a small collector that reports the real state, and now the dashboard shows "● HD desconectado" ("drive disconnected") when that's the case.

The method behind the magic

Looking back, what made this work wasn't Claude "knowing Linux". It was the way of working:

  • Plan before executing. Every larger task started with a plan saved in plan/yyyy-mm-dd.md, with decisions, reasons and a checkbox for each phase. I approved it and followed progress there.
  • Test everything, for real. Nothing was called done without a test: checksums on 6 GB files, simulated unplugs, reboots with and without the drive.
  • Documentation as code. The knowledge bundle (configuration/), in OKF format, is updated with every change and validated automatically with the OKF gem, which checks the documents' structure and flags broken links and stale indexes. Any future session starts out knowing what has already been done.
  • Ask before anything irreversible. Wiping a disk, formatting the drive, deleting files: always with the exact list of what would be affected and my confirmation. When a request of mine was ambiguous and matched more than one thing, it asked which one before deleting.
  • Secrets stay out of the chat. Passwords were generated and stored in the Mac's Keychain, and handed to services without ever appearing on screen.

What went wrong (and why it gave me more confidence)

It wasn't all perfect, and I think this is the most important part of the post:

  • The server outage was caused by one of Claude's own tests. The difference is that it diagnosed, fixed and hardened against the problem right after.
  • It got dates wrong in the documentation once and corrected them when it noticed.
  • A hasty conclusion: the first time the drive re-mounted itself right after being ejected, Claude put it down to a side effect of the previous test, because it couldn't reproduce it. When it happened again, it went back to it on its own, admitted the explanation had been wrong, cross-checked the timestamps against the logs and found the real cause (the 10-minute timer and fstab). Its first method for simulating a drive unplug also didn't actually work; it noticed and switched to one that did.
  • Early on, I pasted a password into the chat. Claude used it, but recommended I change it. I did, and since then everything goes through the Keychain.

An assistant that never makes mistakes is one I'd have no way to evaluate. One that finds its own mistakes, explains them and documents how to avoid them is one I'll let touch my server.

By the numbers

  • 1 server cleaned up: DNS, repositories, upgrade, and 4 TB of NVMe reclaimed.
  • 6 new services on the Ubuntu VM (RDP, qBittorrent, copyparty, Samba, Glance and the dashboard's status collector), plus the network-card watchdog on the host.
  • 3 hardware and software problems I didn't know about: the USB 2.0 port, the network card that hung, and the drive's phantom re-mount.
  • 1 documentation bundle, 4 execution plans, and zero config files edited by me.

Conclusion

I didn't stop understanding my server. Quite the opposite: today it's better documented than anything I've ever set up on my own. The difference is that I spent the week deciding what I wanted, not fighting over how to do it.

If you have a homelab gathering dust for lack of time, my advice is: open a terminal, connect Claude to your server, and start by asking it to look and document before changing anything. The rest comes from the conversation.

Top comments (0)