Before having a homelab with LXCs, VMs, and services running, there’s a boring but necessary first step: installing the hypervisor. In my case, Proxmox VE on a Lenovo M700 (i7-6700T, 32 GB RAM, a 128 GB SSD for the system, and a 1 TB HDD for data). Plugged into the mini PC are a Coral USB TPU for Frigate inference and a Sonoff Zigbee USB dongle for Home Assistant.
The install itself was straightforward and not much to write about — download the ISO, boot from USB, next, next, next. Where it gets interesting is everything that came after.
The community post-install script
Proxmox VE ships with the “enterprise” repository configured by default, which requires a license. If you leave it that way, you can’t run apt update without errors and you lose access to the no-subscription repo updates. There’s a community-maintained script that fixes this and applies several other reasonable tweaks:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/tools/pve/post-pve-install.sh)"
It interactively asks if you want to disable the enterprise repo, add the no-subscription repo, suppress the “you don’t have a license” nag every time you log into the GUI, and a few other things. I said yes to everything.
Installing the Coral TPU runtime
For Frigate to take advantage of the Coral USB you need to install the libedgetpu library on the host. Google distributes the packages from their own repository:
# Add the Coral repo
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" \
| tee /etc/apt/sources.list.d/coral-edgetpu.list
# Import the GPG key (modern way, no deprecated apt-key)
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg \
| gpg --dearmour -o /etc/apt/trusted.gpg.d/coral.gpg
apt update
apt install libedgetpu1-std
One important note: many guides out there use apt-key add to import the GPG key. That’s been deprecated since Debian 11 and is going away. The correct way today is to write the keyring directly to /etc/apt/trusted.gpg.d/, like I do above. I got this recipe from the Home Assistant forum thread on Frigate + Coral USB on Proxmox, one of the few places where it was properly documented.
This only installs the runtime on the host. For Frigate (which runs in an LXC) to actually use the Coral, you need to pass the USB device through to the container — but that’s a different story for another post.
The ZFS ARC eating all your RAM problem
If you install Proxmox using ZFS as the filesystem for the rootfs (which is what I did), you’ll find that the ARC — the ZFS read cache — by default can occupy up to half of your total RAM. In my case that means 16 GB out of the 32 I have. For a file server it might make sense, but for a homelab where RAM gets split between Home Assistant, Frigate, Vaultwarden, Nextcloud, and friends, it’s absurd.
The fix is to cap the ARC at something reasonable. I went with 4 GB:
# 1. Limit ARC to 4 GB in the kernel module configuration
echo "options zfs zfs_arc_max=4294967296" > /etc/modprobe.d/zfs.conf
# 2. Apply it immediately without rebooting
echo 4294967296 > /sys/module/zfs/parameters/zfs_arc_max
# 3. Regenerate initramfs so the change persists across reboots
update-initramfs -u -k all
The number 4294967296 is 4 GB in bytes (4 × 1024³). For a different value, calculate N * 1024 * 1024 * 1024.
To verify it stuck:
cat /etc/modprobe.d/zfs.conf
free -h
arc_size=$(cat /proc/spl/kstat/zfs/arcstats | grep "^size" | awk '{print $3}')
echo "Current ARC: $((arc_size/1024/1024/1024)) GB"
All three steps matter and none of them is optional: the first makes the change persist, the second applies it right now (because the first only takes effect when the module loads, and the module is already loaded), and the third makes sure the kernel reads it from the initramfs on the next boot.
Cleaning up swap
After tweaking the ARC, my system had a bunch of pages stuck in swap that no longer needed to be there. A quick trick is to disable and re-enable swap, which forces everything on disk back into RAM:
swapoff -a && swapon -a
free -h
Only do this if you have enough free RAM to absorb what’s currently in swap, obviously. Otherwise you’ll OOM-kill things.
What’s still pending
This is as far as my memory goes. My homelab also has an external HDD formatted and mounted for VM storage and backups, and the Zigbee USB dongle passed through entirely to the Home Assistant VM. I did both during the initial setup, but honestly I didn’t take notes at the time and don’t remember the exact steps. Each of those topics deserves its own post done properly — and I’ll take this chance to promise I’ll write them when I reconstruct the steps, this time documenting as I go.
Lesson I’m taking from this: document while you configure, not after. Your future self (or the next reinstall) will thank you.