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.com → 88.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>/ |