navigate open Esc close

Linux

Docker and Zoraxy Are Enough for My Homelab

Why my current homelab runs on Docker, Zoraxy, Cloudflare, and one exposed port instead of Kubernetes.

The easiest way to ruin a homelab is to make it look like a company infrastructure project before it needs to be one.

I like Kubernetes. I understand why people run k3s at home. It teaches useful concepts: scheduling, service discovery, ingress, storage classes, secrets, declarative configuration. If the goal is to learn Kubernetes, k3s makes sense.

But that is not my current goal. My goal is to run services I actually use, keep the system understandable, expose as little as possible, and avoid spending more time operating the platform than using it.

For that, Docker is enough right now.

The hardware#

My homelab is currently two machines with very different jobs.

The first is my old Mac Studio. It has an M2 Max chip and 96GB of unified memory. I use it for local LLM experiments, rendering work, and anything that benefits from a large memory pool. It is not the general-purpose server. It is the local compute box.

The second is the storage and services machine: a Ryzen 9 7900, 64GB of RAM, and an RTX 2060 Super that I had lying around. The GPU is useful for media encoding and related workloads. This machine does the heavier self-hosting work: storage, containers, databases, media, analytics, and the services that need to run quietly in the background.

This split matters. Not every machine in a homelab needs to be a node in a cluster. A homelab is not a ritual object. Hardware should have jobs.

What runs on it#

The current stack is practical rather than fashionable.

  • Docker
  • Docker Compose
  • Zoraxy
  • Cloudflare
  • Plausible
  • Jellyfin
  • The arr stack
  • Databases
  • OpenCode test environments
  • This website
  • Analytics and observability tools
  • A long tail of internal services

This is not a small setup, but it also does not require Kubernetes. Most of these services want a container, a volume, a network, a few environment variables, and a reverse proxy entry. Docker Compose handles that cleanly.

The question is not “can Kubernetes run this?” Of course it can. The question is whether Kubernetes improves the system enough to justify the operational overhead. For my current traffic and workload pattern, the answer is no.

The network model#

Only port 443 is exposed.

Everything public enters through HTTPS. Everything else is either behind the reverse proxy, internal-only, or not exposed at all. Zoraxy handles the routing. Cloudflare handles DNS and the public edge. Services talk internally where they can.

That one rule keeps the system legible.

If a service needs to be public, it gets a deliberate route. If it does not need to be public, it stays local. Most internal tools do not need to exist on the open internet. They need to be available to me, on my network, when I need them.

This is where self-hosting becomes less about ideology and more about threat surfaces. Every exposed port is a maintenance obligation. Every public login screen is a future problem. The best public endpoint is the one that does not exist.

Why Zoraxy#

Zoraxy fits the current system because it keeps reverse proxy management straightforward.

I do not need a complex ingress controller for this setup. I need clean routing, TLS, simple service mapping, and the ability to look at the system without decoding a pile of YAML. Zoraxy gives me that.

There is a place for Nginx, Caddy, Traefik, and Kubernetes ingress. I am not making a universal argument against them. I am saying that in a home environment, the best tool is often the one that reduces the number of moving parts you have to keep in your head.

The reverse proxy is load-bearing. If it becomes confusing, the whole homelab becomes confusing.

Why Docker, not Kubernetes#

The reason is simple: Docker solves the problem I currently have.

I do not have traffic that needs horizontal scaling. I do not need a scheduler deciding which node runs which workload. I do not need a multi-node control plane. I do not need distributed block storage. I do not need to pretend my house is a cloud region.

What I need is:

  1. Services that restart when they crash.
  2. Volumes that are easy to reason about.
  3. Networks that are explicit.
  4. Backups that can be tested.
  5. A reverse proxy that routes cleanly.
  6. A deployment process that I can understand at 1 a.m.

Docker Compose is boring, and that is the point. The file tells me what runs, what ports exist, what volumes matter, and which services depend on each other. It is not glamorous infrastructure. It is maintainable infrastructure.

When I need to scale horizontally, I will revisit the question. Until then, adding orchestration for imaginary traffic would be self-inflicted complexity.

The recommendation#

If you are building a homelab, start with the problem, not the platform.

If your goal is to learn Kubernetes, run k3s. That is a valid goal. A homelab is a good place to break things safely.

If your goal is to run services reliably, start with Docker Compose. Add a reverse proxy. Expose one port. Keep most things internal. Back up your volumes. Document what each service does. Learn the failure modes before you add more machinery.

The path I would recommend looks like this:

  1. One Linux server with enough storage.
  2. Docker and Docker Compose.
  3. One reverse proxy, in my case Zoraxy.
  4. Cloudflare for DNS and edge handling.
  5. Port 443 exposed, nothing else unless there is a strong reason.
  6. Internal networks for services that only need to talk to each other.
  7. Backups before experiments.
  8. Monitoring after the basics work.

That order matters. People often add dashboards before backups, orchestration before documentation, and complexity before they have enough services to justify it.

What can go wrong#

Docker does not remove operational responsibility. It just makes the unit of deployment easier.

The common failure modes are predictable.

  • Volumes become unclear. If you do not know where the data lives, you do not have a backup strategy.
  • Compose files sprawl. Every service gets added casually until nobody knows what depends on what.
  • Ports leak. A container exposes something publicly because nobody checked the mapping.
  • Databases become pets. They run for months, then fail, and nobody remembers the restore process.
  • Internal tools become public tools. Convenience slowly expands the attack surface.

The fix is not Kubernetes. The fix is discipline. Name volumes clearly. Keep compose files readable. Use internal networks. Expose only what needs to be exposed. Test restores. Write down what the service is for.

Maintenance is more important than innovation here.

The ownership argument#

The point of a homelab is not to cosplay as a cloud provider. The point is ownership.

When I run my own services, I understand more of the stack. I know where the data is. I know which systems depend on each other. I know what happens when something fails. That knowledge is worth more than the small amount of money saved on subscriptions.

Self-hosting also changes how you think about software. You become less impressed by dashboards and more interested in backups. Less impressed by new features and more interested in logs. Less impressed by abstractions and more interested in where the data actually lives.

That is the useful part.

The conclusion#

My current homelab is not designed to be impressive. It is designed to work.

The Mac Studio handles local compute, LLMs, and rendering. The Ryzen storage server handles Docker workloads, media, databases, analytics, and this site. Zoraxy routes traffic. Cloudflare sits at the edge. Only 443 is exposed. Most tools stay internal.

That is enough for now.

If the system grows beyond Docker, I will move beyond Docker. But infrastructure should earn its complexity. Until horizontal scaling becomes a real requirement, Docker and Zoraxy are the right level of boring.