My homelab and why I run it
- homelab
- self-hosting
- devops
- infrastructure
I run a server at home. It handles my photos, my code, my media, and a handful of other things. This post is about what's on it and why I bother.
The philosophy first
Every service you move off someone else's cloud is a dependency you understand and control. That's the core of it.
It's not about distrust for its own sake. It's about knowing where your data lives, knowing it won't change its pricing model on you, and knowing that when something breaks you're the one who fixes it — which means you're also the one who learns something.
Running a homelab is a slow, practical education in Linux, networking, storage, and failure modes. No course teaches you to think about disk health the way a near-miss with data loss does.
What's running
Forgejo
Self-hosted Git. This is my private remote — personal projects, dotfiles, infrastructure manifests, things I'm not ready to make public or that simply don't belong on a platform I don't own.
Forgejo is a community fork of Gitea, and it's light enough to run alongside everything else without my noticing it's there. Its API is compatible enough with GitHub that most tooling just works.
Immich
My photo library. Every photo from my phone syncs here automatically via the mobile app. Immich does facial recognition, object search, map view, albums — everything I used to get from Google Photos, running on my hardware.
The machine learning features run on CPU, which is slower than a cloud GPU but fast enough for background indexing. Search for "beach 2024" and it finds the right photos. That's all I need.
This one matters to me more than the others. Photos are irreplaceable. I have two copies on-site and one off-site. The triple-redundancy is deliberate.
Jellyfin
Media server. Point it at a directory of films and shows, and it handles transcoding, metadata, and streaming to any device on the network — or outside it, through Caddy.
The transcoding is the resource-hungry part. Direct play is instant; software transcoding for an unsupported codec can saturate a core. Good enough for a home setup. Not good enough for ten concurrent streams.
Everything else
A few more containers round out the setup:
- Vaultwarden — self-hosted Bitwarden-compatible password manager. Bitwarden's client apps connect to it without modification.
- Uptime Kuma — a dashboard that pings each service every 60 seconds and notifies me when something goes down. Simple, effective.
- Caddy — the reverse proxy in front of everything. One config file, one wildcard cert, clean subdomains for each service.
- Portainer — not strictly necessary, but useful when I want to check container state without SSH-ing in.
The tradeoffs
It's not free. There's the hardware cost, the electricity cost, and the time cost of maintenance. Updates need running, things break at inconvenient moments, and on-call is just me.
It's also not for everyone. If you don't find the troubleshooting interesting, the effort won't feel worth it. But if you're the kind of person who wants to understand what's happening beneath the services you use, it's one of the more rewarding rabbit holes I've gone down.
What I've learned
The homelab is where I've broken and fixed the most things. Misconfigured networking, forgotten cron jobs, a filesystem that filled up quietly and took down half the stack — these are the problems you only understand by living through them.
It's also where the concepts from the DevOps projects on this site stopped being abstract. Reverse proxies, container networking, TLS certificates, health checks — I use all of them here before I write about them.
The best way to understand infrastructure is to own some.