
I have been running things at home for longer than I want to count, back when the word for it was “a Linux box under the desk”. These days the box under the desk is a rack, the desk is somewhere else, and the list of services is long enough that I forget half of it between reboots. So here it is, written down once: what I run, how, and what I stopped running.
Why I walked away
Self-hosting is only half of it. The other half is deciding who gets my data, my code and my money when I do not run the thing myself. Three exits, one itch: I want to own less of someone else’s roadmap.
- Email. Proton Mail, with the Bridge running locally for my terminal clients. We moved all of our mail from Gmail to Proton because Proton respects privacy. Running a mail server in 2026 is a hobby I have already declined, so this is the “pay someone you trust” option.
- Git hosting. Codeberg. We moved all of our repositories from GitHub to Codeberg. I had enough of the invasive AI push: GitHub is overcrowded, and I do not want my code ending up as training material for Copilot. Codeberg is run by a non-profit, and it is a better home for code I care about. I do not run the forge myself, I only lend it a CI runner.
- My phone. A Fairphone, which arrives today, 16 October. I would otherwise have bought another iPhone and had to replace it again in two or three years. The Fairphone is the more ethical and more sustainable choice.
The ground rules
- Everything lives in git. If a service cannot be described in a repository, it does not get to exist. The cluster is rebuilt from Ansible and Argo CD, not from my memory.
- Nothing is exposed because it was easy. Most of it is reachable only from the LAN or through Tailscale. A handful of apps are public on purpose, and I know which ones.
- The boring layer comes first. DNS, DHCP, switching and storage get more care than any app on top of them. I wrote about that in Everyone’s installing local LLMs. I bought a rack.
- If I cannot restore it, I do not run it. Config and data go to the NAS on a schedule, and Argo can recreate everything else from the repository.
The hardware
- Five ThinkCentre mini PCs running k3s: three control-plane nodes, two agents. One agent carries an NVIDIA RTX 3050 Ti and does all the GPU work.
- A QNAP TS-932PX and a TerraMaster box for storage, mounted into the cluster over NFS and CIFS.
- One more ThinkCentre, outside the cluster, that does DNS and DHCP.
- A MikroTik router, a NETGEAR 48-port switch and a MikroTik access point holding the whole thing together.
- Hyperion, a dedicated server at Hetzner: this blog, and CI runners.
NOTE
After a power cut, two nodes kept hard NFS mounts to the QNAP stuck in uninterruptible sleep, even though the NAS itself was fine. The fix was rebooting those two nodes, one at a time. I now think of NFS mounts the way I think of a houseplant: fine until you leave for a week.
The services
Alphabetical, like a proper list. Each entry ends with where it runs.
Argo CD
The reason rule 1 works. The whole cluster is an app-of-apps pointing at one directory in a repo, with self-heal and prune turned on. Forty-four applications at the time of writing. Scaling something to zero by hand is a fun way to learn that Argo will scale it right back up. k3s.
cert-manager
Let’s Encrypt certificates for everything with a name, so I stopped thinking about certificates. k3s.
Grafana and Prometheus
Metrics for the cluster, the GPU, the switch over SNMP, the DSL modem, the router and the Pi-hole. I added most of these exporters out of curiosity and keep them because the dashboards are pretty. k3s.
Home Assistant and Mosquitto
The house, such as it is. Home Assistant is always the last app to come back after a cold start, which tells you what it is waiting for. k3s.
Immich
Photos, with the machine-learning parts running on the GPU node. k3s.
Jellyfin
Media server, scheduled on the GPU node. It replaced Plex (see below). k3s.
Kavita
Books and comics reader. Pointed at a share on the NAS and left alone. k3s.
Longhorn
Replicated block storage for the cluster. Seventeen volumes, all at three replicas, all healthy at the last count. It is the part of Kubernetes that made me respect storage people. k3s.
Pi-hole
DNS and DHCP for the house, plus a wildcard so every internal name lands on the ingress. It runs outside the cluster on its own ThinkCentre. Outside the cluster.
The *arr family and Seerr
Prowlarr, Radarr, Sonarr and Lidarr, with Seerr as the front door for requests. Automation so I can stop being the automation. k3s.
Syncthing
File sync between machines, no server in the middle. The one piece of “cloud storage” I trust. k3s and desktop.
Traefik
The ingress. One virtual IP, one wildcard record, and every new app gets a hostname for free. k3s.
Uptime Kuma
Tells me when something fell over before I find out by clicking on it. k3s.
Caddy, on Hyperion
Serves this blog. Hugo builds the site every five minutes from the repository and Caddy hands out the result, with a certificate it renews on its own. Docker.
Forgejo runner, on Hyperion
I do not self-host the forge, Codeberg does that. I only lend it a runner for CI jobs. Docker.
What I tried and dropped
Nextcloud
I built it on the cluster, ran it, and removed it again, down to the volumes. Syncthing already does the one thing I wanted from it, and a second sync tool is a second thing to patch.
Plex
Replaced by Jellyfin. The app, its volumes and its backup job are gone, not just scaled to zero.
Proxmox and Docker Swarm
The old cluster. I moved to k3s because I wanted to learn Kubernetes properly, and that is the whole reason. Swarm was fine.
NPMplus
My old reverse proxy front end. It died, and I took the opportunity not to resurrect it. Traefik handles everything now.
What I leave to others, no drama
- Passwords. Bitwarden, in its EU cloud. A password manager I have to keep alive is a password manager I cannot open when I need it most.
- Comments. Disqus, loaded only if you click.
The numbers
Forty-four apps, about a hundred pods, seventeen replicated volumes, one rented server. The real cost is attention, not electricity: every service I add is a service I have to update, restore and explain to myself six months later.
That last part is why this post has a “dropped” section. The list of what I removed is the more honest half of the inventory.
Cover: Jean-Pierre Houël, The Storming of the Bastille (1789). Public domain, via Wikimedia Commons.