Self-hosters need a middle path between one Compose VM and full platform engineering
Updated 2026-06-24

Most self-hosters eventually hit a wall: a single Docker Compose VM starts to creak, but building a full internal platform with Nomad, Consul, Vault, and custom automation is a project in itself.
The two extremes
On one end you have the battle-hardened single VM: Docker Compose, Traefik as a reverse proxy, Cloudflare for DNS and DDoS protection, maybe a nightly backup cronjob. It works well until it doesn't. One bad compose file or a runaway container takes everything down. There's no isolation between services, no easy way to roll back a broken deployment, and monitoring is often an afterthought — a few Uptime Kuma checks and a Telegram alert if the site stops responding.
On the other end you have what some operators are building in their homelabs: a full virtual datacenter. One KVM homelab author documented building out DNS, PXE boot, NFS storage, service lifecycle management, snapshot workflows, and automated health checks — essentially the same infrastructure patterns a cloud provider runs, just at home. Another operator migrated their public-service workloads from a hardened Compose VM into a TrueNAS-backed Nomad and Consul cluster, with Vault for secrets, a WireGuard mesh, an internal PKI, custom Python automation for deployments, a status page for users, and documented recovery paths for every failure scenario.
Both approaches are legitimate. The second one is impressive engineering. It's also weeks or months of work before you ship a single line of your actual application.
Where operator fatigue sets in
The problem with the full platform path is not the complexity itself — it's the maintenance surface. Every component you add is something that can break on a Sunday night. Consul has to be healthy for Nomad to schedule jobs. Vault needs to be unsealed. Your internal PKI needs renewals. Your Python automation has to handle edge cases you didn't think of when you wrote it.
A mobile-first homelab NOC builder described exactly this problem: they're trying to unify asset health, SSL and domain expiry monitoring, private uptime checks, Docker container state, and recovery visibility into a single coherent view. That's not a feature request — it's operator fatigue expressing itself as a dashboard problem.
When you're running public services (not just home automation), the maintenance overhead of a full platform directly competes with the time you have to work on the thing you actually wanted to host.
What the middle path looks like
The practical middle path is not a new tool category — it's a set of decisions that let you add structure incrementally without committing to a full platform upfront.
One VM per concern, not one service per VM. Instead of cramming everything into one Compose file, group services by failure domain. Your public-facing web apps in one VM, your databases in another, your internal tooling in a third. This gives you isolation without the overhead of a scheduler.
Treat your Compose files as the deployment unit. Version-control each one, use .env files for configuration, and deploy with a simple git pull && docker compose up -d. You don't need a pipeline for this — a Makefile or a short shell script per project is enough.
Add observability before adding orchestration. The most common mistake is reaching for Nomad or Kubernetes when what you actually need is to see what's running and whether it's healthy. Tools like ServerCompass let you see all your running services, SSL expiry, and uptime at a glance across multiple hosts — which is often exactly what a NOC dashboard is trying to solve, without standing up a full monitoring stack.
Document your recovery paths as you go. The operator who migrated to Nomad/Consul/Vault noted that documented recovery paths were a deliberate part of their build. You don't need Vault to document what you do when your database won't start. A plain Markdown file in your repo is enough, and it forces you to think through failure scenarios before they happen.
Automate the toil, not the architecture. Custom Python automation for deployments sounds useful until you're debugging it at 2am. Automate the things you do every day (deployments, certificate renewals, backups), and keep the things you do rarely (adding a new service, migrating a database) manual and documented. The ratio of automation to documentation should shift toward documentation as the consequences of failure increase.
When to actually move to a platform
The full platform path is worth it when the operational requirements justify it — specifically:
- You're running workloads for other people and need SLA-level reliability
- You have multiple team members who need controlled access to different services
- Your service count has grown to the point where manual coordination of deployments is causing incidents
- You need audit trails for compliance reasons
If none of those apply, the single-VM or multi-VM Compose approach with good observability and documented runbooks will take you further than most operators think. The homelab builders doing full Nomad/Consul/Vault platforms are often solving for the learning experience as much as the operational need — which is a perfectly valid reason, but different from what most public-service operators need.
The gap between "one Compose VM" and "full platform engineering" is real, but it's mostly filled with better habits, not more software.
Checklist
- Split services by failure domain across VMs rather than running everything in one Compose file
- Version-control each Compose file and deploy with a simple
git pull && docker compose up -d - Add observability (uptime, SSL expiry, container health) before reaching for an orchestrator — ServerCompass covers this without standing up a monitoring stack
- Document recovery steps for every service in a plain Markdown file in the repo
- Automate daily toil (deployments, cert renewals, backups) but keep rare operations manual and documented
- Only add a scheduler (Nomad, Swarm, etc.) when manual coordination is actively causing incidents
- Build recovery paths explicitly — do not assume you will remember what to do when a service fails at 2am
- Review your maintenance surface every few months: every component you add is something that can break on a Sunday night
Final verdict