docs: add full homelab documentation structure
This commit is contained in:
107
docs/architecture/ARCHITECTURE_OVERVIEW.md
Normal file
107
docs/architecture/ARCHITECTURE_OVERVIEW.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Homelab Architecture Overview
|
||||
|
||||
## Primary Docker Host
|
||||
Host: `PlausibleDeniability` (TrueNAS Scale)
|
||||
|
||||
Production Docker workloads run on PlausibleDeniability via standalone Docker Compose stacks.
|
||||
TrueNAS Apps (ix-app format) have been fully migrated to compose stacks.
|
||||
|
||||
## Repository Layout
|
||||
Repo root: `/mnt/docker-ssd/docker/compose`
|
||||
Remote: `git@github.com:Paccoco/truenas-stacks.git`
|
||||
Gitea mirror: `https://gitea.paccoco.com/fizzlepoof/truenas-stacks.git`
|
||||
|
||||
Stack directories:
|
||||
- `databases/` = shared-postgres, shared-mariadb, shared-redis — deploy FIRST
|
||||
- `infrastructure/` = newt, homepage, uptime-kuma, dockhand, netdata, tailscale — deploy SECOND
|
||||
- `media/` = plex, tautulli, audiobookshelf, seerr, calibre-web-automated
|
||||
- `photos/` = immich server + machine learning
|
||||
- `home/` = kitchenowl, donetick, dakboard bridge, shlink, shlink-web-client, qui
|
||||
- `dev/` = gitea, rackpeek
|
||||
- `ai/` = ollama, openwebui
|
||||
- `meshtastic/` = meshmonitor, mqtt-proxy, tileserver, meshtastic-map
|
||||
|
||||
## Storage Model
|
||||
|
||||
### Local SSD
|
||||
Mounted at: `/mnt/docker-ssd`
|
||||
- Docker data root: `/mnt/docker-ssd/docker/docker-data`
|
||||
- Databases: `/mnt/docker-ssd/docker/databases/`
|
||||
- Write-heavy appdata: `/mnt/docker-ssd/docker/appdata/`
|
||||
- GPU/model storage
|
||||
- Apps that perform chown or aggressive startup writes
|
||||
- SQLite-backed apps
|
||||
|
||||
Notable appdata on SSD:
|
||||
- plex, tautulli, audiobookshelf, seerr, dockhand, rackpeek
|
||||
- immich, immich-ml, ollama, openwebui
|
||||
- shlink, gitea, netdata, tailscale, uptime-kuma
|
||||
|
||||
### TrueNAS Pool (tank)
|
||||
Mounted at: `/mnt/tank`
|
||||
- General appdata: `/mnt/tank/docker/appdata/`
|
||||
- Backups: `/mnt/tank/docker/backups/`
|
||||
- Downloads: `/mnt/tank/docker/downloads/`
|
||||
|
||||
Notable appdata on tank:
|
||||
- homepage, newt, dockhand (config only)
|
||||
- kitchenowl, donetick, qui
|
||||
- calibre-web-automated config
|
||||
|
||||
### Unraid NFS
|
||||
Mounted at: `/mnt/unraid`
|
||||
- Media libraries: `/mnt/unraid/data/media/`
|
||||
- Immich media: `/mnt/unraid/immich`
|
||||
|
||||
## Networks
|
||||
- `ix-databases_shared-databases` — created by databases stack; project name `ix-databases` set in compose
|
||||
- `pangolin` — created by newt at runtime; used by all externally exposed services
|
||||
|
||||
## Active Stacks (as of 2026-05-05)
|
||||
|
||||
### databases/
|
||||
- shared-postgres (immich-optimized image with vectorchord + pgvector)
|
||||
- shared-mariadb
|
||||
- shared-redis
|
||||
|
||||
### infrastructure/
|
||||
- newt, homepage, dockhand, uptime-kuma, netdata, tailscale
|
||||
|
||||
### media/
|
||||
- ix-plex-plex-1 (GPU passthrough, RTX 2080 Ti)
|
||||
- ix-tautulli-tautulli-1
|
||||
- ix-audiobookshelf-audiobookshelf-1
|
||||
- seerr (Postgres backend)
|
||||
- calibre-web-automated
|
||||
|
||||
### photos/
|
||||
- ix-immich-immich-server-1
|
||||
- ix-immich-immich-machine-learning-1 (GPU, CUDA)
|
||||
|
||||
### home/
|
||||
- kitchenowl, donetick, donetick-dakboard-bridge, qui, shlink, shlink-web-client
|
||||
|
||||
### dev/
|
||||
- gitea, ix-rackpeek-rackpeek-1
|
||||
|
||||
### ai/
|
||||
- ollama (GPU, RTX 2080 Ti, port 11434)
|
||||
- openwebui (Postgres backend, port 8282)
|
||||
|
||||
### meshtastic/
|
||||
- meshmonitor, meshmonitor-mqtt-proxy, meshmonitor-tileserver, meshtastic-map
|
||||
|
||||
## Planned / Not Yet Deployed
|
||||
- dispatcharr, gotify, bytestash, kima-hub, n8n, qdrant, paperless-ngx, home-assistant
|
||||
|
||||
## Shelved
|
||||
- scriberr — SQLite incompatible with ZFS nfsv4 ACLs
|
||||
|
||||
## Design Principles
|
||||
- deterministic storage paths
|
||||
- no anonymous volumes
|
||||
- stack-local .env for secrets; .env.example committed with placeholders
|
||||
- SSD for write-heavy / DB / SQLite / GPU workloads
|
||||
- tank NFS for general appdata and configs
|
||||
- Unraid NFS for media only
|
||||
- databases stack uses `name: ix-databases` to maintain network name compatibility
|
||||
77
docs/architecture/HARDWARE_INVENTORY.md
Normal file
77
docs/architecture/HARDWARE_INVENTORY.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Hardware Inventory
|
||||
|
||||
## Serenity (NAS / Media Ingestion)
|
||||
- **OS:** Unraid 7.2.4
|
||||
- **IP:** 10.5.1.5 | Tailscale: 100.94.87.79
|
||||
- **CPU:** Xeon X5690
|
||||
- **RAM:** 102GB
|
||||
- **GPU:** None (Matrox IPMI only)
|
||||
- **UPS:** None
|
||||
|
||||
### Storage
|
||||
| Pool | Type | Drives | Usable | Notes |
|
||||
|------|------|--------|--------|-------|
|
||||
| malcolm | RAIDZ1 | 6× 10TB HDD | ~40TB | Heavily utilized |
|
||||
| cache | ZFS single | 1× Kingston SNV2S 1TB NVMe | ~1TB | Appdata/Docker |
|
||||
|
||||
### Key Shares
|
||||
| Share | Size | Purpose |
|
||||
|-------|------|---------|
|
||||
| data | 35TB | Media library |
|
||||
| immich | 62GB | Immich photo storage |
|
||||
| nextcloud | 7.4GB | Nextcloud data |
|
||||
| Tesla/dashcam | 1.6TB | Dashcam footage |
|
||||
| fizzlebang | 17GB | Personal files |
|
||||
| isos | 22GB | ISO images |
|
||||
| Syncthing | 4.6GB | Syncthing data |
|
||||
| manndra | — | Partner's storage |
|
||||
| Long and Low Crafts | — | Crafts business |
|
||||
| zfs_backups_array | — | ZFS backup target |
|
||||
|
||||
---
|
||||
|
||||
## PlausibleDeniability (Primary Docker Host)
|
||||
- **OS:** TrueNAS Scale 25.10.2.1
|
||||
- **CPU:** Ryzen 9 3950X
|
||||
- **RAM:** 32GB
|
||||
- **GPU:** Nvidia RTX 2080 Ti (11GB VRAM) — Plex, Immich ML, Ollama
|
||||
- **UPS:** None
|
||||
|
||||
### Storage
|
||||
| Pool | Type | Mount | Notes |
|
||||
|------|------|-------|-------|
|
||||
| tank | ZFS mirror (2 drives) | `/mnt/tank` | ~3.5TB usable |
|
||||
| docker-ssd | Single Crucial MX500 500GB | `/mnt/docker-ssd` | No redundancy |
|
||||
| boot-pool | Single sdc3 | — | TrueNAS boot |
|
||||
|
||||
### NFS Mounts
|
||||
- Serenity data array → `/mnt/unraid/data`
|
||||
|
||||
---
|
||||
|
||||
## N.O.M.A.D. (Offline Knowledge + Game Servers)
|
||||
- **OS:** Ubuntu 25.10 (bare metal)
|
||||
- **IP:** 10.5.1.16
|
||||
- **CPU:** Intel Core i7-4770K @ 3.50GHz (4c/8t, up to 3.9GHz)
|
||||
- **RAM:** 32GB DDR3 1600MHz (4×8GB)
|
||||
- **GPU:** NVIDIA GeForce GTX 1080 (8GB VRAM)
|
||||
- **NIC:** Intel I218-V (1GbE) + Aquantia AQC113 (10GbE)
|
||||
- **Motherboard:** ASRock H97M Pro4
|
||||
- **UPS:** None
|
||||
|
||||
### Storage
|
||||
| Device | Size | Mount | Purpose |
|
||||
|--------|------|-------|---------|
|
||||
| Samsung SSD 840 (sdb) | 232.9GB | `/` (LVM 100GB) | OS boot |
|
||||
| WD Red HDD (sda) | 3.6TB | `/mnt/hdd-1` | Primary data, project-nomad symlink |
|
||||
| WD Red HDD (sdc) | 3.6TB | `/mnt/hdd-2` | Docker data-root |
|
||||
| Seagate SSD (sdd) | 223.6GB | `/mnt/ssd-1` | Fast scratch |
|
||||
|
||||
---
|
||||
|
||||
## Desktop: ROCINANTE
|
||||
- **OS:** Windows 11 Pro
|
||||
- **CPU:** Ryzen 7 9850X3D
|
||||
- **RAM:** 64GB
|
||||
- **GPU:** RTX 4090 (24GB VRAM)
|
||||
- **Role:** Heavy AI inference, local Ollama (expose via `OLLAMA_HOST=0.0.0.0`)
|
||||
56
docs/architecture/NETWORKING_MODEL.md
Normal file
56
docs/architecture/NETWORKING_MODEL.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Homelab Networking Model
|
||||
|
||||
## Physical Network
|
||||
- **Gear:** Unifi throughout
|
||||
- **Main LAN:** 10.5.1.x (Trusted VLAN)
|
||||
- **Other VLANs:** Cameras, Guest, IoT
|
||||
- **Serenity IP:** 10.5.1.5
|
||||
- **N.O.M.A.D. IP:** 10.5.1.16
|
||||
- **PlausibleDeniability:** DHCP on LAN
|
||||
|
||||
## Remote Access
|
||||
- **Pangolin VPS + Newt:** Services exposed as subdomains via reverse proxy. Newt agents run on PD and N.O.M.A.D.
|
||||
- **Tailscale:** Personal remote access, runs on Serenity (100.94.87.79)
|
||||
- **Cloudflared:** No longer used. Dead container on Serenity to be removed.
|
||||
|
||||
## DNS
|
||||
- **Provider:** Cloudflare
|
||||
- All public subdomains point at Pangolin VPS IP
|
||||
|
||||
## Known Public Subdomains
|
||||
- `paccoco.com` → Pangolin VPS
|
||||
- `panel.paccoco.com` → Pelican Panel (N.O.M.A.D.)
|
||||
- `node1.paccoco.com` → Wings daemon (N.O.M.A.D., no auth)
|
||||
- `meshmonitor.paccoco.com` → Meshmonitor (PD)
|
||||
- `gitea.paccoco.com` → Gitea (PD)
|
||||
- `ai.paccoco.com` → OpenWebUI (PD) — DNS/Pangolin resource pending
|
||||
|
||||
## Docker Networking (PlausibleDeniability)
|
||||
|
||||
### ix-databases_shared-databases
|
||||
Created by the `databases` stack. The databases compose file uses `name: ix-databases` so Docker names the network `ix-databases_shared-databases`, matching what all other stacks declare as external.
|
||||
|
||||
Any stack connecting to shared-postgres, shared-mariadb, or shared-redis must declare:
|
||||
```yaml
|
||||
networks:
|
||||
ix-databases_shared-databases:
|
||||
external: true
|
||||
```
|
||||
|
||||
### pangolin
|
||||
Created at runtime by the `newt` container in the infrastructure stack. Any service needing reverse-proxy exposure must declare:
|
||||
```yaml
|
||||
networks:
|
||||
pangolin:
|
||||
external: true
|
||||
```
|
||||
|
||||
### Internal Service Model
|
||||
Internal services run HTTP only behind the reverse proxy. Compose service names used for internal DNS between services in the same stack/network.
|
||||
|
||||
## N.O.M.A.D. Networking Notes
|
||||
- `panel.paccoco.com` added to `/etc/hosts` → `127.0.0.1` for NAT loopback
|
||||
- nginx listens on 80 and 443 (self-signed cert) for Wings → Panel communication
|
||||
- Wings uses `--ignore-certificate-errors` for local loopback
|
||||
- Pangolin resource `node1.paccoco.com` has auth disabled (Wings handles its own auth)
|
||||
- Minecraft port 25565 TCP/UDP goes directly via home router port forward, not through Pangolin
|
||||
103
docs/architecture/SERVICES_DIRECTORY.md
Normal file
103
docs/architecture/SERVICES_DIRECTORY.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Services Directory
|
||||
|
||||
All running services across the homelab with ports, URLs, and backend info.
|
||||
|
||||
## PlausibleDeniability
|
||||
|
||||
### Databases (internal only)
|
||||
| Service | Port | Backend | Notes |
|
||||
|---------|------|---------|-------|
|
||||
| shared-postgres | 5432 | — | immich-optimized, vectorchord + pgvector |
|
||||
| shared-mariadb | 3306 | — | |
|
||||
| shared-redis | 6379 | — | |
|
||||
|
||||
### Infrastructure
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| newt | — | — | Pangolin reverse proxy agent |
|
||||
| homepage | — | — | Dashboard |
|
||||
| dockhand | — | — | Container management |
|
||||
| uptime-kuma | — | — | MariaDB backend |
|
||||
| netdata | — | — | Metrics |
|
||||
| tailscale | — | — | VPN |
|
||||
|
||||
### Media
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| plex | — | — | GPU passthrough, RTX 2080 Ti |
|
||||
| tautulli | — | — | Plex analytics |
|
||||
| audiobookshelf | — | — | Audiobooks |
|
||||
| seerr | — | — | Postgres backend |
|
||||
| calibre-web-automated | — | — | Ebooks |
|
||||
|
||||
### Photos
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| immich-server | — | — | Postgres + Redis, GPU |
|
||||
| immich-ml | — | — | GPU, CUDA |
|
||||
|
||||
### Home
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| kitchenowl | — | — | Grocery/tasks |
|
||||
| donetick | — | — | Postgres backend, selfhosted.yaml required |
|
||||
| shlink | — | — | URL shortener, Postgres |
|
||||
| shlink-web-client | — | — | |
|
||||
| qui | — | — | qBittorrent UI, manages Serenity remotely |
|
||||
|
||||
### Dev
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| gitea | — | gitea.paccoco.com | Postgres backend |
|
||||
| rackpeek | — | — | |
|
||||
|
||||
### AI
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| ollama | 11434 | — | GPU, RTX 2080 Ti |
|
||||
| openwebui | 8282→8080 | ai.paccoco.com (pending) | Postgres backend |
|
||||
|
||||
### Meshtastic
|
||||
| Service | Internal Port | Public URL | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| meshmonitor | 8081→3001 | meshmonitor.paccoco.com | Postgres backend |
|
||||
| meshmonitor virtual node | 4404 | — | TCP virtual node server |
|
||||
| meshmonitor-tileserver | 8082→8080 | — | Map tiles |
|
||||
| meshmonitor-mqtt-proxy | — | — | MQTT→TCP bridge |
|
||||
|
||||
---
|
||||
|
||||
## Serenity
|
||||
|
||||
### Media Ingestion
|
||||
| Service | Notes |
|
||||
|---------|-------|
|
||||
| sonarr | TV |
|
||||
| sonarr-anime | Anime |
|
||||
| radarr | Movies |
|
||||
| lidarr | Music |
|
||||
| readarr | Books |
|
||||
| readarr-epub | EPUBs |
|
||||
| prowlarr | Indexer manager |
|
||||
| bazarr | Subtitles |
|
||||
| unpackerr | Archive extraction |
|
||||
| qBittorrent | Download client |
|
||||
| GluetunVPN | VPN tunnel for qbit |
|
||||
| autobrr | Auto-grab |
|
||||
| qbit_manage | qBit maintenance |
|
||||
| Notifiarr | Notifications |
|
||||
| Wizarr | User invites |
|
||||
| romm | ROM manager |
|
||||
| GameVault | Game library |
|
||||
| shelfmark | Book/audiobook search, port 8084 |
|
||||
|
||||
---
|
||||
|
||||
## N.O.M.A.D.
|
||||
|
||||
| Service | Port | Notes |
|
||||
|---------|------|-------|
|
||||
| Pelican Panel | 80/443 | panel.paccoco.com, PHP 8.4 + nginx + MariaDB |
|
||||
| Wings | 8443 | node1.paccoco.com, game server daemon |
|
||||
| Minecraft | 25565 | Purpur, Java 21, direct port forward |
|
||||
| N.O.M.A.D. containers | — | 10 containers, start_nomad.sh / stop_nomad.sh |
|
||||
Reference in New Issue
Block a user