What I Self-Host and Why: 13 Apps on a Single Laptop
26 posts about infrastructure. Zero about what actually runs on it. Here is every app in the cluster, what it replaced, and whether it was worth it.
Every app on this cluster replaced a SaaS subscription, a freemium tier with limits I kept hitting, or a service whose privacy policy I finally read. Thirteen services, all self-hosted, all running on a single Dell laptop. Some of them save me money. Some of them cost me more in time than the subscription ever did. All of them are mine.
The Daily Drivers
These are the apps I use every day. If the cluster went down, these are the ones I would notice within hours.
Miniflux: RSS Reader
Miniflux is a minimalist RSS reader written in Go. I follow about 80 feeds: security advisories, infrastructure blogs, Kubernetes release notes, a few newsletters. Miniflux fetches them, presents them in a clean reading interface, and gets out of the way.
It replaced Feedly. Not because Feedly was bad, but because I wanted my reading list under my control. Feedly’s free tier limits you to 100 feeds and inserts promotional content. Miniflux has no limits, no ads, and a keyboard-driven interface that feels like it was designed by someone who actually reads RSS.
Miniflux is the only app in the cluster that uses an external database: a PostgreSQL 16 sidecar. The Go binary itself uses 128Mi. Postgres uses another 128Mi. It authenticates through Authentik via OIDC, which means I sign in once and Miniflux creates the user automatically.
Memory: 256Mi total (app + Postgres) | Replaces: Feedly ($0–99/yr)
Vaultwarden: Password Manager
A Rust reimplementation of Bitwarden’s server API. Every Bitwarden client (browser extension, mobile app, desktop app, CLI) works with it. My entire password vault syncs to this server instead of Bitwarden’s cloud.
This is the most security-critical service in the cluster. It has its own deep-dive post, but the short version: it uses 96Mi of memory, stores data in a 1Gi Longhorn PVC, and signups are disabled. Network policies restrict it to Traefik ingress and DNS egress only.
Memory: 96Mi | Replaces: Bitwarden Premium ($10/yr)
Actual Budget: Personal Finance
Actual is an envelope-style budgeting app. It replaced YNAB, which went from a one-time purchase to a $99/year subscription and moved everything to their cloud. Actual is open-source, self-hosted, and stores data locally. The UI is fast, the sync works across devices, and the budgeting methodology is identical to YNAB’s original approach.
At 160Mi and 1Gi of storage, it is one of the lightest apps in the cluster. I check it a few times a week to categorize transactions and review budget status.
Memory: 160Mi | Replaces: YNAB ($99/yr)
Linkding: Bookmark Manager
Every article I want to save goes into Linkding. It is a simple bookmark manager with tagging, search, full-text archival, and a browser extension that makes saving a two-click operation. I tried Raindrop.io, Pocket, and browser bookmarks. None of them survived more than a few months because they were either too complex or too limited.
Linkding does one thing and does it well. It runs as a single Python process at 192Mi, stores bookmarks in a SQLite database, and that is exactly the right amount of complexity for saving links.
Memory: 192Mi | Replaces: Raindrop.io ($0–28/yr)
The Media Stack
These apps serve content from my Unraid NAS over NFS. The media files live on Unraid’s disk array: terabytes of storage that would be absurd to put on a laptop NVMe. The Kubernetes pods mount the NFS shares read-only and handle indexing, transcoding, and streaming.
Navidrome: Music Server
Navidrome indexes my music library and streams it via the Subsonic API. On my phone, I use Symfonium. On desktop, the Navidrome web UI. The library lives on a 500Gi NFS share on Unraid.
It replaced Spotify. Not entirely. I still use Spotify for discovery. But for music I own, Navidrome means I am not paying a subscription to listen to files I already have. It also means my listening history is not being mined for ad targeting.
Navidrome integrates with Authentik for authentication via a reverse proxy header (X-authentik-username), which auto-creates user accounts on first login.
Memory: 192Mi | Replaces: Spotify (partially, $11/mo)
Audiobookshelf: Audiobook and Podcast Server
Audiobookshelf manages my audiobook library with per-book progress tracking, chapter navigation, and playback speed controls. Like Navidrome, the media lives on a 500Gi NFS share. The config and metadata database live on a 2Gi Longhorn PVC.
It replaced Audible. I still buy audiobooks, but now I strip the DRM and host them myself. Audiobookshelf’s mobile app tracks progress across devices, handles sleep timers, and works offline with downloaded files. It is genuinely better than Audible’s app for library management.
Memory: 256Mi | Replaces: Audible app (free, but DRM-locked)
The Blog
Ghost: CMS and Publishing Platform
You are reading it. Ghost runs with a SQLite backend at 384Mi, which makes it one of the heavier apps in the cluster. It replaced a static HTML page baked into a ConfigMap, which was technically cheaper but made publishing anything an exercise in frustration.
Ghost has its own backup CronJob that writes nightly tarballs to Unraid, and its own debugging post about the redirect loop that cost me an embarrassing amount of time. It is the most written-about service in the cluster, which I suppose is appropriate for the service that produces the writing.
Memory: 384Mi | Replaces: Medium, Dev.to, or paying for Ghost Pro ($9–25/mo)
The Operations Layer
These apps monitor, manage, and present the cluster itself.
Uptime Kuma: Uptime Monitoring
Uptime Kuma pings every service endpoint on a schedule and tracks availability over time. If something goes down, it fires a webhook to ntfy, which pushes a notification to my phone. It is simple, visual, and shows me at a glance whether everything is healthy.
I run it alongside Prometheus, which might seem redundant. It is not. Prometheus monitors the internals of the cluster: CPU, memory, pod restarts, log patterns. Uptime Kuma monitors the externals: can a user actually reach the service? Both can be green when the other is red.
Memory: 256Mi | Replaces: UptimeRobot ($0–$7/mo)
Homepage: Dashboard
Homepage is a customizable start page that aggregates links and status information for every service. Each app gets a card with a health indicator, a direct link, and metadata pulled from the service’s API where available. It is the single pane of glass for the cluster.
The configuration is interesting: an init container copies config files from a ConfigMap to an emptyDir volume on startup. This means Homepage’s config lives in Git and deploys through Flux like everything else, even though the app expects writable config files at runtime.
Memory: 192Mi | Replaces: nothing (it is its own category)
ntfy: Push Notification Hub
ntfy is a self-hosted push notification server. Publish an HTTP POST to a topic, subscribers get a push notification. It is the alert bus for the entire cluster: Prometheus Alertmanager and Uptime Kuma both route to it, and it relays to my phone.
At 128Mi, it is one of the cheapest services to run. The value is disproportionate: without ntfy, every alert would require me to be looking at a dashboard at the right moment.
Memory: 128Mi | Replaces: PagerDuty/OpsGenie ($0–29/mo)
The Utility Belt
Apps I use occasionally but would miss if they disappeared.
IT-Tools: Developer Utilities
A collection of converters, encoders, generators, and formatters in a single web app. Base64 encode/decode, JWT debugger, cron expression parser, UUID generator, hash calculator. It is the kind of thing you Google for and end up on a sketchy ad-laden site. Self-hosting it means I get clean tools with no tracking.
At 64Mi, it is the lightest app in the cluster. No persistent storage. No database. Just an nginx container serving static HTML and JavaScript.
Memory: 64Mi | Replaces: random web tools
Stirling-PDF: PDF Toolkit
Merge, split, compress, convert, OCR, watermark: every PDF operation you would normally do with a paid desktop app or a shady online tool. Stirling-PDF runs a Java backend with a web UI.
Java being Java, the JVM wanted to eat the entire node. I capped it at 128MB heap via JAVA_TOOL_OPTIONS=-Xmx128m, which keeps the container at 384Mi total. It is not light, but it replaces Adobe Acrobat Pro ($20/mo) for the operations I actually need.
Memory: 384Mi | Replaces: Adobe Acrobat Pro ($20/mo)
Mealie: Recipe Manager
Mealie stores recipes with a clean UI, meal planning, and a grocery list generator. Paste a URL from any recipe site and it extracts the recipe, stripping the 4,000-word life story that food bloggers prepend to every ingredient list.
At 448Mi, it is the heaviest app in the cluster. Python/FastAPI with a high baseline memory footprint. I have considered dropping it. The memory cost is steep for how often I use it. But every time I go to cook something and the recipe is right there, clean and ad-free, I decide to keep it.
Memory: 448Mi | Replaces: Paprika ($5 one-time), recipe websites
The Total Cost
| App | Memory Limit | Replaces |
|---|---|---|
| Miniflux + Postgres | 256Mi | Feedly |
| Vaultwarden | 96Mi | Bitwarden |
| Actual Budget | 160Mi | YNAB |
| Linkding | 192Mi | Raindrop.io |
| Navidrome | 192Mi | Spotify (partial) |
| Audiobookshelf | 256Mi | Audible app |
| Ghost | 384Mi | Ghost Pro / Medium |
| Uptime Kuma | 256Mi | UptimeRobot |
| Homepage | 192Mi | Nothing |
| ntfy | 128Mi | PagerDuty |
| IT-Tools | 64Mi | Web tools |
| Stirling-PDF | 384Mi | Adobe Acrobat |
| Mealie | 448Mi | Paprika / recipe sites |
| Total | 3,008Mi |
Three gigabytes of memory limits for 13 services. The infrastructure layer (Cilium, Longhorn, Prometheus, Grafana, Loki, Alloy, Traefik, Authentik, cert-manager, Cloudflare tunnel) uses roughly 9 GB. The apps are not the problem. The platform is.
In dollar terms, the SaaS equivalents would run somewhere between $20 and $60 per month depending on which tiers you pick. The homelab costs about $5/month in electricity. The Dell laptop was free (it was headed for e-waste). The NVMe and RAM were already in it. The real cost is time, and I have written 26 blog posts about that time, so clearly I do not consider it wasted.
What I Would Cut
If I had to drop the cluster to 8 GB of RAM tomorrow, the apps would not be where I cut. The entire app layer is 3 GB. The infrastructure is 9 GB. I would look at Longhorn first (its instance-manager alone uses over 1 GB), then at whether Loki could be replaced with something lighter, then at Grafana’s 512Mi footprint.
If I had to cut apps specifically: Mealie goes first (448Mi for occasional use), then Stirling-PDF (384Mi, could use the CLI version on my laptop instead). Everything else either earns its memory daily or costs so little that cutting it would not matter.
What I Would Add
The short list, if the second node materializes and I have 32 GB more to work with:
- Immich: self-hosted Google Photos replacement. The biggest SaaS dependency I have not addressed yet. Photo storage is the one thing I still trust entirely to a cloud provider, and that bothers me.
- Paperless-ngx: document management with OCR. Every receipt, bill, and tax document, searchable and tagged. Currently these live in a folder on my NAS with no organization.
- Gitea or Forgejo: self-hosted Git. Not to replace GitHub, but for private repos and mirrors that I do not want on someone else’s infrastructure.
But that is a future post. For now, 13 apps on 3 GB of RAM, all deployed through Git, all monitored, all backed up. The Architect is satisfied.