Layered Backup for a Kubernetes Homelab: snapper, btrbk, and a Raspberry Pi

Running Kubernetes on a single VPS is convenient — but it concentrates risk. Every application, every PVC, every bit of state lives on one machine. If that machine disappears, so does everything else. Backup is not optional here; it’s the difference between a recoverable incident and a weekend rebuild.

This post explains the backup strategy I settled on for my homelab and why the layers are the way they are. The full technical reference — including step-by-step restore commands — is in the homelab documentation.

[Read More]

One Month of MicroShift: A Homelab Retrospective

One month in. The migration from Gentoo + Docker to Fedora Server 43 + MicroShift is complete and everything is running in production: mail stack, Nextcloud, Vaultwarden, Paperless, Collabora Online, monitoring, and this website — all on a single VPS, orchestrated by Kubernetes, managed by GitOps. So far, so good.

But let me be honest about the complexity. The full documentation runs to eight major sections covering base system, storage, firewall, WireGuard, MicroShift, GitOps, TLS, and eight services with their operational scripts. Behind that documentation are 368 commits across two repositories in four weeks — 232 in the GitOps manifests repo alone, 136 in the runbook. That’s not a “deploy and forget” setup. Every one of those commits represents something that had to be figured out, fixed, or explicitly decided.

[Read More]

Running a Self-Hosted Cloud on MicroShift

My home server runs a full self-hosted stack on a single VPS: Nextcloud, Vaultwarden, Paperless-NGX, a complete mail stack (Postfix + Dovecot + Rspamd + ClamAV), Collabora Online, and monitoring via Grafana Cloud — all on MicroShift, managed by Flux CD, behind a WireGuard VPN.

The whole thing runs on Btrfs with hourly snapshots sent to a Raspberry Pi. A GitHub Action creates a snapshot before every GitOps push. grub-btrfs registers every snapshot in the GRUB menu. If something breaks, rolling back takes thirty seconds.

[Read More]