Skip to content

> STATUS: STALE — many claims (PVE version, Pocket-ID port, Dockge as docker manager) no longer accurate. Source of truth is /CLAUDE.md and /docs/services/. This file kept for the original nexa-stack design notes only.

# Instructions for Claude (and other agents)

This file tells future automated runs what they need to know about this repo.

## Repo conventions

- Documentation: all docs live in `/docs/` and are numbered. Entry point is `docs/index.md`. When you add a doc, give it the next free `NN-` prefix and add a row to the index TOC.
- Runtime artifacts: live in `nexa-core/` (workflows, prompts, configs, scripts). Don't put `.md` documentation in there — link from `/docs/` instead.
- Source-of-truth: if a doc duplicates content from `nexa-core/config/*.md`, delete the duplicate. Single source of truth.

## Real infrastructure (verified from screenshots, May 2026)

- Proxmox host `nuc` at `192.168.1.20:8006` (PVE 9.1.9, kernel 6.17.13-4-pve, EFI).
- Hardware: 22 threads (Intel Core Ultra 7 155H, 1 socket), 62 GiB RAM, 1.64 TiB disk.
- Steady state: ~32 GiB used (≈24 GiB of which is ZFS ARC, tunable via `zfs_arc_max`), CPU load <2.0, IO delay <0.05%.
- LXC 102 dns (AdGuard) — internal DNS, rewrites for `*.nuclide.systems`.
- LXC 103 backrest — backup orchestration.
- LXC 104 docker — main docker host at `192.168.1.40`, hostname `docker`, OS Debian 13. Unprivileged, originally provisioned from the Dockge helper-script template, but Arcane is the active docker manager today (Dockge is stale, slated for retirement — see docs/12 #33). Dozzle is the live log viewer. Allocated: 16 CPU, 31.25 GiB RAM (25% used), 8 GiB swap, 200 GiB boot disk (47.7% used). Storage = Ubiquiti UNAS Pro at `192.168.1.31` (UniFi Drive 4.1.16 on UniFi OS 5.0.17, SFP+ 10 GbE, RAID 6, 19.96 TiB raw / 2.05 TiB used). NFS-exported at `/var/nfs/shared/storage`, mounted by Proxmox at `/mnt/pve/unas`, also exposed via SMB at `smb://192.168.1.31/<share>` (Mac) / `\\192.168.1.31\<share>` (Win).

Standard pattern for docker volumes (verified via Karakeep, Q19): plain host bind-mount of `/mnt/pve/unas/services/<svc>/<vol>` from inside LXC 104. No `driver_opts`, no CIFS, no credentials in the compose. Karakeep, Immich and the rest do exactly this. Nexa follows suit. SMB-as-docker-volume is documented as an escape hatch only (docs/12 #27) for services that hit Nextcloud-style NFS issues — Nexa doesn't, so we don't use it.

Storage-layer snapshots are NOT configured on UNAS Pool 1 ("Click to Setup" in the UniFi Drive dashboard). All 2 TB of homelab data has no point-in-time protection at the storage layer — Backrest covers files, not "the whole pool last Tuesday". Highest-leverage fix in the homelab right now (docs/12 #38).

UNAS layout conventions (homelab-wide, all docker containers follow them): - `services/<svc>/` is the general docker config store — every container in LXC 104 binds its persistent data here. Existing tenants observed: immich, karakeep, nextcloud, ntfy, paperless-ai, pocketid, shelfmark, stremio, traccar, vaultwarden, gluetun. Stale (retire, do not consume): `services/siyuan/` (migrated to Obsidian), `services/open-webui/` (unused — LobeHub is the active LLM UI), and `services/dockge/` if it exists (retired in favor of Arcane). Nexa MUST follow the same pattern: `services/nexa/{qdrant,tei-cache,graphdb,...}`. Don't invent a parallel layout. - `backup/<svc>/` — per-service backups (existing: home-assistant tars, immich pgdump, nextcloud borg). Nexa snapshots → `backup/nexa/`. - `media/`, `code/`, `_sortMe/`, `dump/`, `test_perm` — user data, not Nexa's concern. - Before deploying any Nexa container, READ AN EXISTING STACK in Arcane (e.g. `karakeep` or `immich`) to confirm the exact mount syntax in use — driver name, share path, credential injection pattern. Match it. The actual NFS export root is `/var/nfs/shared/storage`; the SMB share name is still TBD — see Q19 in `docs/11`.

Hard-blocklist for any Nexa indexer / agent (never read these paths or matching glob): - `_sortMe/wallet/**` — contains PGP keys + bitcoin wallet files. - Any path matching `*.gpg`, `*.asc`, `*.key`, `*.pem`, `id_rsa*`, `*wallet*`, `*.kdbx`, `*credentials*`, `*secret*`. - The Nextcloud appdata dir (`services/nextcloud/appdata_*`) — Nextcloud-internal, not user content. Intel iGPU passthrough is configured but currently broken — see docs/12 #26. - LXC 105 nextcloud — Nextcloud at `nc.nuclide.systems`. - LXC 106 octoprint — currently Exited; flagged in docs/11. - LXC 108 zoraxy — reverse proxy at `192.168.1.4:8000`, TLS for `*.nuclide.systems`. - VM 100 haos — Home Assistant. - Already-running services on docker host (don't redeploy): - Memos `:5230`, n8n `:5678`, LiteLLM `:4000` (UI LobeHub `:3210`), Qdrant (`qdrant_scientific`), ntfy `:7998`, Karakeep (legacy alias `hoarder.nuclide.systems`), Vaultwarden `:11001`, Pocket-ID `:1411`, Immich, Audiobookshelf, Paperless-ngx, Traccar, Prowlarr, plus MCP containers (`crawl4ai-mcp`, `markitdown-mcp`, `papersearch-mcp`). - Octoprint (LXC 106) is intentionally powered down most of the time. Phase-5 monitoring must skip names matching `octoprint*` rather than alert on its Exited state. - Obsidian vault lives inside Nextcloud at `nc.nuclide.systems/Notizen/` (multi-device sync via Nextcloud client). Nexa accesses it via WebDAV — read-only, no filesystem mount. Ignore list: `.copilot/`, `.copilot-index/`, `.smart-env/`, `.caldav-sync/`, `assets/` (visual queue, Phase 3.2), `Templates/`, `BMO/`, `Excalidraw/`. Index target: `Notizen/**/*.md`. - Nextcloud Tasks lists & calendars (German names, may grow over time): - `Persönlich` → Personal context. - `DLR` → Work context (DLR is the user's employer). - `Einkaufsliste` → Shopping. - `Wunschliste` → Wishes. Lists are discovered by name at runtime (Qdrant `_config` namespace caches `name → id`). Never hardcode IDs. The discovery workflow runs daily and on cache-miss; new lists added in Nextcloud are honoured automatically next refresh. - Mail = Nextcloud Mail, single account `fkrebs@nucli.de`. No separate IMAP entry. The `Waiting` folder is a manual user signal — items there are skipped from digests. - Backup model is 3-2-1: UNAS native snapshots → `s3.nuclide.systems` (warm, on-site) → encrypted off-site cold tier (provider TBD, Jottacloud is the user's candidate — see Q20). Always `restic`/`rclone-crypt` before upload — third-party provider sees only ciphertext. Don't propose alternative backup paths without checking docs/12 #37 first. - Auth = Pocket-ID SSO is global at the Zoraxy layer. Don't add app-level basic-auth to Nexa surfaces; UIs inherit SSO. Machine-to-machine still uses API keys / app passwords. - Decided for Nexa (don't re-litigate without user input): - Vector store: reuse `qdrant_scientific` with collections suffixed by modality (`nexa_knowledge_text`, `nexa_knowledge_visual`). - Embeddings staged: Phase 3.1 TEI + `BAAI/bge-m3` (text-only, 1024-dim). Phase 3.2 swap to `infinity` and add `jinaai/jina-clip-v2` (768-dim, joint text+image space). All forward-compat fields (`modality`, `media_uri`, `graph_iri`, `nexa:pendingVisualIndex`) exist from 3.1 — adding the visual collection is additive. - Graph store: Ontotext GraphDB (SPARQL/RDF), Phase 3.4. RDF schema in docs/08 already includes `nexa:modality` / `nexa:mediaUri` / `nexa:vectorCollection` / `nexa:pendingVisualIndex`. - Chat model: SAIA via LiteLLM virtual key.

## When working on Nexa

1. Read `docs/index.md` first — it's the navigator.
2. Open questions first. Before writing code or workflow JSON, scan `docs/11-open-questions.md`. If your task touches an unanswered Q, stop and ask rather than picking a default. Append new blockers to that doc as `[ ] Q-NN`.
3. Optimization findings. When you spot infrastructure improvements, add them to `docs/12-optimization-opportunities.md` as a numbered bullet — don't just mention them in commit messages.
4. Never inline secrets in workflow JSON or `.env` committed to git. Use n8n credentials, LiteLLM virtual keys, or (longer term) Vaultwarden.
5. Keep deployment minimal. The default answer to "do we need a new container?" is no — the existing stack covers most needs.

## Branch policy

- This branch is `claude/organize-docs-deployment-7N4v2`. Push only here unless told otherwise.
- New work for an unrelated feature → new branch under `claude/<topic>`.

## Quick links

- docs/index.md
- docs/09-deployment.md — most-touched file during bring-up
- docs/11-open-questions.md — read before assuming defaults