Self-hosted infrastructure powering 40+ containerized services with 33TB of ZFS-backed storage.
  • PHP 48.5%
  • TypeScript 37.3%
  • Python 5.3%
  • HTML 4.8%
  • Hack 3%
  • Other 1.1%
Find a file
Dan 4d9fe66d90
Update PORTFOLIO.md
- removed redundancies
2026-02-28 16:29:05 +01:00
docker Complete restructuring 2026-02-28 15:31:40 +01:00
docs Update PORTFOLIO.md 2026-02-28 16:29:05 +01:00
infrastructure Complete restructure 2026-02-28 15:54:31 +01:00
scripts Complete restructuring 2026-02-28 15:31:40 +01:00
services Complete restructure 2026-02-28 15:54:31 +01:00
.env.example Complete restructuring 2026-02-28 15:31:40 +01:00
.gitignore Add Docker Compose configurations for all 60+ services 2026-02-17 00:20:23 +01:00
INDEX.md add: shoutout section 2026-02-28 16:22:25 +01:00
README.md add: shoutout section 2026-02-28 16:22:25 +01:00

Homelab Infrastructure

Status Services Storage OS NAS

A reference implementation of a self-hosted home infrastructure stack: 40+ containerised services, 33 TB storage, zero port-forwarding. Runs on NixOS with D-PlaneOS — a self-developed NAS management layer — currently migrating storage from BTRFS RAID5 to ZFS RAID-Z2.


INDEX.md — complete map of every file in this repository.

Contents


Architecture

Internet
  │
  ▼
VPS — IONOS, Berlin (2 vCPU / 2 GB RAM / 80 GB NVMe)
  ├─ UFW firewall        ports 80, 443, 51820 only
  ├─ CrowdSec IDS/IPS   community blocklists, Traefik bouncer
  ├─ Traefik v3          TLS 1.3 termination, Let's Encrypt
  └─ Gerbil              WireGuard endpoint (Pangolin component)
            │
            │  WireGuard tunnel — ChaCha20-Poly1305, encrypted
            ▼
Raspberry Pi 5 — local LAN hub (Pangolin brain)
  ├─ Pangolin server     identity, routing control plane
  ├─ Newt                tunnel termination
  └─ Traefik (inner)     internal routing → services
            │
            ▼
Home network — 10.XXX.0.0/24
  ├─ NAS server (10.XXX.0.1)     40+ containers, 33 TB storage
  └─ Pi-hole  (10.XXX.0.2)       DNS, ad-blocking

Key design decision: Pangolin tunnel instead of port-forwarding means the home IP is never exposed, there is no dynamic DNS dependency, and the home router attack surface is zero.

Interactive diagrams: Architecture · Security layers · Data flow


Security model

Defense in depth: each layer is independently hardened and does not rely on the correctness of outer layers.

Layer 1 — Perimeter (VPS)
  UFW: only ports 80, 443, 51820 reachable from internet
  CrowdSec: IP reputation, automated banning, community threat feeds
  DDoS mitigation: IONOS network-level

Layer 2 — Transport
  WireGuard: encrypted tunnel between VPS and home network
  TLS 1.3: enforced at both outer (VPS Traefik) and inner (Pi Traefik) layers
  Let's Encrypt: certificates auto-renewed, HSTS enabled

Layer 3 — Network isolation
  Docker bridge networks scoped per service group
  Databases not exposed to host network interface
  Services communicate only via explicitly defined networks

Layer 4 — Application
  Per-service authentication; OIDC where supported
  2FA enforced on Vaultwarden and Nextcloud
  Vaultwarden for shared credential management

Layer 5 — Data integrity
  ZFS end-to-end checksumming: every block verified on read, silent corruption repaired from RAID-Z2 parity
  RAID-Z2: dual-disk fault tolerance, no write-hole vulnerability (unlike BTRFS RAID5)
  Scheduled scrubs verify the full pool
  Current: migrating from BTRFS RAID5 — see infrastructure/storage/README.md

Service matrix

Media

