My NAS was doing a server's job, so I bought it a server
My ZimaBoard started as a NAS. By October it was also running Immich and Paperless, Uptime Kuma, Grafana and Prometheus, a Homepage dashboard, two small metrics bridges, and a container full of AI coding agents. All of that on 7.5 GiB of RAM, with Grafana alone needing a whole gigabyte of it.
The board was coping on average. What worried me was the agents’ container. It wasn’t the steady use; it was what happens when an agent runs npm install or a test suite and that spike lands on the same memory Immich and Paperless are using. So on 16 October a GMKtec K10 went onto the desk beside it, and the board went back to being mostly a NAS.
The agents were the real reason
Memory was the pressure. The agents were why the answer had to be a separate machine.
They run code, install packages and hold sudo. That’s what makes them useful, and it’s also why I didn’t want them living on the machine that serves my data. In their container on the ZimaBoard they had a filesystem of their own, but they shared the kernel, the memory and the disks with my photos.
I wanted the agents off the NAS, and I wanted their operating system separate from the services moving onto the new host. On the new machine that means separate virtual machines with their own snapshots. If an agent breaks its own VM, I roll the VM back, and a broken agent VM no longer means rebuilding the machine that serves my photos. That isn’t the same as the agents being unable to reach the photos: they’re on the same network, and network access and credentials still need their own boundaries, which I haven’t tested.
The first idea was a smaller box
My first plan was a ZimaBlade: cheap, silent, fanless, made by the same people as the board, and dedicated to the agents. The weak spot is its processor, a quad-core Celeron J3455, an Apollo Lake chip from 2016. herdr, which keeps my agents’ sessions running when my desktop sleeps, is light, and the agents themselves mostly wait on the network. What they run isn’t light: package installs, test suites, builds. I wanted more headroom for those than an older low-power Celeron offered.
The other options were a newer N150 mini PC, or a bigger machine running Proxmox, with the agents in a virtual machine I could resize later. I went for the bigger machine. The K10 was QAR 1,500 on AliExpress as a barebones unit, with no memory or storage. The 16 GB of DDR5 and the 512 GB NVMe came out of my laptop when I upgraded it last year, so the rest of the machine was already in a drawer.
The same conversation settled the operating system, and that held whatever the hardware. ZimaOS is an appliance: a read-only root, with everything meant to run as a Docker app from its store. herdr works best as a native program under a normal user, with the agent tools, git, SSH keys, Python and Node all on the same PATH. Packing all that into a container on ZimaOS is the setup I already had, just moved to new hardware. So the agents’ VM is plain Ubuntu Server, with herdr running natively as a service that starts at boot.
The machine
| Model | GMKtec NucBox K10 |
| CPU | Intel Core i9-13900HK, 14 cores, 20 threads |
| Memory | 16 GB DDR5, from my laptop’s upgrade |
| Storage | Lexar NM620 512 GB NVMe, from the same laptop |
| Cost | QAR 1,500, barebones, from AliExpress |
| OS | Proxmox VE 9.2 on Debian 13, ZFS on the NVMe, ARC capped at 2 GB |
It runs two VMs:
- Lighthouse is the agents’ machine: herdr, the Hermes agent I run there, and the coding agents’ command-line tools.
- Coastguard is for the services leaving the ZimaBoard. Grafana and Prometheus moved into it on 18 October, with their history.
Coastguard was installed fresh rather than cloned from Lighthouse. Installing it fresh avoided carrying the agents’ keys and state into the services VM.
What stayed on the board, and why
Moving everything wasn’t the goal. Some things belong next to the disks, or outside the new machine:
- Immich and Paperless stay. Their data is on the mirror beside them, the one I’d only just made sure my photos were really on, and moving them would mean reading libraries over the network.
- Uptime Kuma stays. It watches Shipyard, the new Proxmox host, from outside. On Shipyard it couldn’t report Shipyard’s death.
- node-exporter stays, because it reports on the machine it runs on. Prometheus on Coastguard reaches across to scrape it.
Taking the agents’ container off the board freed 520 MiB on its own.
A restore before I trusted the backups
The VMs back up nightly to a share on the ZimaBoard’s mirror. Before the first scheduled run, I backed up Lighthouse by hand and restored it. Its 100 GiB disk became a 2.78 GB archive in 28 seconds. I restored it as a second VM in 27 seconds, with its network link set down first so it couldn’t take the real Lighthouse’s address, booted it, checked it came up as the same Ubuntu with the same disk, and destroyed it. That checked the guest comes back, not every application inside it or anything it depends on outside.
The first scheduled backup ran at 02:00 on 18 October: 6.7 GB for Lighthouse and 3.5 GB for Coastguard, both OK.
The honest downsides
I’m working within 16 GB. With Lighthouse at its first 10 GB, the host sat at about 82 percent memory. I shrank Lighthouse to 6 GiB to make room for Coastguard’s 4, and after the reboot the host used 6.3 of 15.4 GiB instead of 12.6. It works, and I’m keeping it to two VMs until I upgrade to 32 GB.
ZFS on one disk is not a mirror. Proxmox’s installer calls a single-disk pool RAID0, which on one disk means no redundancy at all. The protection is the nightly backup to the board’s mirror, not the pool itself.
The agents need supervising, VM or not. An agent did the Coastguard build, with my approval required before every change on the ZimaBoard, one service at a time. Even so, a railway-bridge container was created on Coastguard before that service’s turn came. I stopped it and left the real one on the board. A separate VM limits what an agent can damage, but it doesn’t make the agent follow the order.
When a second machine makes sense
If a NAS only stores files and serves a couple of apps, it doesn’t need a server beside it. Once it’s also running things that change themselves, like agents with sudo or anything you’d want to roll back, those belong somewhere a rollback is one click, and where breaking them doesn’t mean rebuilding the machine that holds the disks you care about.
The test I’d apply: if this thing went wrong at its worst, what else on the same machine would it take with it?
