Skip to content

Nodes

Three nodes, one per role. Alias matches the SSH host and the Netbird mesh DNS name. All run Debian (trixie).

node hardware role runtime
pi-home Raspberry Pi 3B — 1 GB RAM, 4 cores; SD root (477 G) + 687 G HDD Vaultwarden, Radicale, Pi-hole/DNS, ntfy, beszel hub, filebrowser, syncthing, cloudflared ingress native systemd (no Docker)
vps-apps VPS — 8 GB RAM, 4 cores, one 75 G disk the app fleet: RomM, Dawarich, music pipeline, backrest, hermes agents, docs site Docker Compose
vps-net VPS — 1 GB RAM, 2 cores Netbird control plane ONLY (mgmt/signal/relay) Docker Compose, minimal

The repo lives at /opt/homelab on vps-apps only — the single node with an auto-sync timer (pull + push every 15 min). pi-home and vps-net have no clone. vps-net is the most critical node: if it goes down, remote access to all three nodes goes with it. Never add unrelated services to it.

pi-home

Native systemd units, no Docker. Units: vaultwarden, radicale, pihole-FTL + unbound (DNS on 53, mesh 5053), netbird, filebrowser, syncthing, cloudflared (token tunnel — the only public ingress), ntfy, pocket-id, hydroxide (ProtonMail bridge), telegram-bot, beszel-hub + beszel-agent-native, dietpi-dashboard, smbd/nmbd (homes/printers only), nfs-server (backups export), dropbear (sshd :27925), fail2ban, ufw.

Local forward shims (systemd-socket-proxyd) send cloudflared routes to vps-apps: 2fauth-fwd (localhost:8700 → vps-apps:8700), linkding-fwd (localhost:9090 → vps-apps:9090).

Storage: /mnt/pi-hdd (687 G HDD — the restic repo for both hosts) and /mnt/dietpi_userdata (app data root). /dev/sda (15 G) is raw and unconfigured.

vps-apps

Tracked compose projects (repo under vps-apps/<app>/): romm (+ db) · 8333, dawarich (app/sidekiq/db/redis/watchdog) · 3000, diun, musicload (+ gdrive-push) · 8000, backrest · 9898, docs · 8001, opencloud · 9200, webdav (rclone serve, pi-home HDD share) · 8085.

Untracked stacks under /opt/docker: metube 8881, dozzle 8080, uptime-kuma 3001, portainer 9000/9443, music-grabber 6666, shelfmark 8084, beets 8337, termix 8787, 2fauth 8700, calibre-web 8046, homepage 7575, bentopdf 8095, hermes + hermes-dashboard 8644/9119, hermes-webui 8788 (host-net local build), actual-budget 5006, livesync-couchdb 5984, hc-heartbeat, beszel-agent.

All published ports bind to 100.64.0.100 (mesh). Ingress to mesh-bound ports is via the Netbird mesh; public ingress goes through the cloudflared tunnel on pi-home — no Caddy and no nginx-proxy-manager run on any node.

Two tracked compose projects have no container: homeassistant (compose only) and caddy (compose only). navidrome is retired; compose + config remain.

vps-net

Netbird mgmt/signal/relay via vps-net/netbird compose; public vpn.jmrdez.com88.218.77.101. Not a Netbird peer — reached only over the wgr-vpsnet tunnel via pi-home (10.99.1.1:22).

Data roots

Every app keeps two trees per node: config (compose/units, committed) and data (state, backed up nightly). See data.md.

node config root data root
vps-apps /opt/homelab/vps-apps/<app>/ (tracked); /opt/docker/<app>/ (untracked) /opt/homelab-data/<app>/
vps-net /opt/homelab/vps-net/<app>/ /opt/homelab-data/<app>/
pi-home systemd units + /etc/<app>/ /mnt/dietpi_userdata/<app>/