Skip to main content

How to Build a Homelab in 2026: Software Stack

·OSSAlt Team
homelabself-hostingdockerproxmoxnetworkingmonitoringmedia-serverlinux

How to Build a Complete Homelab in 2026: Software Stack Guide

The homelab has changed. In 2020, a homelab was a repurposed desktop running Plex. In 2026, the same hardware runs 20+ services — a private cloud replacing subscriptions to Dropbox, Netflix, Zapier, LastPass, and a dozen SaaS tools — all orchestrated through Docker Compose, monitored with Uptime Kuma, and exposed securely via Cloudflare Tunnel.

This guide covers the full 2026 homelab software stack: what to run, how to run it, and how it all fits together.

The 2026 Homelab Philosophy

Before the software: one principle. Replace subscriptions, not just add complexity. Every service in your homelab should replace something you're paying for (or would pay for). A homelab that costs 20 hours to maintain but saves $0 is a hobby. A homelab that saves $2,000/year in subscriptions while taking 2 hours/month to maintain is an investment.

The stack below is built around that principle. Every component has a clear "what this replaces" answer.


Layer 1: The Foundation — OS and Virtualization

Proxmox VE (Type-1 hypervisor, free, Debian-based) is the recommended foundation for any homelab with more than 3–4 services. It runs on bare metal and lets you create:

  • LXC containers — lightweight Linux containers with near-native performance; ideal for services that don't need full isolation
  • KVM VMs — full virtual machines for Windows, pfSense, TrueNAS, or anything requiring its own kernel
  • Mix and match — a TrueNAS VM for storage, LXC containers for services, isolated VMs for testing
# Install Proxmox VE on a bare metal machine
# Download ISO from proxmox.com/downloads
# Boot from USB, follow installer
# After install — disable enterprise repo (requires subscription):
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" > \
  /etc/apt/sources.list.d/pve-no-subscription.list
apt update && apt full-upgrade

Proxmox hardware minimums: 4 GB RAM (8+ GB recommended), 64-bit x86 CPU with virtualization extensions (Intel VT-x or AMD-V), SSD for the OS.

Ubuntu Server / Debian (Simpler Alternative)

If you're running a single machine and don't need VMs, Ubuntu Server 24.04 LTS or Debian 12 with Docker is faster to set up. Skip Proxmox unless you need VM isolation.

# Install Docker on Ubuntu Server 24.04
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

Layer 2: Container Management

Portainer CE

Portainer gives you a web GUI for managing Docker containers across hosts — view logs, restart containers, browse volumes, and deploy new stacks without SSH.

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

volumes:
  portainer_data:

Access at https://your-server:9443. For multi-host setups, deploy the Portainer Agent on each host and connect them all to a single Portainer CE instance.

Dockge (Compose-Focused Alternative)

Dockge is a newer, lightweight Compose-focused UI — better if you primarily work with Docker Compose stacks rather than individual containers.

services:
  dockge:
    image: louislam/dockge:latest
    restart: unless-stopped
    ports:
      - "5001:5001"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - dockge_data:/app/data
      - /opt/stacks:/opt/stacks  # directory where your compose files live
    environment:
      - DOCKGE_STACKS_DIR=/opt/stacks

Layer 3: Reverse Proxy and SSL

A reverse proxy lets you access all services via clean domain names (jellyfin.home, nextcloud.yourdomain.com) and handles SSL termination.

Nginx Proxy Manager

The most popular homelab reverse proxy. Point DNS at your server, add a proxy host in the UI, and NPM fetches Let's Encrypt certificates automatically.

services:
  nginx-proxy-manager:
    image: jc21/nginx-proxy-manager:latest
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "81:81"  # Admin UI
    volumes:
      - npm_data:/data
      - npm_letsencrypt:/etc/letsencrypt

volumes:
  npm_data:
  npm_letsencrypt:

Admin UI at http://your-server:81. Default credentials: admin@example.com / changeme — change on first login.