Service Purpose Compose
Emby Media server arr-suite.yml
Sonarr TV show automation arr-suite.yml
Radarr Movie automation arr-suite.yml
Lidarr Music automation arr-suite.yml
Prowlarr Indexer management arr-suite.yml
Bazarr Subtitle automation arr-suite.yml
qBittorrent Download client (via Gluetun VPN) arr-suite.yml
Gluetun WireGuard VPN gateway for downloads arr-suite.yml
SwingMusic Self-hosted music player swingmusic.yml
Navidrome Music streaming (Subsonic API) navidrome.yml
Audiobookshelf Audiobooks + podcast server audiobookshelf.yml
Pinchflat YouTube archiver pinchflat.yml
Stremio Server Streaming add-on server stremio.yml

Productivity & cloud

Service Purpose Compose
Nextcloud + Collabora File sync, cloud office suite nextcloud.yml
Nextcloud Talk HPB High-performance video call backend nextcloud.yml
Immich Google Photos replacement immich.yml
Paperless-NGX Document OCR and archive paperless.yml
Vaultwarden Self-hosted Bitwarden server vaultwarden.yml
Joplin Server Note sync backend joplin.yml
Memos Lightweight notes / journal memos.yml
Linkwarden Bookmark archiver with full-page capture linkwarden.yml
Wallos Subscription and expense tracker wallos.yml

Infrastructure & management

Service Purpose Compose
Pi-hole Network-wide DNS + ad-blocking pihole.yml
Traefik v3 Reverse proxy, TLS termination VPS-managed — see infrastructure/networking/traefik/
Pangolin + Gerbil Self-hosted WireGuard tunnel VPS + Pi — see infrastructure/networking/pangolin/
CrowdSec IDS/IPS, collaborative threat intel VPS-managed — see infrastructure/security/crowdsec/
Dockge Docker Compose management UI dockge.yml
Dockpeek Container health dashboard dockpeek.yml
Scrutiny S.M.A.R.T disk health monitoring scrutiny.yml
Glances System resource monitoring glances-dashboard.yml
Syncthing Peer-to-peer file sync (config backup) syncthing.yml
SearXNG Self-hosted metasearch engine searxng.yml
PostgreSQL (×8) Relational database instances Per-service
Redis (×3) In-memory cache instances Per-service

Development

Service Purpose Location
D-PlaneOS website Project landing page d-planeos-website.yml
Aptifolio Next.js frontend + FastAPI backend + PDF resume parser aptifolio.yml

Storage strategy

Full details: infrastructure/storage/README.md

33 TB across four HDDs — currently BTRFS on mdadm RAID5 (legacy, from ZimaOS). Migrating to ZFS RAID-Z2 via D-PlaneOS.

Why ZFS

ZFS RAID-Z2 (dual-parity) eliminates the write-hole vulnerability present in BTRFS RAID5, provides end-to-end checksumming at every level of the storage tree, and integrates cleanly with D-PlaneOS's pool and dataset management. zfs send replication makes off-site backup straightforward. The 15+ year production track record in enterprise environments makes it the right choice for a long-lived NAS.

Target pool layout

zpool: mainpool  (RAID-Z2, 4× HDD)
├── mainpool/appdata     /DATA/AppData — container bind-mount volumes
├── mainpool/media       /DATA/Media   — media library
├── mainpool/home        user home directories
└── mainpool/backups     local snapshot targets

zpool: bootpool  (mirror, NVMe)
└── NixOS system root

Pool and dataset configuration is managed through D-PlaneOS. Refer to that repository for NixOS module definitions and dataset property details (compression=zstd, xattr=sa, recordsize tuning per workload).


Repository structure

