This is my actual infrastructure — the real thing, not a reference diagram or a planning doc. It runs on Proxmox on commodity hardware in Ontario. I'm writing it down because most self-hosting guides show you either a single container or a full enterprise deployment. This is what the middle looks like after years of iteration.

The Foundation

Proxmox VE on commodity hardware — VMs and LXC containers, nothing exotic. The point is that you can swap any piece of this for whatever you already have. Proxmox is free, runs on anything with a CPU and enough RAM, and gives you one web interface for the whole fleet.

Everything runs in Docker containers under Docker Compose. Each service gets its own directory, its own compose file, its own data volume. That isolation means I can update, restart, or debug one service without touching the rest.

The Gateway

Traefik is the reverse proxy. Every service is reachable by domain name with automatic TLS from Let's Encrypt, and Traefik discovers services from their labels — deploy a container with the right labels and it routes itself. No hand-edited nginx files.

Crowdsec is the community-driven WAF. It reads Traefik's access logs, recognizes attack patterns, and shares threat intelligence with other Crowdsec nodes — fail2ban's idea, but collaborative and aware of application-layer attacks. See Traefik + Crowdsec for the setup.

WireGuard handles remote access. No port forwarding, no exposed admin panels — I reach the network from anywhere through an encrypted tunnel. The only ports open to the internet are 80 and 443, in front of Traefik.

The Services

Security & Identity

  • Vaultwarden — Self-hosted Bitwarden. Passwords, TOTP, secure notes. The first service I tell anyone to self-host.
  • Crowdsec — Intrusion detection and community threat sharing.

Code & Development

  • Gitea — Self-hosted Git: all my repositories, CI runners, and issue tracking. My code doesn't live exclusively on someone else's platform.
  • The Samaritan Portal — This site. SvelteKit, prerendered to static files and served behind Traefik.

Media & Knowledge

  • Plex — Media server. My library, my rules, no algorithm deciding what I should watch.
  • Navidrome — Music streaming. Subsonic-compatible, works with any Subsonic client.
  • Audiobookshelf — Audiobooks and podcasts with progress tracking.
  • Kiwix — Offline Wikipedia and other reference archives. The entire English Wikipedia, served locally.

Home & Automation

  • Home Assistant — Home automation with no cloud dependency. Lights, sensors, climate — all local.

AI & Inference

  • Ollama — Local LLM inference on a local GPU. No tokens sent to external APIs for private queries.
  • Bifrost — An OpenAI-compatible inference gateway that routes requests to the right model backend.

Web Properties

Utilities

  • PrivateBin — Encrypted pastebin. Share text without a third party reading it.
  • Deluge — Torrent client with a web interface.

The Patterns

One service, one directory, one compose file. Resist the urge to put everything in a single docker-compose.yml — past a couple dozen services, monolithic compose files become unmanageable.

Labels over published ports. Let containers register with the reverse proxy through labels instead of exposing ports on the host. Traefik handles routing; the host stays clean.

Named volumes for persistent data. Unless you need direct filesystem access (like serving static files), named volumes are cleaner than bind mounts.

Restart policies matter. restart: unless-stopped on everything. If the host reboots, the services come back; if I explicitly stop one, it stays stopped.

Back up the data, not the config. The compose files are replaceable — they live in Git. The data volumes are not. Back them up, and test the restores. I use local snapshots plus encrypted off-site copies.

See Docker Patterns for more operational detail.

Why this instead of the cloud

This entire stack runs on hardware I own. The electricity bill is real and the maintenance is real — but so is the trade-off: none of it can be taken away by a vendor decision, a pricing change, or an acquisition. My passwords, my code, my media, my home automation, my AI inference — all on my own metal.

That's the stack. It took years to get here. Start with one service and grow.