Cloudflare Tunnel (No Port Forwarding Required)

If you don't want to open ports on your router, Cloudflare Tunnel creates an outbound-only encrypted tunnel from your server to Cloudflare's edge:

# Install cloudflared
docker run -d \
  --name cloudflared \
  --restart unless-stopped \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run \
  --token YOUR_TUNNEL_TOKEN

Configure in Cloudflare Zero Trust dashboard. Point tunnel routes to http://nginx-proxy-manager:80 or directly to services. No public IP, no port forwarding, no DynDNS required.


Layer 4: DNS

Pi-hole + Unbound

Pi-hole blocks ads and tracking at the DNS level for your entire network. Unbound adds a recursive DNS resolver, eliminating dependence on upstream DNS providers.

services:
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    restart: unless-stopped
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "8080:80"
    environment:
      - TZ=America/New_York
      - WEBPASSWORD=${PIHOLE_PASSWORD}
      - PIHOLE_DNS_=172.20.0.3#5335  # Unbound container
    volumes:
      - pihole_config:/etc/pihole
      - dnsmasq_config:/etc/dnsmasq.d
    networks:
      dns_net:
        ipv4_address: 172.20.0.2

  unbound:
    image: mvance/unbound:latest
    container_name: unbound
    restart: unless-stopped
    volumes:
      - unbound_config:/opt/unbound/etc/unbound
    networks:
      dns_net:
        ipv4_address: 172.20.0.3

networks:
  dns_net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

volumes:
  pihole_config:
  dnsmasq_config:
  unbound_config:

Set your router's DHCP DNS to your Pi-hole server's IP. All devices get ad-blocking automatically without configuring each device individually.

Pi-hole also handles local DNS — add custom DNS records for internal services:

  • jellyfin.home192.168.1.100
  • nextcloud.home192.168.1.100
  • portainer.home192.168.1.100

Layer 5: File Storage

Nextcloud

Self-hosted Google Drive replacement. Handles files, contacts, calendars, document editing (via Nextcloud Office/Collabora), and video calls (Nextcloud Talk).

# All-in-One method (recommended)
docker run \
  --name nextcloud-aio-mastercontainer \
  --restart always \
  --publish 80:80 \
  --publish 8080:8080 \
  --publish 443:443 \
  --volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
  --volume /var/run/docker.sock:/var/run/docker.sock:ro \
  nextcloud/all-in-one:latest

Open https://your-server-ip:8080 → enter your domain → AIO handles Let's Encrypt and starts all containers.

Replaces: Google Drive, Google Docs, Google Calendar, Google Contacts ($7–14/user/month on Google Workspace)

Immich (Photo Backup)

Immich is the best self-hosted Google Photos replacement. Face recognition, mobile backup, album sharing, search by location or date.

services:
  immich-server:
    image: ghcr.io/immich-app/immich-server:release
    restart: unless-stopped
    ports:
      - "2283:2283"
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
    environment:
      - DB_HOSTNAME=database
      - DB_USERNAME=postgres
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_DATABASE_NAME=immich
      - REDIS_HOSTNAME=redis
    depends_on:
      - redis
      - database

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:release
    restart: unless-stopped
    volumes:
      - model_cache:/cache

  redis:
    image: redis:7-alpine
    restart: unless-stopped

  database:
    image: tensorchord/pgvecto-rs:pg16-v0.2.0
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: postgres
      POSTGRES_DB: immich
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  model_cache:
  postgres_data:

Replaces: Google Photos ($3–10/month for storage), iCloud Photos ($2.99–9.99/month)


Layer 6: Media Server

Jellyfin

Free, open-source, GPL-2.0. Hardware transcoding at no cost. Zero telemetry.

services:
  jellyfin:
    image: lscr.io/linuxserver/jellyfin:latest
    container_name: jellyfin
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
    volumes:
      - jellyfin_config:/config
      - /mnt/media/movies:/data/movies
      - /mnt/media/tv:/data/tv
      - /mnt/media/music:/data/music
    ports:
      - "8096:8096"
    devices:
      - /dev/dri:/dev/dri  # Intel/AMD hardware transcoding

