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:
@@ -1,230 +0,0 @@
|
||||
# Port Map — NUC 14 Docker Stacks
|
||||
|
||||
> **Reverse proxy**: [Zoraxy v3.3.2](http://192.168.1.4:8000) on `192.168.1.4:8000` (LXC 108)
|
||||
> Wildcard cert `*.nuclide.systems` · source of truth: [`proxy/zoraxy/routes.json`](proxy/zoraxy/routes.json)
|
||||
> Manage routes: `uv run scripts/zoraxy_sync.py [--apply|--prune|--list]`
|
||||
|
||||
## Port Scheme
|
||||
|
||||
| Range | Category |
|
||||
|---|---|
|
||||
| 10000–10999 | Infrastructure |
|
||||
| 11000–11999 | Security & Auth |
|
||||
| 12000–12999 | Media – Immich |
|
||||
| 13000–13999 | Media – Downloads / Arr |
|
||||
| 14000–14999 | AI Stack |
|
||||
| 15000–15999 | Documents |
|
||||
| 16000–16999 | Automation |
|
||||
| 17000–17999 | Notes & Bookmarks |
|
||||
| 18000–18999 | DevOps / Image Gen |
|
||||
| 19000–19999 | Tracking |
|
||||
| 20000–20999 | Storage Admin |
|
||||
| 30000–30999 | VPN Control |
|
||||
|
||||
---
|
||||
|
||||
## Infrastructure (10000–10999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [10000](http://192.168.1.40:10000) | Homepage | `homepage` | — | Dashboard, LAN only |
|
||||
| [10001](http://192.168.1.40:10001) | Dozzle | `dozzle` | [dozzle.nuclide.systems](https://dozzle.nuclide.systems) | Log viewer |
|
||||
| [10002](http://192.168.1.40:10002) | Arcane | `arcane` | [arcane.nuclide.systems](https://arcane.nuclide.systems) | Web IDE |
|
||||
| [10003](http://192.168.1.40:10003) | Gotify | `gotify` | [gotify.nuclide.systems](https://gotify.nuclide.systems) | Push notifications |
|
||||
| [10004](http://192.168.1.40:10004) | Garage S3 API | `garage` | s3.nuclide.systems (non-responsive, see notes) | Internal: `http://garage:3900` |
|
||||
| 10005 (127.0.0.1 only) | Garage Admin | `garage` | — | localhost only |
|
||||
|
||||
---
|
||||
|
||||
## Security & Auth (11000–11999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [11001](http://192.168.1.40:11001) | Vaultwarden | `vaultwarden` | [vault.nuclide.systems](https://vault.nuclide.systems) | Password manager · **no Pocket-ID client yet — gap** |
|
||||
|
||||
> Pocket-ID **migrated from this CT to LXC 110** on 2026-05-20. See the [External Services](#external-services-not-on-nuc-docker) table below.
|
||||
|
||||
---
|
||||
|
||||
## Media – Immich (12000–12999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [12000](http://192.168.1.40:12000) | Immich | `immich_server` | [immich.nuclide.systems](https://immich.nuclide.systems) | Photos/videos |
|
||||
| — | Immich Power Tools | `immich_power_tools` | [immich-tools.nuclide.systems](https://immich-tools.nuclide.systems) | Container-internal :3000, Zoraxy proxy |
|
||||
|
||||
---
|
||||
|
||||
## Media – Downloads / Arr Stack (13000–13999)
|
||||
|
||||
All arr-stack services run behind `vpn_gluetun` container network.
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [13001](http://192.168.1.40:13001) | RDTClient | `rdtclient` | — | LAN only |
|
||||
| [13002](http://192.168.1.40:13002) | Prowlarr | `prowlarr` | — | LAN only |
|
||||
| [13003](http://192.168.1.40:13003) | Audiobookshelf | `audiobookshelf` | [abs.nuclide.systems](https://abs.nuclide.systems) | |
|
||||
| [13004](http://192.168.1.40:13004) | ShelfArr | `shelfarr` | — | LAN only |
|
||||
| [13005](http://192.168.1.40:13005) | Flaresolverr | `flaresolverr` | — | Internal only |
|
||||
| [30000](http://192.168.1.40:30000) | Gluetun VPN control | `vpn_gluetun` | — | HTTP control API |
|
||||
|
||||
---
|
||||
|
||||
## AI Stack (14000–14999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [14000](http://192.168.1.40:14000) | LiteLLM | `litellm` | [ai.nuclide.systems](https://ai.nuclide.systems) | LLM proxy gateway |
|
||||
| [14001](http://192.168.1.40:14001) | LobeHub | `lobehub` | [chat.nuclide.systems](https://chat.nuclide.systems) | Chat UI |
|
||||
| [14002](http://192.168.1.40:14002) | Qdrant | `qdrant_scientific` | — | Vector DB, internal only |
|
||||
| [8080](http://192.168.1.40:8080) | MCP Gateway | `mcp-gateway` | [mcp.nuclide.systems](https://mcp.nuclide.systems) | Pocket ID gated; spawns MCP servers on `ai-internal` |
|
||||
| [18002](http://192.168.1.40:18002) | ComfyUI | `comfyui` | — | LAN only (Intel Arc iGPU, FLUX.1-schnell GGUF) |
|
||||
| [18003](http://192.168.1.40:18003) | ComfyUI MCP | `comfyui-mcp` | — | FastMCP; reachable via gateway at `mcp.nuclide.systems/comfyui/mcp` |
|
||||
| — | SearXNG | `searxng` | — | Internal, `shared_backend`, used by LobeHub |
|
||||
|
||||
---
|
||||
|
||||
## Documents (15000–15999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [15000](http://192.168.1.40:15000) | Traccar HTTP | `traccar` | [traccar.nuclide.systems](https://traccar.nuclide.systems) | GPS tracking UI |
|
||||
| [15001](http://192.168.1.40:15001) | Traccar GPS | `traccar` | — | TCP+UDP watch protocol |
|
||||
| [15002](http://192.168.1.40:15002) | Paperless AI | `paperless-ai` | [paperless-ai.nuclide.systems](https://paperless-ai.nuclide.systems) | Internal-only Zoraxy policy |
|
||||
| [15003](http://192.168.1.40:15003) | Paperless-ngx | `paperless-ngx-webserver-1` | [paperless.nuclide.systems](https://paperless.nuclide.systems) | Internal-only Zoraxy policy |
|
||||
|
||||
---
|
||||
|
||||
## Automation (16000–16999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [16000](http://192.168.1.40:16000) | n8n | `n8n` | [n8n.nuclide.systems](https://n8n.nuclide.systems) | Workflow automation |
|
||||
|
||||
---
|
||||
|
||||
## Notes & Bookmarks (17000–17999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [17000](http://192.168.1.40:17000) | Memos | `memos` | [memos.nuclide.systems](https://memos.nuclide.systems) | Notes |
|
||||
| [17001](http://192.168.1.40:17001) | Karakeep | `karakeep` | [hoarder.nuclide.systems](https://hoarder.nuclide.systems) | Bookmarks |
|
||||
|
||||
---
|
||||
|
||||
## DevOps (18000–18999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
<!-- Daytona DECOMMISSIONED 2026-05-20; replaced by Coder on CT 111. Compose renamed *.DECOMMISSIONED-2026-05-20. -->
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Tracking (19000–19999)
|
||||
|
||||
_Traccar moved to 15000–15001 (Documents range). 19000–19001 now free._
|
||||
|
||||
---
|
||||
|
||||
## Storage Admin (20000–20999)
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| 20010 (127.0.0.1 only) | pgAdmin | `pgadmin` | — | localhost only |
|
||||
|
||||
---
|
||||
|
||||
## LXC 111 — Dev (`192.168.1.42`)
|
||||
|
||||
CT 111 hosts the self-hosted dev platform. Same Pocket-ID SSO as the rest.
|
||||
|
||||
| Port | Service | Container | Public URL | Notes |
|
||||
|---|---|---|---|---|
|
||||
| [7080](http://192.168.1.42:7080) | Coder | `coder` | [dev.nuclide.systems](https://dev.nuclide.systems) | Workspace orchestrator; OIDC via Pocket-ID; password auth disabled |
|
||||
| [3000](http://192.168.1.42:3000) | Gitea | `gitea` | [git.nuclide.systems](https://git.nuclide.systems) | Self-hosted Git; OIDC; password form disabled |
|
||||
| [222](http://192.168.1.42:222) | Gitea SSH | `gitea` | — | `ssh -p 222 git@git.nuclide.systems` |
|
||||
| 5432 (internal) | coder-db | `coder-db` | — | Postgres 16 for Coder |
|
||||
| 5432 (internal) | gitea-db | `gitea-db` | — | Postgres 16 for Gitea |
|
||||
| [13080](http://192.168.1.42:13080) | docs site | `docs-server` | — (LAN-only) | mkdocs Material; auto-rebuilds from `fkrebs/docs` every 5 min |
|
||||
| (no port) | coder-fkrebs-dev | (workspace) | (Coder app proxy) | Active Coder workspace |
|
||||
| (no port) | act-runner | `act-runner` | — | Gitea Actions runner (`ct111-runner`) |
|
||||
|
||||
---
|
||||
|
||||
## External Services (Not on NUC Docker)
|
||||
|
||||
Zoraxy routes to these external backends:
|
||||
|
||||
| Domain | Target | Host | Service |
|
||||
|---|---|---|---|
|
||||
| [ha.nuclide.systems](https://ha.nuclide.systems) | `192.168.1.60:8123` | Home Assistant VM 100 | Home automation |
|
||||
| [nc.nuclide.systems](https://nc.nuclide.systems) | `192.168.1.41:11000` | Nextcloud LXC 105 | Cloud storage |
|
||||
| [ocpp.nuclide.systems](https://ocpp.nuclide.systems) | `192.168.1.60:8887` | Home Assistant VM 100 | EV charger OCPP |
|
||||
| [shepard.nuclide.systems](https://shepard.nuclide.systems) | `192.168.1.49:80` | Shepard LXC 101 | Shepard |
|
||||
| [shepard-api.nuclide.systems](https://shepard-api.nuclide.systems) | `192.168.1.49:8080` | Shepard LXC 101 | Shepard API |
|
||||
| [id.nuclide.systems](https://id.nuclide.systems) | `192.168.1.5:11000` | Pocket-ID LXC 110 | OIDC IdP (migrated 2026-05-20) |
|
||||
| [git.nuclide.systems](https://git.nuclide.systems) | `192.168.1.42:3000` | Dev LXC 111 | Gitea (self-hosted Git) |
|
||||
| [dev.nuclide.systems](https://dev.nuclide.systems) | `192.168.1.42:7080` | Dev LXC 111 | Coder (workspace orchestrator) |
|
||||
| Gitea SSH | `192.168.1.42:222` | Dev LXC 111 | `ssh -p 222 git@git.nuclide.systems` |
|
||||
|
||||
---
|
||||
|
||||
## Zoraxy Public Routes (proxied via `192.168.1.4`)
|
||||
|
||||
| Domain | Backend (NUC `192.168.1.40`) | Port |
|
||||
|---|---|---|
|
||||
| [ai.nuclide.systems](https://ai.nuclide.systems) | litellm | 14000 |
|
||||
| [chat.nuclide.systems](https://chat.nuclide.systems) | lobehub | 14001 |
|
||||
| [mcp.nuclide.systems](https://mcp.nuclide.systems) | mcp-gateway | 8080 |
|
||||
| [arcane.nuclide.systems](https://arcane.nuclide.systems) | arcane | 10002 |
|
||||
| [gotify.nuclide.systems](https://gotify.nuclide.systems) | gotify | 10003 |
|
||||
| [vault.nuclide.systems](https://vault.nuclide.systems) | vaultwarden | 11001 |
|
||||
| [immich.nuclide.systems](https://immich.nuclide.systems) | immich_server | 12000 |
|
||||
| [immich-tools.nuclide.systems](https://immich-tools.nuclide.systems) | immich_power_tools | (container-internal) |
|
||||
| [abs.nuclide.systems](https://abs.nuclide.systems) | audiobookshelf | 13003 |
|
||||
| [n8n.nuclide.systems](https://n8n.nuclide.systems) | n8n | 16000 |
|
||||
| [memos.nuclide.systems](https://memos.nuclide.systems) | memos | 17000 |
|
||||
| [hoarder.nuclide.systems](https://hoarder.nuclide.systems) | karakeep | 17001 |
|
||||
| [traccar.nuclide.systems](https://traccar.nuclide.systems) | traccar | 15000 |
|
||||
| [dozzle.nuclide.systems](https://dozzle.nuclide.systems) | dozzle | 10001 |
|
||||
|
||||
**Not publicly proxied** (LAN / localhost only): pgadmin, paperless, paperless-ai, comfyui, comfyui-mcp, rdtclient, prowlarr, shelfarr, qdrant.
|
||||
|
||||
---
|
||||
|
||||
## Known Issues
|
||||
|
||||
- **`s3.nuclide.systems`** (Garage external S3): non-responsive. Internal S3 `http://garage:3900` works fine for wal-g, memos, lobe. External binding risks quorum loss — deferred.
|
||||
- **`lobe-postgres` / `lobe-redis`**: host-port exposed (`0.0.0.0:5432/6379`) — firewall blocks external access but ideally restricted to localhost.
|
||||
|
||||
---
|
||||
|
||||
## OIDC Client Registry (Pocket ID — `id.nuclide.systems`)
|
||||
|
||||
| Client ID | Name | Redirect URIs |
|
||||
|---|---|---|
|
||||
| `e73bb7b9` | litellm | (empty = accept all) — used by LiteLLM UI + MCP Gateway |
|
||||
| `26f3c26b` | lobehub | `https://chat.nuclide.systems/api/auth/callback/generic-oidc` |
|
||||
| `81cf4ed0` | arcane | `https://arcane.nuclide.systems/auth/oidc/callback` |
|
||||
| `33135ad4` | n8n | `https://n8n.nuclide.systems/auth/oidc/callback` |
|
||||
| `9c91c18b` | immich | `https://immich.nuclide.systems/auth/login` + mobile |
|
||||
| `62bf4e0d` | memos | `https://memos.nuclide.systems/auth/callback` |
|
||||
| `d92f82b0` | karakeep | `https://hoarder.nuclide.systems/api/auth/callback/custom` |
|
||||
| `a14b8076` | nextcloud | `https://nc.nuclide.systems/apps/user_oidc/code` |
|
||||
| `0aee4280` | Coder | `https://dev.nuclide.systems/api/v2/users/oidc/callback` |
|
||||
| `9444609e` | Gitea | `https://git.nuclide.systems/user/oauth2/pocket-id/callback` |
|
||||
| `38469e7e` | Proxmox VE | `https://192.168.1.20:8006` |
|
||||
| `798a367f` | ~~daytona~~ | **ORPHAN — Daytona decommissioned 2026-05-20, remove** |
|
||||
| `cbbf20d5` | Audiobookshelf | `https://abs.nuclide.systems/…` + `*` |
|
||||
| `d8733fcc` | shelfarr | `*` |
|
||||
| `78c78998` | Claude MCP | `https://claude.ai/api/mcp/auth_callback` + `https://mcp.nuclide.systems/mcp/auth/callback` |
|
||||
| `82ca2d53` | nuc-ai | (empty) — used by spawned MCP servers |
|
||||
| `7fe1a14b` | zoraxy | (empty) |
|
||||
| `af2f837b` | mcp-auth | (empty) — legacy, unused |
|
||||
|
||||
**OIDC Endpoints** (corrected 2026-05-17 — previously used wrong `/api/v1/oauth2/` path):
|
||||
- Authorization: `https://id.nuclide.systems/authorize`
|
||||
- Token: `https://id.nuclide.systems/api/oidc/token`
|
||||
- Userinfo: `https://id.nuclide.systems/api/oidc/userinfo`
|
||||
- Discovery: `https://id.nuclide.systems/.well-known/openid-configuration`
|
||||
@@ -1,129 +0,0 @@
|
||||
# Docker Networks
|
||||
|
||||
## Current Landscape (May 16, 2026)
|
||||
|
||||
Each Docker Compose stack creates its own `{stack}_default` bridge network when it
|
||||
has no explicit `networks:` declaration. This has exhausted Docker's built-in
|
||||
172.x.x.x/16 address pool, triggering CIDR overlap errors.
|
||||
|
||||
### Networks & Subnets
|
||||
|
||||
| Network | Subnet | Containers |
|
||||
|---|---|---|
|
||||
| `bridge` (built-in) | 10.0.0.0/24 | 0 |
|
||||
| `ai-internal` | 172.31.0.0/16 | 8 |
|
||||
| `arcane_default` | 172.22.0.0/16 | 1 |
|
||||
| `arr-stack_default` | 172.21.0.0/16 | 4 |
|
||||
| `daytona-minimal_daytona-network` | 172.23.0.0/16 | 4 |
|
||||
| `dozzle_default` | 192.168.16.0/20 | 1 |
|
||||
| `homepage_default` | 172.19.0.0/16 | 1 |
|
||||
| `immich_default` | 172.18.0.0/16 | 5 |
|
||||
| `karakeep_default` | 172.30.0.0/16 | 3 |
|
||||
| `memos_default` | 192.168.32.0/20 | 1 |
|
||||
| `n8n_default` | 172.25.0.0/16 | 1 |
|
||||
| `ntfy_default` | 172.27.0.0/16 | 1 |
|
||||
| `nuc-ai-core_default` | 172.29.0.0/16 | 1 |
|
||||
| `paperless-ngx_default` | 172.28.0.0/16 | 5 |
|
||||
| `pocketid_default` | 172.20.0.0/16 | 1 |
|
||||
| `qdrant_default` | 172.24.0.0/16 | 1 |
|
||||
| `traccar_default` | 172.26.0.0/16 | 1 |
|
||||
| `vaultwarden_default` | 192.168.64.0/20 | 1 |
|
||||
| `vpn_default` | 192.168.80.0/20 | 1 |
|
||||
|
||||
Total: 19 user-defined bridge networks.
|
||||
|
||||
### Problem
|
||||
|
||||
Docker's default address pool for user-defined bridge networks is
|
||||
172.17.0.0/16 – 172.31.0.0/16 (15 subnets max). With 15 172.x.x.x/16 networks
|
||||
already allocated, there is no room for new ones.
|
||||
|
||||
The Daytona runner (`daytona-minimal-runner-1`) programmatically creates a
|
||||
`runner-bridge` network on startup. It fails with:
|
||||
|
||||
```
|
||||
Error response from daemon: invalid pool request: Pool overlaps with other one
|
||||
on this address space
|
||||
```
|
||||
|
||||
## Consolidation Plan
|
||||
|
||||
### shared_backend Network
|
||||
|
||||
A single shared bridge network (`shared_backend`) has been created to replace
|
||||
per-stack defaults for lightweight services that don't need isolation.
|
||||
|
||||
### Stacks Already Migrated
|
||||
|
||||
- arcane
|
||||
- dozzle
|
||||
- ntfy
|
||||
- qdrant
|
||||
- traccar
|
||||
- vaultwarden
|
||||
- memos
|
||||
- n8n
|
||||
- pocketid
|
||||
|
||||
These stacks now declare:
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: shared_backend
|
||||
```
|
||||
|
||||
### How to Free Subnets
|
||||
|
||||
After migrating a stack to `shared_backend`, recreate it and prune the old network:
|
||||
|
||||
```bash
|
||||
cd /opt/stacks/{stack} && docker compose up -d
|
||||
docker network rm {stack}_default # after containers disconnect
|
||||
```
|
||||
|
||||
### Stacks Keeping Own Networks
|
||||
|
||||
These stacks have complex internal networking and should keep their own:
|
||||
|
||||
- **immich** — 5 services with inter-dependencies
|
||||
- **paperless-ngx** — 5 services (webserver, broker, db, gotenberg, tika)
|
||||
- **arr-stack** — 5 services (rdtclient, prowlarr, audiobookshelf, shelfarr, flaresolverr)
|
||||
- **daytona** — explicit `daytona-minimal_daytona-network`
|
||||
- **karakeep** — 3 services with chrome dependency
|
||||
- **homepage** — single service, can stay or migrate
|
||||
- **streamio** — already removed, stremio uses VPN container directly
|
||||
- **vpn** — single service, can stay or migrate
|
||||
- **ai/*_ai** — AI stacks, untouched
|
||||
|
||||
### Long-term Fix
|
||||
|
||||
Add `default-address-pools` to `/etc/docker/daemon.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"default-address-pools": [
|
||||
{"base": "10.0.0.0/8", "size": 24}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This gives 65536 /24 subnets, eliminating exhaustion. Requires Docker daemon
|
||||
restart (`systemctl restart docker`), which briefly disrupts all containers.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# List all networks
|
||||
docker network ls
|
||||
|
||||
# Inspect a network
|
||||
docker network inspect {name}
|
||||
|
||||
# Remove unused networks
|
||||
docker network prune
|
||||
|
||||
# Remove a specific network (must have 0 containers)
|
||||
docker network rm {name}
|
||||
```
|
||||
@@ -1,96 +0,0 @@
|
||||
# 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 |
|
||||
|
||||
### 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.
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
# Todo
|
||||
|
||||
## Goal
|
||||
Consolidate databases, migrate storage to UNAS, integrate all services with Homepage.
|
||||
|
||||
---
|
||||
|
||||
# Ideas (user)
|
||||
- Claude Max sub integration with litellm (how to handle auth, rate limits, etc.?)
|
||||
- MCP deployment process ideas? Current setup seems cumbersome — can litellm host directly?
|
||||
(how to integrate npx, uvx, and maybe docker-based containers?)
|
||||
- Select offsite backup hosting provider, set up backup process (maybe restic to Backblaze B2
|
||||
or similar), then set up rclone for off-site sync of Garage buckets to remote S3
|
||||
(Backblaze B2, Jottacloud, or Hetzner)
|
||||
- Research the LiteLLM MCP `source_url` column problem across GitHub issues, PRs, and docs
|
||||
to understand the full picture
|
||||
- Add Google Gemini (vision + 1M ctx + free text-embedding-004; needs GEMINI_API_KEY)
|
||||
- Add fal.ai MCP server (`mcp/fal`) for fast cloud image gen < 5 s (vs ~150 s local ComfyUI)
|
||||
- Add Cerebras (Llama 3 at ~1M tok/s, generous free tier; CEREBRAS_API_KEY)
|
||||
|
||||
# Next Steps / Todos
|
||||
- [x] **ComfyUI added & fixed (2026-05-17)** — root-caused the self-referential
|
||||
bind-mount, repaired mounts/healthcheck, migrated CPU→**Intel Arc iGPU**
|
||||
(torch 2.7.1+xpu, no IPEX), pinned v0.21.1. FLUX.1-schnell GGUF, legible
|
||||
text, ~94 s/image. Canonical workflow in `ai/comfyui/workflows/`.
|
||||
- [x] **ComfyUI→LobeChat via MCP (2026-05-17)** — purpose-built `comfyui-mcp`
|
||||
server, proven end-to-end. See `docs/comfyui-mcp.md`.
|
||||
- [x] **MCP gateway finished (2026-05-17)** — DinD, real streaming MCP
|
||||
reverse-proxy, Pocket ID bearer + RFC9728 discovery, OAuth callback fixed,
|
||||
secrets from `.env`, no port collisions. See `docs/mcp-gateway.md`.
|
||||
- [x] **LobeChat S3 images fixed (2026-05-17)** — added `S3_PUBLIC_DOMAIN=http://192.168.1.40:10004`
|
||||
to `lobehub.yml`; pre-signed URLs now use the LAN-accessible Garage port instead of
|
||||
the internal `garage:3900` hostname.
|
||||
- [x] **MCP gateway groups + combined endpoints (2026-05-17)** — servers now grouped
|
||||
(research/dev/personal/image); `/group/{name}/mcp` aggregates all member tools with
|
||||
`server__tool` namespacing; UI shows grouped cards with copy-URL buttons; `/` → `/ui`
|
||||
redirect added.
|
||||
- [x] **LiteLLM Redis caching (2026-05-17)** — `cache: true` with Redis backend
|
||||
(`lobe-redis`, already on `ai-internal`); 10-min TTL on completion + embedding calls.
|
||||
- [x] **Cohere added to LiteLLM (2026-05-17)** — `command-a-03-2025` (20 RPM),
|
||||
`cohere-embed-english/multilingual/light-v3` (2000 RPM); `COHERE_API_KEY` in `.env`.
|
||||
Note: command-r / command-r-plus retired 2025-09-15.
|
||||
- [x] **LobeChat MCP import done** — `comfyui-flux` server imported via UI.
|
||||
- [x] **ComfyUI MCP async queue (2026-05-17)** — full rewrite: `generate_image`
|
||||
returns job_id in <0.1 s; background polling thread updates state; `img2img`
|
||||
accepts many images (URL/base64/`job:<id>` chaining); `get_job_status`,
|
||||
`list_queue`, `cancel_job`, `list_recent_images`. New `flux-img2img-api.json`
|
||||
workflow (VAEEncode path). See `docs/comfyui-mcp.md`.
|
||||
- [ ] Nextcloud MCP: bearer token enabled in NC admin (user_oidc provider settings).
|
||||
Gateway now provisions NC app-password at SSO login time (PocketID token live).
|
||||
**Needs end-to-end test**: log in via mcp.nuclide.systems, then call /nextcloud/mcp.
|
||||
- [ ] Observability LXC: deploy OTEL collector + VictoriaMetrics + Grafana + Loki
|
||||
+ Uptime Kuma on a Proxmox LXC; see `docs/stack-ideas.md §8`.
|
||||
- [ ] Arcane: migrate central server to Proxmox LXC; deploy arcane-agent (headless)
|
||||
on NUC + .49; connect via TCP Docker socket or SSH Docker context.
|
||||
- [ ] Docling + n8n ingest pipeline: Nextcloud/Paperless → Docling → LiteLLM embed
|
||||
→ LobeChat knowledge base; see `docs/stack-ideas.md §1`.
|
||||
- [x] **Gateway spawn servers (2026-05-17)** — papersearch, crawl4ai, markitdown
|
||||
all running on `ai-internal`. Fixed papersearch command (`uvx --with` not
|
||||
`uv tool run --from`). nextcloud deferred: Nextcloud OIDC discovery not
|
||||
enabled; needs `NEXTCLOUD_USERNAME`/`NEXTCLOUD_PASSWORD` in `ai/.env` for
|
||||
BasicAuth mode (server.py already updated).
|
||||
- [x] **ComfyUI inpaint smoke-tested (2026-05-17)** — Kodak #23 (768×512) + center
|
||||
alpha-mask, submitted via API, output in 290s. Workflow confirmed working end-to-end.
|
||||
- [x] **garage external S3 working** — `s3.nuclide.systems` returns 403 (AccessDenied
|
||||
on root, expected); Zoraxy routes correctly to `10004→3900`. Was already fixed by
|
||||
the earlier port binding change (`0.0.0.0:10004`); todo was stale.
|
||||
- [x] **syncstack gone** — container no longer present; one-shot job completed/pruned.
|
||||
- [x] **immich_machine_learning healthcheck fixed** — already on :3003/ping.
|
||||
Container shows healthy.
|
||||
- [x] **LiteLLM healthcheck fixed** — was hitting host port 14000 inside container;
|
||||
corrected to container port 4000. Now healthy.
|
||||
- [x] **immich_power_tools / karakeep / karakeep_chrome** — all healthy (slow warmup
|
||||
self-resolved).
|
||||
|
||||
## In Progress
|
||||
- None
|
||||
|
||||
## Blocked
|
||||
- None
|
||||
|
||||
---
|
||||
|
||||
# Reference / History
|
||||
|
||||
## Done
|
||||
- Created `/opt/stacks/shared-db/` with shared-postgres (pg16), Garage S3, pgAdmin
|
||||
- Consolidated daytona, litellm, paperless-ngx → shared-postgres
|
||||
- LobeHub kept on own pg17 (ParadeDB)
|
||||
- Switched LobeHub from RustFS → Garage S3 (`lobe-files` bucket)
|
||||
- Migrated arr-stack configs + media to UNAS via rsync
|
||||
- Migrated qdrant to UNAS (fresh start)
|
||||
- Added 29 selfh.st icons, updated all homepage labels to `sh-` prefix
|
||||
- Homepage: instance hrefs (192.168.1.40:PORT) + public hrefs (*.nuclide.systems)
|
||||
- Homepage widgets for 11 services
|
||||
- Groups consolidated from 14 → 6 (infrastructure, security, media, ai, productivity, diagnostic)
|
||||
- Configured memos with Garage S3
|
||||
- Fixed Garage port binding: `127.0.0.1:10004` → `0.0.0.0:10004` (Zoraxy couldn't reach it)
|
||||
- Fixed memos S3 endpoint: `https://s3.nuclide.systems` → `http://garage:3900` (TLS cert mismatch)
|
||||
- Cleaned up old local data remnant at `/opt/stacks/memos/data/`
|
||||
- traccar GPS port fixed: 15001 → 19001 (paperless-ai port conflict)
|
||||
- Updated PORTMAP.md, created storage.md and volumes.md
|
||||
- WAL-G v3.0.8 setup for all 3 PG instances (shared-postgres, immich, lobe)
|
||||
- Garage S3 buckets + per-instance keys for PG backups
|
||||
- WAL archiving enabled and flowing to Garage (`wal-g wal-push`)
|
||||
- Daily full backup cron at 3am (`/etc/cron.d/pg-backup`)
|
||||
- Home Assistant added to Homepage (infrastructure, widget token)
|
||||
- ShelfArr added to Homepage (diagnostic, MDI icon)
|
||||
|
||||
## Proxy migration → Zoraxy + clean-state recreate — audit 2026-05-16
|
||||
|
||||
### Done
|
||||
- Reverse-proxy plan moved Traefik → **Zoraxy** v3.3.2 (`192.168.1.4:8000`, noauth, internal).
|
||||
Traefik abandoned: it runs on a different host than the containers, so Docker labels
|
||||
can't work cross-host; Zoraxy already had the wildcard `*.nuclide.systems` cert + rules.
|
||||
- Source of truth: `proxy/zoraxy/routes.json` + idempotent CSRF-aware
|
||||
`scripts/zoraxy_sync.py` (`--dry-run` default / `--apply` / `--prune` / `--list`).
|
||||
Self-service: edit the JSON, run `--apply`.
|
||||
- Zoraxy reconciled: fixed `ai`→14000 (litellm), `mcp`→8080 (mcp-gateway),
|
||||
added `chat`→14001 (lobehub). Pruned (not exposed): dozzle, immich-tools,
|
||||
mcp-auth. Internal-only: pgadmin, paperless, paperless-ai.
|
||||
- Fixed AI URL configs (`litellm.nuclide.systems` had no route):
|
||||
`ai/litellm-config/config.yaml`, `ai/.env`, `karakeep/.env` → `ai.nuclide.systems`;
|
||||
`paperless_ai/.env` CUSTOM_BASE_URL `mcp`→`ai`.
|
||||
- paperless-ngx host port `15000:8000` published (internal LAN); paperless-ai 15001 already in compose.
|
||||
- Stripped **all** `traefik.*` labels from every compose file; fixed memos YAML escaping.
|
||||
- Cleaned `proxy/` (removed dead Traefik artifacts) + added `proxy/zoraxy/README.md`.
|
||||
- `shared-db/docker-compose.yml` restored from HEAD (WIP had deleted shared-postgres
|
||||
+ `GARBAGE_` typos) and force-recreated cleanly.
|
||||
- Removed stale `*_old` containers; clean-state force-recreate of all 19 stacks.
|
||||
|
||||
### Verified working (Zoraxy end-to-end, https via .4)
|
||||
- ai, chat, mcp, arcane, ntfy, id, vault, abs, n8n, memos, hoarder, daytona, traccar — all serving.
|
||||
- Static/external: ha, nc, ocpp, shepard, shepard-api — reachable.
|
||||
- shared-postgres healthy; litellm/lobehub/mcp-gateway healthy & proxied; garage S3 working
|
||||
internally (active wal-g WAL backups).
|
||||
|
||||
### Issues found → fix outcomes (2026-05-16)
|
||||
- [x] **FIXED — immich_server crash-loop** (`getaddrinfo ENOTFOUND database`):
|
||||
the `database` service was on `immich_immich_default`+`shared_backend` while
|
||||
immich-server/redis/ml were on the implicit `immich_default` → no shared net.
|
||||
Fix: `immich/docker-compose.yml` top-level network is now
|
||||
`default: {name: immich_default}` and `database` joins `[default, shared_backend]`.
|
||||
Verified: immich_server **healthy**, `immich.nuclide.systems` → **200** via Zoraxy.
|
||||
- [x] **FIXED — vpn_gluetun "unhealthy"**: removed the bogus custom healthcheck
|
||||
(`wget :8000`, 404s) so gluetun's built-in healthcheck (127.0.0.1:9999) runs.
|
||||
Verified: `vpn_gluetun` **healthy**; arr-stack recreated (it uses
|
||||
`network_mode: container:vpn_gluetun`) — prowlarr/rdtclient/shelfarr/flaresolverr healthy.
|
||||
- [ ] **NOT fixed — garage external S3 (`s3.nuclide.systems`)**: tried
|
||||
`api_bind_addr`/`rpc_bind_addr` `[::]`→`0.0.0.0`, but applying it needs a
|
||||
force-recreate, and garage's single-node cluster is fragile to restarts — the
|
||||
recreate caused "could not reach quorum" (RPC). **Reverted `garage.toml` to HEAD
|
||||
and recreated**; garage is back to the known-good state (HEALTHY node, layout v1,
|
||||
buckets OK, internal S3 / PG WAL backups working). External `s3.nuclide.systems`
|
||||
remains non-responsive **as it was before** — tracked in Todos above.
|
||||
- [ ] `nuc-ai-core-syncstack-1` left `Created` — tracked in Todos above.
|
||||
|
||||
### Other (pre-existing, NOT in the fix-1/2/3 scope, surfaced by clean recreate)
|
||||
- `immich_machine_learning` shows "unhealthy" but **works** — its healthcheck tests
|
||||
`localhost:3000/health` while ML serves `:3003` (immich_server logs confirm
|
||||
"Machine learning server became healthy"). Cosmetic healthcheck-port mismatch in
|
||||
the immich compose.
|
||||
- `immich_power_tools`, `karakeep`, `karakeep_chrome` showing "unhealthy" after the
|
||||
clean recreate — slow/long healthcheck warmup; revisit if still unhealthy later.
|
||||
|
||||
### Notes
|
||||
- Zoraxy self-service: `python3 scripts/zoraxy_sync.py [--apply|--prune|--list]`.
|
||||
- The shared-db WIP (garage/postgres rework) was reverted to HEAD — redo it intentionally
|
||||
if that work was wanted.
|
||||
|
||||
|
||||
@@ -1,345 +0,0 @@
|
||||
# Volume Mounts — NUC 14 Docker Stacks
|
||||
|
||||
> Every bind mount and named volume across all running containers.
|
||||
> Last updated: May 16, 2026
|
||||
|
||||
## Legend
|
||||
|
||||
| Column | Meaning |
|
||||
|---|---|
|
||||
| **Type** | `bind` = host directory, `volume` = docker named volume, `tmpfs` = memory |
|
||||
| **Source** | Host path (bind) or volume name (volume) |
|
||||
| **Container** | Mount point inside container |
|
||||
| **UNAS** | `/mnt/pve/unas/services/` target (migrated or planned) |
|
||||
|
||||
---
|
||||
|
||||
## Infrastructure
|
||||
|
||||
### Arcane — `arcane`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/var/run/docker.sock` | `/var/run/docker.sock` | — |
|
||||
| bind | `/opt/stacks` | `/app/data/projects` | — |
|
||||
| **bind** | **`/mnt/pve/unas/services/arcane`** | **`/app/data`** | ✅ **Migrated** |
|
||||
| ~~volume~~ | ~~`arcane_arcane-data`~~ | ~~`/app/data`~~ | 🗑️ removed |
|
||||
|
||||
### Dozzle — `dozzle`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/dozzle/dozzle_data` | `/data` | (optional, ephemeral) |
|
||||
| bind | `/var/run/docker.sock` | `/var/run/docker.sock` | — |
|
||||
|
||||
### Homepage — `homepage`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/homepage/config` | `/app/config` | (keep in stack dir) |
|
||||
| bind | `/opt/stacks/homepage/icons` | `/app/public/icons` | (keep in stack dir) |
|
||||
| bind | `/var/run/docker.sock` | `/var/run/docker.sock` | — |
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
### Pocket ID — `pocketid`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/pocketid`** | **`/app/data`** | ✅ **Already on UNAS** |
|
||||
|
||||
### Vaultwarden — `vaultwarden`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/vaultwarden`** | **`/data`** | ✅ **Already on UNAS** |
|
||||
| bind | `/etc/localtime` | `/etc/localtime` | — |
|
||||
| bind | `/etc/timezone` | `/etc/timezone` | — |
|
||||
|
||||
---
|
||||
|
||||
## Media — Immich
|
||||
|
||||
### Immich Server — `immich_server`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/immich/encoded-video`** | `/usr/src/app/upload/encoded-video` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/services/immich/profile`** | `/usr/src/app/upload/profile` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/services/immich/thumbs`** | `/usr/src/app/upload/thumbs` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/media/images`** | `/usr/src/app/upload` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/backup/immich`** | `/usr/src/app/upload/backups` | ✅ **Already on UNAS** |
|
||||
| volume | `7d25f4ac...` (anonymous) | `/data` | (unknown, check) |
|
||||
|
||||
### Immich ML — `immich_machine_learning`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `immich_model-cache` | `/cache` | (cache, regenerable) |
|
||||
| bind | `/dev/bus/usb` | `/dev/bus/usb` | — |
|
||||
|
||||
### Immich Postgres — `immich_postgres`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/opt/stacks/immich/postgres`** | **`/var/lib/postgresql/data`** | ⏳ Plan: `immich/db` |
|
||||
|
||||
---
|
||||
|
||||
## Media — Downloads / Arr Stack
|
||||
|
||||
All behind gluetun VPN.
|
||||
|
||||
### RDTClient — `rdtclient`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/arr-stack/rdtclient/config` | `/data/db` | ⏳ Plan: `arr-stack/rdtclient` |
|
||||
| bind | `/opt/stacks/arr-stack/media/Torrents` | `/data/downloads` | ⏳ Plan: `arr-stack/torrents` |
|
||||
|
||||
### Prowlarr — `prowlarr`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/arr-stack/prowlarr` | `/config` | ⏳ Plan: `arr-stack/prowlarr` |
|
||||
|
||||
### Audiobookshelf — `audiobookshelf`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/arr-stack/audiobookshelf` | `/config` | ⏳ Plan: `arr-stack/audiobookshelf` |
|
||||
| bind | `/opt/stacks/arr-stack/media/audiobooks` | `/audiobooks` | ⏳ Plan: `arr-stack/audiobooks` |
|
||||
| bind | `/opt/stacks/arr-stack/media/ebooks` | `/ebooks` | ⏳ Plan: `arr-stack/ebooks` |
|
||||
| bind | `/opt/stacks/arr-stack/media/podcasts` | `/podcasts` | ⏳ Plan: `arr-stack/podcasts` |
|
||||
|
||||
### ShelfArr — `shelfarr`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/arr-stack/shelfarr/storage` | `/rails/storage` | ⏳ Plan: `arr-stack/shelfarr` |
|
||||
| bind | `/opt/stacks/arr-stack/media/audiobooks` | `/audiobooks` | (shared) |
|
||||
| bind | `/opt/stacks/arr-stack/media/ebooks` | `/ebooks` | (shared) |
|
||||
| bind | `/opt/stacks/arr-stack/media/Torrents` | `/downloads` | (shared) |
|
||||
|
||||
### Flaresolverr — `flaresolverr`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/var/lib/flaresolver` | `/config` | (cache, regenerable) |
|
||||
|
||||
---
|
||||
|
||||
## AI Stack
|
||||
|
||||
### LiteLLM — `litellm`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/ai/litellm-config` | `/app/config` | (keep in stack dir) |
|
||||
|
||||
### LiteLLM DB — `nuc-ai-core-litellm-db-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/opt/stacks/ai/postgres_data`** | **`/var/lib/postgresql/data`** | ⏳ Plan: `ai/litellm-db` |
|
||||
|
||||
### LobeHub — `lobehub`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/ai/lobehub/data` | `/var/lib/postgresql/data` | ⏳ Plan: `ai/lobehub-db` |
|
||||
|
||||
### LobeHub Redis — `lobe-redis`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `nuc-ai-core_redis_data` | `/data` | (ephemeral, stay) |
|
||||
|
||||
### LobeHub RustFS — `lobe-rustfs`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `nuc-ai-core_rustfs-data` | `/data` | ⏳ Plan: `ai/rustfs` |
|
||||
|
||||
### SearXNG — `searxng`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/ai/searxng` | `/etc/searxng` | (keep in stack dir) |
|
||||
| volume | `bb5bb182...` (anonymous) | `/var/cache/searxng` | (cache, regenerable) |
|
||||
|
||||
### SearXNG Redis — `redis-searxng`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `f9c3c386...` (anonymous) | `/data` | (ephemeral, stay) |
|
||||
|
||||
### SAIA Image Proxy — `nuc-ai-core-saia-image-proxy-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/ai/saia-image-proxy` | `/app` | (keep in stack dir) |
|
||||
|
||||
### Crawl4AI — `crawl4ai-mcp`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| tmpfs | `/dev/shm` | `/dev/shm` | — |
|
||||
|
||||
---
|
||||
|
||||
## Documents
|
||||
|
||||
### Paperless-ngx Webserver — `paperless-ngx-webserver-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/media/documents/public/paperless-ngx/consume`** | `/usr/src/paperless/consume` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/media/documents/public/paperless-ngx/export`** | `/usr/src/paperless/export` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/media/documents/public/paperless-ngx/library`** | `/usr/src/paperless/media` | ✅ **Already on UNAS** |
|
||||
| volume | `paperless-ngx_data` | `/usr/src/paperless/data` | ⏳ Plan: `paperless-ngx/data` |
|
||||
|
||||
### Paperless-ngx DB — `paperless-ngx-db-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `paperless-ngx_pgdata` | `/var/lib/postgresql/data` | ⏳ Plan: `paperless-ngx/pgdata` |
|
||||
|
||||
### Paperless-ngx Broker — `paperless-ngx-broker-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `paperless-ngx_redisdata` | `/data` | (ephemeral, stay) |
|
||||
|
||||
### Paperless AI — `paperless-ai`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/paperless-ai`** | **`/app/data`** | ✅ **Already on UNAS** |
|
||||
|
||||
---
|
||||
|
||||
## Productivity & Bookmarks
|
||||
|
||||
### Memos — `memos`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/memos`** | **`/var/opt/memos`** | ✅ **Migrated** |
|
||||
| ~~bind~~ | ~~`/opt/stacks/memos/data`~~ | ~~`/var/opt/memos`~~ | 🗑️ replaced |
|
||||
|
||||
### Karakeep — `karakeep`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/karakeep/data`** | **`/data`** | ✅ **Already on UNAS** |
|
||||
|
||||
### Karakeep Meilisearch — `karakeep_meilisearch`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/karakeep/meilisearch`** | **`/meili_data`** | ✅ **Already on UNAS** |
|
||||
|
||||
---
|
||||
|
||||
## Automation
|
||||
|
||||
### n8n — `n8n`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/n8n`** | **`/home/node/.n8n`** | ✅ **Migrated** |
|
||||
| bind | `/opt/stacks/n8n/hooks.js` | `/home/node/hooks.js` | (keep in stack dir) |
|
||||
| ~~volume~~ | ~~`n8n_n8n_storage`~~ | ~~`/home/node/.n8n`~~ | 🗑️ removed |
|
||||
|
||||
---
|
||||
|
||||
## DevOps
|
||||
|
||||
### Daytona API — `daytona-minimal-api-1`
|
||||
|
||||
No DB-specific mounts needed (connects via env vars).
|
||||
|
||||
### Daytona DB — `daytona-minimal-db-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `daytona-minimal_db_data` | `/var/lib/postgresql/data` | ⏳ Plan: `daytona/db` |
|
||||
|
||||
### Daytona Runner — `daytona-minimal-runner-1`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| volume | `9416da14...` (anonymous) | `/var/lib/docker` | (runner state, stay) |
|
||||
| bind | `/var/run/docker.sock` | `/var/run/docker.sock` | — |
|
||||
|
||||
---
|
||||
|
||||
## Tracking
|
||||
|
||||
### Traccar — `traccar`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/traccar/data`** | `/opt/traccar/data` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/services/traccar/logs`** | `/opt/traccar/logs` | ✅ **Already on UNAS** |
|
||||
| **bind** | **`/mnt/pve/unas/services/traccar/traccar.xml`** | `/opt/traccar/conf/traccar.xml` | ✅ **Already on UNAS** |
|
||||
|
||||
---
|
||||
|
||||
## VPN
|
||||
|
||||
### Gluetun — `vpn_gluetun`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/gluetun/data`** | **`/gluetun`** | ✅ **Already on UNAS** |
|
||||
|
||||
---
|
||||
|
||||
## Shared Infrastructure
|
||||
|
||||
### Shared PostgreSQL — `shared-postgres`
|
||||
|
||||
| Type | Source | Container | Notes |
|
||||
|---|---|---|---|
|
||||
| volume | `shared-db_shared-pgdata` | `/var/lib/postgresql/data` | 🗄️ Local NVMe (not NFS) |
|
||||
|
||||
### Garage S3 — `garage`
|
||||
|
||||
| Type | Source | Container | Notes |
|
||||
|---|---|---|---|
|
||||
| bind | `/mnt/pve/unas/services/shared-db/garage/data` | `/var/lib/garage/data` | S3 object data |
|
||||
| bind | `/mnt/pve/unas/services/shared-db/garage/meta` | `/var/lib/garage/meta` | S3 metadata (LMDB) |
|
||||
|
||||
---
|
||||
|
||||
## Stacks Not Running (Compose Config Only)
|
||||
|
||||
### Streamio — `streamio`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| **bind** | **`/mnt/pve/unas/services/stremio`** | **`/root/.stremio-server`** | ✅ **Already on UNAS** |
|
||||
|
||||
### Qdrant — `qdrant_scientific`
|
||||
|
||||
| Type | Source | Container | UNAS |
|
||||
|---|---|---|---|
|
||||
| bind | `/opt/stacks/qdrant/qdrant_storage` | `/qdrant/storage` | ⏳ Plan: `qdrant/` |
|
||||
|
||||
---
|
||||
|
||||
## Summary: Migration Status
|
||||
|
||||
| Status | Count | Services |
|
||||
|---|---|---|
|
||||
| ✅ Already on UNAS | 11 | gluetun, immich*(4), karakeep*(2), ntfy*(2), paperless-ai, pocketid, stremio, traccar*(3), vaultwarden, paperless-docs*(3), garage*(2) |
|
||||
| ✅ Migrated (Phase 1) | 3 | memos, arcane, n8n |
|
||||
| 🔷 Shared infrastructure | 2 | shared-postgres (local volume), garage (on UNAS) |
|
||||
| ⏳ Phase 2 planned (PG consolidation) | 5 | immich → shared-postgres, paperless → shared-postgres, daytona → shared-postgres, litellm → shared-postgres, lobehub → shared-postgres |
|
||||
| ⏳ Phase 3 planned | 1 | arr-stack*(8 mounts) |
|
||||
| 📋 Keep local | ~5 | homepage, dozzle, litellm-config, searxng-config, saia-image-proxy |
|
||||
| 🧠 Cache (stay) | ~5 | immich_model-cache, paperless-ngx redis, lobe-redis, searxng-redis, flaresolverr, daytona-runner |
|
||||
Reference in New Issue
Block a user