docs: dissolve Stacks chapter → infra/; reconcile portmap, storage, changelog (2026-05-21)
- Move PORTMAP, storage, volumes, docker-networks from stacks/ → infra/ - Remove stacks/todo.md (content migrated to CHANGELOG + ideas) - portmap: add new MCP servers (18005/07/09/10/11), fix s3.nuclide.systems entry, update Daytona OIDC row to DECOMMISSIONED, add Vaultwarden OIDC placeholder, add DevOps table row for MCP server Gitea repos - storage: add Garage S3 buckets subsection (lobe-files + chat-artifacts) - docker-networks: remove daytona-minimal_daytona-network row + daytona from "Stacks Keeping Own Networks" list - ct-inventory: add CT 112 (secrets/Infisical, planned) - CHANGELOG: prepend 2026-05-21 entry (docs, S3, MCP, dev env, Gitea repos, planned) - ideas/stack-ideas: add §11 Renovate Bot, §12 egress firewall, §13 local LLM - mkdocs.yml: replace nav — dissolve Stacks chapter, add infra/ entries
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Storage layout
|
||||
|
||||
> Verified state as of 2026-05-21. Source of truth for which service lives on which storage class.
|
||||
> Earlier revisions of this doc were stale on multiple items (Garage, n8n, Arcane, Karakeep, Pocket-ID, arr-stack, Nextcloud's storage protocol, missing Coder/Gitea). Reconciled via live audit.
|
||||
|
||||
## Storage classes
|
||||
|
||||
| Class | Substrate | Where | Typical use |
|
||||
|---|---|---|---|
|
||||
| Local zfs (rootfs) | NVMe in nuc | `/opt/stacks/<stack>/` on each LXC | Tier-1 hot state: databases, SQLite, secret stores, anything latency-sensitive |
|
||||
| Local zfs (subvol) | NVMe in nuc | `rpool/data/subvol-<NNN>-disk-0` per LXC | Container rootfs, image cache |
|
||||
| Docker named volume | NVMe in nuc | `/var/lib/docker/volumes/...` on each Docker CT | Per-container persistent state managed by Docker |
|
||||
| UNAS over **NFSv3** | `192.168.1.31` | `/mnt/pve/unas` on CTs 101, 103, 104, 111 | Bulk media, workspace home dirs, document storage |
|
||||
| UNAS over **CIFS/SMB 3.1.1** | `192.168.1.31` | `/mnt/pve/unas` on CT 105 (Nextcloud) | Nextcloud-only path — earlier docs mis-labelled this as NFS |
|
||||
|
||||
## What lives where (verified 2026-05-21)
|
||||
|
||||
### UNAS NFS — `/mnt/pve/unas/services/...`
|
||||
|
||||
Bulk + media + non-latency-sensitive app data.
|
||||
|
||||
| Service | CT | Path on UNAS → in container | Backed up? | Notes |
|
||||
|---|---|---|---|---|
|
||||
| Immich (uploads, thumbs, derived) | 104 | `services/immich/{encoded-video,profile,thumbs}` + `media/images` + `backup/immich` | Immich own pg_dump → `media/images/db-dumps`; no off-host copy | |
|
||||
| Paperless-ngx (documents) | 104 | `media/documents/public/paperless-ngx/{consume,export,library}` | none | |
|
||||
| Paperless-AI | 104 | `services/paperless-ai` → `/app/data` | none | |
|
||||
| Vaultwarden (attachments + SQLite DB) | 104 | `services/vaultwarden` → `/data` | none | tier-1 DB on NFS — risky, plan to move local |
|
||||
| Traccar (logs, config) | 104 | `services/traccar/{logs,traccar.xml}` | none | data dir reverted to local `/opt/stacks/traccar/data` |
|
||||
| Memos | 104 | `services/memos` → `/var/opt/memos` | none | |
|
||||
| Arr-stack (Audiobookshelf, Prowlarr, RDTClient, Shelfarr) + media | 104 | `services/arr-stack/*` + `media/{audiobooks,ebooks,podcasts,Torrents}` | none | already migrated (older doc claimed "still local") |
|
||||
| Gluetun (VPN) | 104 | `services/gluetun/data` → `/gluetun` | none | |
|
||||
| Gitea | 111 | `services/gitea` → `/data` | none | new 2026-05-20 |
|
||||
| Coder workspace home dirs | 111 | `services/coder/<user>/<workspace>` → `/home/<user>` | none | new 2026-05-20 |
|
||||
| Backrest's jottacloud-mirrored data | 103 | `media/data-dir` only | **rclone → jottacloud (Backrest)** | only path with off-host backup |
|
||||
|
||||
### Local zfs — `/opt/stacks/...`
|
||||
|
||||
Tier-1 state and anything that should NOT be NFS-backed.
|
||||
|
||||
| Service | CT | Local path → in container | Backed up? | Notes |
|
||||
|---|---|---|---|---|
|
||||
| Pocket-ID | **110** | `/opt/stacks/pocketid/data` → `/app/data` | none | CT 110 has no NFS mount at all. Earlier doc said UNAS — incorrect. |
|
||||
| Garage (S3 meta + data) | 104 | `/opt/stacks/shared-db/garage/{data,meta}` → `/var/lib/garage/*` | none | **moved off NFS** 2026-05-19 after WAL-G outage. Stale copy may still exist on UNAS. |
|
||||
| Shared Postgres (multi-stack) | 104 | docker named volume `shared-db_shared-pgdata` | **WAL-G → local Garage** (configured; outage 2026-05-19 prompted move) | Garage itself is single-disk local — no off-host copy. |
|
||||
| n8n | 104 | `/opt/stacks/n8n/data` → `/home/node/.n8n` | none | **back to local** after PG migration attempt failed. Stale 408 MB `database.sqlite` left on UNAS (May 15) — clean up. n8n now uses `shared-postgres` as its actual DB. |
|
||||
| Arcane | 104 | `/opt/stacks/arcane/data` → `/app/data` | none | reverted from UNAS to local 2026-05-19 (undocumented before now) |
|
||||
| Karakeep + Meilisearch | 104 | `/opt/stacks/karakeep/localdata/{data,meili}` | none | reverted from UNAS to local |
|
||||
| Immich Postgres (pgvector) | 104 | `/opt/stacks/immich/postgres` → `/var/lib/postgresql/data` | Immich pg_dump → UNAS | tier-1; PG demands local disk |
|
||||
| Homepage | 104 | `/opt/stacks/homepage/{config,icons}` | none | |
|
||||
| Dozzle | 104 | `/opt/stacks/dozzle/dozzle_data` | none | |
|
||||
| LiteLLM config | 104 | `/opt/stacks/ai/litellm-config` | none | |
|
||||
| SearXNG config | 104 | `/opt/stacks/ai/searxng` | none | |
|
||||
| Flaresolverr | 104 | `/var/lib/flaresolver` | none | |
|
||||
| AdGuard / Zoraxy / DNS / Shepard / Backrest binaries | 102/108/103/101 | local zfs only | none | Backrest itself has no self-backup |
|
||||
| Nextcloud config + sidecars | 105 | local zfs (CT rootfs) | none | data path is CIFS — see below |
|
||||
|
||||
### Garage S3 buckets (on local zfs, CT 104)
|
||||
|
||||
| Bucket | Access key | Use | Public URL |
|
||||
|---|---|---|---|
|
||||
| `lobe-files` | GK55210… (from `.env`) | LobeHub file uploads + WAL-G PG backups | internal only |
|
||||
| `chat-artifacts` | GK50bfc… | AI chat output artefacts (images, reports, SVG) | `https://chat-artifacts.s3.nuclide.systems/<key>` |
|
||||
|
||||
### Docker named volumes
|
||||
|
||||
Local on `/var/lib/docker/volumes/`. Mostly databases and caches.
|
||||
|
||||
| Volume | Service / CT | Backed up? |
|
||||
|---|---|---|
|
||||
| `shared-db_shared-pgdata` | shared-postgres / 104 | WAL-G → local Garage |
|
||||
| `paperless-ngx_pgdata`, `_redisdata`, `_data` | paperless-ngx / 104 | none |
|
||||
| `lobe-postgres` + `lobe-redis` | lobehub / 104 | none |
|
||||
| `nuc-ai-core_rustfs-data` | lobehub stack / 104 | none |
|
||||
| `pgadmin-data` | pgadmin / 104 | none (regenerable) |
|
||||
| `immich_model-cache` | immich-ml / 104 | regenerable |
|
||||
| `coder-db` + `gitea-db` (docker volume `coder-db`) | / 111 | none |
|
||||
| (orphaned) `daytona-minimal_db_data` + runner anon vol | / 104 | none — clean up post-decommission |
|
||||
|
||||
### Nextcloud (CT 105) — the CIFS outlier
|
||||
|
||||
Nextcloud AIO mounts `//192.168.1.31/storage` over **CIFS/SMB 3.1.1**, not NFS like every other CT. Application data path is under that mount. The Postgres + Redis sidecars stay on local docker volumes.
|
||||
|
||||
## Backup reality
|
||||
|
||||
**There is effectively no off-host backup of service data.** The only configured Backrest plan covers `/mnt/pve/unas/media/data-dir → jottacloud` — i.e., Backrest backs up *one specific UNAS path*, not the services that write to UNAS.
|
||||
|
||||
Coverage:
|
||||
|
||||
- Immich pg_dump → UNAS (same filer; survives container loss, not filer loss)
|
||||
- shared-postgres WAL-G → Garage (same host; survives container loss, not disk loss)
|
||||
- Everything else: zero
|
||||
|
||||
This is a known gap. Plans:
|
||||
1. Extend Backrest plans to snapshot tier-1 paths (Pocket-ID sqlite, Vaultwarden data, Gitea repos, Coder workspace homes) to jottacloud nightly.
|
||||
2. Once the second NVMe lands (see `infra/proxmox-state.md` §6), mirror `rpool` so a single disk death doesn't take everything.
|
||||
|
||||
## Drift cleanup TODO
|
||||
|
||||
- [ ] Remove stale `services/n8n/database.sqlite` (408 MB, last write 2026-05-15) from UNAS.
|
||||
- [ ] Remove stale `services/shared-db/garage/` copy from UNAS if present.
|
||||
- [ ] Remove orphaned `daytona-minimal_db_data` Docker volume on CT 104.
|
||||
- [ ] Vaultwarden `data/` on UNAS — plan to migrate to local zfs (latency + tier-1).
|
||||
- [ ] Add a Backrest plan for Pocket-ID DB and Gitea data → jottacloud.
|
||||
Reference in New Issue
Block a user