homelab/
├── infrastructure/
│   ├── networking/
│   │   ├── pihole/pihole.yml
│   │   ├── traefik/          # Traefik config notes (VPS-managed)
│   │   └── pangolin/         # Pangolin tunnel docs + component map
│   ├── security/
│   │   ├── vaultwarden/vaultwarden.yml
│   │   └── crowdsec/         # CrowdSec notes (VPS-managed)
│   ├── monitoring/
│   │   ├── big-bear-scrutiny/scrutiny.yml
│   │   ├── big-bear-dockge/dockge.yml
│   │   ├── big-bear-dockpeek/dockpeek.yml
│   │   └── glances-dashboard.yml
│   └── storage/
│       └── README.md
├── services/
│   ├── media/
│   │   ├── arr-suite.yml              # Sonarr, Radarr, Lidarr, Prowlarr, Bazarr, qBittorrent, Gluetun
│   │   ├── audiobookshelf/audiobookshelf.yml
│   │   ├── immich/immich.yml
│   │   ├── navidrome/navidrome.yml
│   │   ├── pinchflat/pinchflat.yml
│   │   ├── stremio/stremio.yml
│   │   └── swingmusic/swingmusic.yml
│   ├── productivity/
│   │   ├── nextcloud.yml              # Nextcloud, Collabora, Talk HPB, Redis, PostgreSQL
│   │   ├── big-bear-joplin/joplin.yml
│   │   ├── big-bear-linkwarden/linkwarden.yml
│   │   ├── big-bear-paperless-ngx/paperless.yml
│   │   ├── big-bear-wallos/wallos.yml
│   │   └── memos/memos.yml
│   ├── management/
│   │   ├── stacks.yml
│   │   ├── syncthing/syncthing.yml
│   │   └── searxng/searxng.yml
│   └── development/
│       ├── d-planeos-website.yml
│       ├── aptifolio.yml
│       └── aptifolio-dockge.yml
├── scripts/
│   └── export-all-compose.sh
├── docs/
│   ├── hardware-specs.md
│   ├── homelab-complete-journey.md
│   ├── docker-infrastructure.md
│   ├── network-security.md
│   ├── network-remote-access.md
│   ├── media-stack.md
│   ├── productivity-services.md
│   ├── nextcloud-optimization-guide.md
│   ├── homelab-dashboard-guide.md
│   ├── pangolin-infrastructure.md
│   ├── pangolin-deployment-guide.md
│   ├── pangolin-configurations.md
│   ├── pangolin-vps-relay-guide.md
│   ├── pangolin-upgrade-guide.md
│   ├── pangolin-z-performance-tuning.md
│   ├── pangolin-traefikdashboard-guide.md
│   ├── NIXOS-MIGRATION.md
│   ├── DOCKER-SERVICES.md
│   ├── INDEX.md
│   └── *.html               # Interactive architecture diagrams
├── docker/                  # Legacy source tree — see docker/README.md
├── .env.example             # All required environment variables
└── README.md

Tech stack

Layer Technology
Operating system NixOS — declarative, reproducible, atomic OTA
NAS management D-PlaneOS (self-developed) — ZFS pool management, SMB/NFS, Docker orchestration, web UI
Container orchestration Docker Compose
Reverse proxy Traefik v3 — TLS 1.3, automatic Let's Encrypt
Tunnel Pangolin — self-hosted WireGuard
Security CrowdSec IDS/IPS
DNS Pi-hole
Storage OpenZFS RAID-Z2 (target) — migrating from BTRFS on mdadm RAID5 — 33 TB
Databases PostgreSQL 14 (×8 instances), Redis Alpine (×3 instances)
Hardware Intel i3-13100 / 32 GB DDR4-3200 / 120 GB NVMe
VPS gateway IONOS Berlin — 2 vCPU / 2 GB / 80 GB NVMe

Cost analysis

Initial investment
  Hardware            €1,290
  VPS (3 yr)            €180
  Domain (3 yr)          €36
  ────────────────────────────
  Total               €1,506

Annual operating cost
  Electricity           €75    (~30 W average, €0.30/kWh)
  VPS                   €60
  Domain                €12
  ────────────────────────────
  Total                €147/yr  (€12/month)

Replaced SaaS (annual)
  Google One            €30
  Dropbox Plus         €120
  1Password             €60
  Spotify              €180
  Netflix              €156
  iCloud+               €36
  ────────────────────────────
  Total replaced       €582/yr

Net savings: €435/yr → break-even Year 4

Documentation

Document Description
Why D-PlaneOS ZimaOS limitations, alternatives considered, what D-PlaneOS solves
Complete Journey Full build narrative, decisions, and lessons learned
Hardware Specs Component list, benchmarks, power draw
Docker Infrastructure Container architecture and patterns
Network Security Security layer detail
Remote Access VPN comparison, Pangolin vs Tailscale vs ZeroTier
Pangolin Infrastructure Tunnel architecture deep-dive
Pangolin Deployment Guide Step-by-step VPS setup
Pangolin Configurations Config file reference
Pangolin VPS Relay Relay server setup
Pangolin Upgrade Guide Version upgrade procedures
Pangolin Performance Tuning Kernel sysctl optimisations
Pangolin Traefik Dashboard Dashboard configuration
Media Stack Arr suite + Emby configuration
Productivity Services Nextcloud, Immich, Paperless setup
Nextcloud Optimisation PostgreSQL + Redis + PHP tuning
Dashboard Guide Homelab dashboard setup
NixOS Migration Plan ZimaOS → NixOS migration roadmap
Service Index Full service inventory