volumes:
  jellyfin_config:

After start: Dashboard → Playback → Transcoding → enable VA-API (Intel/AMD) or NVENC (NVIDIA).

Replaces: Plex Pass ($69.99/year), Netflix, streaming subscriptions

*arr Stack (Automated Media Management)

The *arr stack automates downloading and organizing your media library:

services:
  sonarr:
    image: lscr.io/linuxserver/sonarr:latest
    ports:
      - "8989:8989"
    volumes:
      - sonarr_config:/config
      - /mnt/media/tv:/tv
      - /mnt/downloads:/downloads

  radarr:
    image: lscr.io/linuxserver/radarr:latest
    ports:
      - "7878:7878"
    volumes:
      - radarr_config:/config
      - /mnt/media/movies:/movies
      - /mnt/downloads:/downloads

  prowlarr:
    image: lscr.io/linuxserver/prowlarr:latest
    ports:
      - "9696:9696"
    volumes:
      - prowlarr_config:/config

  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    ports:
      - "8080:8080"
    volumes:
      - qbittorrent_config:/config
      - /mnt/downloads:/downloads
  • Sonarr: TV show monitoring and download automation
  • Radarr: Movie monitoring and download automation
  • Prowlarr: Indexer manager (connects Sonarr/Radarr to torrent/Usenet indexes)
  • qBittorrent: Download client

Layer 7: Monitoring

Uptime Kuma

Single-container uptime monitoring for all your services. 90+ notification channels, public status pages, SSL/domain expiry alerts.

services:
  uptime-kuma:
    image: louislam/uptime-kuma:latest
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - uptime_kuma_data:/app/data
      - /var/run/docker.sock:/var/run/docker.sock  # Docker container monitoring

volumes:
  uptime_kuma_data:

First monitors to add: Nextcloud (HTTPS), Jellyfin (TCP 8096), Pi-hole (HTTP), Nginx Proxy Manager (HTTPS), Immich (HTTP 2283), Portainer (HTTPS 9443), your main domain SSL certificate expiry.

Replaces: Better Stack ($20/month), Freshping, StatusCake paid plans

Grafana + Prometheus (Advanced Metrics)

For server metrics (CPU, RAM, disk, network): add Prometheus and node_exporter alongside Uptime Kuma.

services:
  prometheus:
    image: prom/prometheus:latest
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

  node_exporter:
    image: prom/node-exporter:latest
    restart: unless-stopped
    pid: host
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro

  grafana:
    image: grafana/grafana:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana

Import Grafana dashboard ID 1860 (Node Exporter Full) for a complete server metrics dashboard out of the box.


Layer 8: Security

Vaultwarden

Bitwarden-compatible password manager server. All vault data stays on your server.

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    ports:
      - "8083:80"
    volumes:
      - vaultwarden_data:/data
    environment:
      - ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
      - SIGNUPS_ALLOWED=false  # Disable after creating your account

volumes:
  vaultwarden_data:

Use Bitwarden's official apps (browser extension, mobile, desktop) and point them to your Vaultwarden URL. 100% compatible.

Replaces: Bitwarden Premium ($10/year), 1Password ($36/year), LastPass ($36/year)

Authentik (Single Sign-On)

Authentik provides SSO for all your homelab services — one login across Nextcloud, Grafana, Portainer, and any other service that supports OIDC or SAML.

services:
  postgresql:
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: ${PG_PASS}
      POSTGRES_USER: authentik
      POSTGRES_DB: authentik
    volumes:
      - authentik_db:/var/lib/postgresql/data

  redis:
    image: docker.io/library/redis:alpine
    restart: unless-stopped

  server:
    image: ghcr.io/goauthentik/server:2025.10
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
    ports:
      - "9000:9000"
      - "9443:9443"

  worker:
    image: ghcr.io/goauthentik/server:2025.10
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
      AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}

