Head of Hybrid Platform Services & Datacenter at Dirk Rossmann GmbH. Background in AI research, enterprise infrastructure, and platform engineering.

E-mail: web1 [at] michaelkoester [dot] de

About me →

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]

Hardening a Self-Hosted Mail Server: fail2ban, Postfix, and Dovecot

My home server runs a full mail stack — Postfix, Dovecot, Rspamd, ClamAV — on MicroShift. It’s exposed directly to the internet on ports 25 and 587. That means it gets attacked. Here’s how I protect it, what the attacks look like in the logs, and how I recently tightened the configuration after spotting a gap.

The Threat Landscape

Two distinct attack types show up regularly in the logs:

1. SASL Brute-Force — Attackers try username/password combinations via SMTP AUTH or IMAP. The pattern: multiple IPs, each trying a different username, typically in parallel waves.

[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]

Btrfs vs. OpenZFS: Why Snapshot Space Accounting Is Hard

Both Btrfs and OpenZFS are copy-on-write filesystems with native snapshots. On the surface they look similar. Under the hood, they handle one fundamental question very differently: who owns a block of data, and how do you account for it when snapshots share it?

I ran into this the hard way. Enabling Btrfs quotas on a system with hundreds of snapshots crashed my Kubernetes cluster every hour — reliably, for the same reason, until I figured out what was happening.

[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]