Quick start

# Clone
git clone https://github.com/4nonX/homelab

# Set up environment variables
cp .env.example .env
$EDITOR .env   # fill in domains, passwords, IPs

# Deploy a stack — example: Nextcloud
cd services/productivity
docker compose -f nextcloud.yml up -d

# Deploy monitoring
cd infrastructure/monitoring
docker compose -f glances-dashboard.yml up -d

For the full external access setup (Pangolin tunnel + Traefik + CrowdSec on VPS), start with docs/pangolin-deployment-guide.md.


Built on the shoulders of giants

This homelab would not exist without these projects. Each one is worth knowing about.


🥇 Pangolin — the backbone of external access

Pangolin

The single most impactful piece of infrastructure in this stack. Pangolin is a self-hosted tunnelled reverse proxy with identity and access management — think Cloudflare Tunnel, but open source and entirely under your control.

Before Pangolin, the realistic options for external access were: open ports on your home router (bad), pay for a commercial tunnel (fine but a dependency), or set up WireGuard manually and manage it yourself (works, but significant operational overhead). Pangolin wraps WireGuard, Traefik, and an identity layer into something you can actually run on a cheap VPS and forget about. Zero port-forwarding. Zero home IP exposure. Let's Encrypt certificates handled automatically. The security architecture of this entire homelab is built around what Pangolin makes possible.

Components: Pangolin (control plane) · Gerbil (WireGuard gateway) · Newt (tunnel client) · Badger (identity)

If you self-host anything that needs external access, start here.


🗄️ D-PlaneOS — the NAS management layer (self-developed)

D-PlaneOS

A NAS management layer I built myself — ZFS pool management, SMB/NFS shares, Docker orchestration, user management, and a unified web UI, purpose-built on top of NixOS. Developed specifically to fill the gap between CasaOS (simple but limited) and TrueNAS (powerful but container-hostile). The homelab you're looking at is its production testing environment. See docs/why-d-planeos.md.


🐳 Core infrastructure

Project Role in this stack
NixOS The OS everything runs on. Declarative system configuration, atomic rollbacks, reproducible builds — the base that makes the whole stack manageable. D-PlaneOS runs on top of it.
Traefik Reverse proxy — TLS termination, automatic Let's Encrypt, routing. Runs on the VPS and handles every inbound HTTPS request.
CrowdSec Collaborative IDS/IPS. Analyses Traefik logs, bans malicious IPs via bouncer, pulls community threat feeds. The passive security layer that works without any configuration after setup.
Pi-hole Network-wide DNS and ad-blocking. Every device on the LAN benefits without any per-device configuration.
OpenZFS The filesystem everything is migrating to. End-to-end checksumming, RAID-Z2, snapshots, zfs send replication — the right foundation for a long-lived NAS.

📦 Services

Project What it replaces
Nextcloud Google Drive, Google Docs, iCloud
Immich Google Photos
Vaultwarden 1Password, LastPass
Paperless-NGX Manual document filing
Emby Netflix, Plex (self-hosted media server)
Sonarr Radarr Lidarr Manual media management
Prowlarr Per-client indexer configuration
Bazarr Manual subtitle hunting
Gluetun Any VPN client — containerised, provider-agnostic WireGuard gateway
Syncthing Dropbox, rsync scripts
Dockge Manual docker compose commands
Scrutiny Ignoring disk health until something fails
SearXNG Google, Bing
Audiobookshelf Audible, podcast apps
Navidrome Spotify (self-hosted music streaming)
SwingMusic Local music player apps
Pinchflat YouTube Premium downloads
Linkwarden Browser bookmarks, Pocket
Memos Notion, Apple Notes
Wallos Manual subscription tracking
Glances Scattered system monitoring tools
Joplin Evernote, Apple Notes (sync backend)

D-PlaneOS Pangolin