Replaces: Okta ($2/user/month), Auth0 (paid tiers), Duo ($3/user/month)


Layer 9: Network Security

Tailscale (Zero-Config VPN)

Tailscale creates a secure mesh VPN between all your devices. Access homelab services from anywhere without opening ports.

services:
  tailscale:
    image: tailscale/tailscale:latest
    restart: unless-stopped
    network_mode: host
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    volumes:
      - /dev/net/tun:/dev/net/tun
      - tailscale_state:/var/lib/tailscale
    environment:
      - TS_AUTHKEY=${TAILSCALE_AUTH_KEY}
      - TS_ROUTES=192.168.1.0/24  # Advertise your home subnet
      - TS_ACCEPT_DNS=false

With subnet routing enabled, you can access all homelab services from your phone or laptop via Tailscale IPs — no Cloudflare Tunnel, no port forwarding.

Replaces: WireGuard self-hosted setup (Tailscale is WireGuard under the hood, just with automatic key management)


Layer 10: Automation

n8n or Activepieces

Workflow automation to connect all your services. Trigger actions when files are added to Nextcloud, send Telegram alerts when services go down, automate routine tasks.

services:
  n8n:
    image: n8nio/n8n:latest
    restart: unless-stopped
    ports:
      - "5678:5678"
    volumes:
      - n8n_data:/home/node/.n8n
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}

Common homelab automations:

  • Uptime Kuma → Telegram: custom alert formatting
  • Nextcloud file upload → trigger Immich sync
  • Sonarr/Radarr download complete → Jellyfin library scan notification
  • Weekly backup verification: ping Uptime Kuma heartbeat after backup script succeeds

Complete Hardware Sizing Guide

Use CaseCPURAMStoragePower Draw
Minimal (3–5 services)4-core8 GB120 GB SSD + NAS~35W
Standard homelab (10–15 services)6–8 core16 GB256 GB SSD + 4 TB HDD~45–65W
Full stack (20+ services + Plex/Jellyfin 4K)8–12 core32 GB512 GB NVMe + 8+ TB~65–120W
Mini PC (N100/N305)4 core16 GB500 GB NVMe~10–15W

2026 popular hardware: Intel N100/N305 mini PCs (Beelink EQ12, Minisforum N305) are the efficiency-per-dollar winners for homelabs under 15 services. HP EliteDesk mini PCs (used, $80–150) offer excellent value. Older Xeon workstations give CPU headroom for transcoding but use significantly more power.


The Full Stack: Monthly Cost

Replaced ServiceHomelab EquivalentMonthly Savings
Google Photos (2 TB)Immich$3–10
Google Workspace (1 user)Nextcloud$14
NetflixJellyfin$23
Bitwarden PremiumVaultwarden$0.83
Zapier (Pro)n8n/Activepieces$49
Better Stack (100 monitors)Uptime Kuma$20
Plex PassJellyfin$5.83
Infrastructure (VPS or home server)Hetzner VPS or $200 mini PC-$15
Net monthly savings~$110–130/month

That's $1,320–$1,560/year in subscription savings from a homelab that takes 2–3 hours/month to maintain.


Building everything at once is overwhelming. This sequence minimizes dead ends:

  1. Week 1: OS + Docker + Portainer + Nginx Proxy Manager + Uptime Kuma
  2. Week 2: Pi-hole (local DNS) + Vaultwarden
  3. Week 3: Nextcloud (file sync on one device first) + Immich
  4. Week 4: Jellyfin + one *arr service
  5. Month 2: Authentik SSO + Tailscale + automation (n8n or Activepieces)
  6. Ongoing: Add services as they replace specific subscriptions

Start monitoring (Uptime Kuma) before adding services — you'll want visibility into what breaks during setup.


Browse all self-hosted alternatives at OSSAlt. Related: Uptime Kuma monitoring guide, Jellyfin vs Plex comparison, Dify for AI workflows.

Comments