User's Nextcloud rollout already hit the classic trap of unprivileged-LXC
write attempts against an NFS share, so don't repeat that pattern for
Nexa. Updated docs to:
- Use SMB volumes mounted directly as docker volumes (driver: local,
type: cifs) with explicit username/uid/gid — bypasses LXC uid-mapping
entirely. Concrete YAML in docs/09 step 3 against
//192.168.1.31/nexa/<volume>.
- Keep the host-side /mnt/pve/unas NFS mount for admin-only use (rsync,
manual snapshot copies). Don't bind-mount it into containers.
- docs/12 #27 reordered to lead with SMB targets (qdrant, graphdb,
tei-cache, snapshots) and only mention NFS for host admin.
- CLAUDE.md storage block flipped to "SMB = default per-container
storage; NFS = host-side admin only".
- Also captured: deployments go through the Dockge UI (LXC is
the Dockge flavor of helper-scripts), not raw `docker compose up`.
- New optimization #30 about the local mail spool nag on the docker LXC
("You have new mail." at login).
- LXC 104 (docker) confirmed: 16 CPU, 31.25 GiB RAM (7.86 used / 25%),
200 GiB boot disk at 47.7% — disk is the real near-term constraint,
not RAM. Numbers propagated into Q11 (docs/11), docs/03 architecture
table, and CLAUDE.md infra block.
- New optimization #26 in docs/12: fix the Intel Arc iGPU passthrough
flagged as broken in the LXC notes. Concrete /etc/pve/lxc/104.conf
snippet provided. Once working, TEI / infinity / Immich CLIP can run
GPU-accelerated for ~5–10x throughput.
- New optimization #27: disk-pressure mitigation playbook (move Qdrant
to unas if it grows, prune docker layers monthly, cap n8n executions).
- New optimization #28: shrink the LXC's 8 GiB swap to 2 GiB.
Verified from screenshots:
- Q6/Q7 → Lists & calendars discovered by NAME, not by ID. Names confirmed:
"Persönlich" (personal), "DLR" (work), "Einkaufsliste" (shopping),
"Wunschliste" (wishes). Self-healing: #nexa:config runs daily and on
cache-miss, so user-added lists become routable without code changes.
Routing logic in docs/07 expanded from 2-way to 4-way switch with a
Resolver step that consults the Qdrant _config cache before fanning out;
default route is "Persönlich" when SAIA confidence < 0.7.
- Q8 → Single Nextcloud Mail account fkrebs@nucli.de. No separate IMAP.
The "Waiting" folder is honored as a manual user signal — items there are
excluded from digest.
- Q9 → Pocket-ID SSO is global at the Zoraxy layer; Nexa surfaces inherit
it. No app-level basic-auth. Q10 folded in.
- Q11 → Capacity confirmed: 22 threads (Core Ultra 7 155H), 62 GiB RAM
(~32 GiB used, ~24 GiB of which is ZFS ARC), 1.64 TiB disk (0.35%).
Phase-3 budget (~7 GB) is comfortable; two levers documented (raise
LXC cap, or cap zfs_arc_max). Earlier "16 CPU" references corrected.
Propagation:
- system_prime.txt rewritten with the four context labels and the new
list names; legacy NC_LIST_ID_* placeholders removed.
- docs/04 integration matrix uses the German names directly.
- docs/05 documents that #nexa:config also runs scheduled and on
cache-miss, with the example output reflecting real list IDs.
- docs/09 step 6 mirrors the same flow + lists the Waiting-folder
semantics.
- CLAUDE.md gets an authoritative block of homelab decisions so future
agents don't re-litigate any of these.
New section in docs/12 (#17–25): Proxmox host tuning suggestions
based on the live node summary — cap ZFS ARC (frees ~16 GiB),
enable KSM (~1-3 GiB savings across 40 containers), suppress the
no-subscription banner, drop swappiness, verify scrub/SMART/fstrim
timers, NTP via AdGuard.
- Q4 → Obsidian vault is the Notizen/ folder in Nextcloud (multi-device sync).
Nexa reads via WebDAV using the existing NC_APP_PASSWORD — no filesystem
mount. Ignore list pinned: .copilot/, .copilot-index/, .smart-env/,
.caldav-sync/, assets/ (routed to Phase-3.2 visual queue), Templates/,
BMO/, Excalidraw/. Index target: Notizen/**/*.md.
- Q5 → canonical name is Karakeep; legacy Zoraxy alias hoarder.nuclide.systems
kept for compatibility.
- Q13 → Octoprint container is intentionally powered down most of the time.
Phase-5 monitoring must skip names matching octoprint*. Reflected in
docs/10 monitoring table and CLAUDE.md.
- Q14 → Homepage Zoraxy widget config error; cosmetic, dropped from open
questions and from docs/12 optimization list.
- Q18 → SAIA does proxy embeddings but rate limit is 10 msg/min, unusable
for ingest. TEI stays in Phase 3.1.
- docs/12: stale items removed (Octoprint, Zoraxy widget, generic Immich
vector idea); added new ones derived from the Obsidian discovery (plugin
embedding collision, notify_push upgrade path, assets/ size note).
- docs/04 integration matrix updated to describe Obsidian-via-Nextcloud
read path explicitly.
- docs/09 step-4 credentials list collapses NC Tasks / Calendar / WebDAV
onto a single app password.
- Q16 → image bytes stay in their source (Memos / Nextcloud / Obsidian);
Phase-3.2 backfill fetches by media_uri. Zero copy.
- Q17 → Immich stays out-of-band; Nexa does not call Immich's smart-search.
- New Q18 carries forward the unresolved sub-question of whether SAIA's
LiteLLM gateway already proxies an embedding model — a 1-line check that
could let us skip TEI in 3.1.
Decision (Q15 resolved): start with text-only via TEI + bge-m3 in Phase 3.1,
prepare data shapes so Phase 3.2 (visual collection via infinity + jina-clip-v2)
is a pure additive operation — no rename, no schema migration, no n8n rewiring.
Concretely:
- Qdrant collection renamed nexa_knowledge → nexa_knowledge_text (1024-dim
for bge-m3) with modality-aware payload (modality, source_type, media_uri,
graph_iri, content_hash, context). Visual placeholder schema committed
alongside (qdrant_schema_visual.json, 768-dim, jina-clip-v2).
- Image attachments captured in 3.1 are recorded in GraphDB as nexa:Note with
nexa:modality "image" + nexa:pendingVisualIndex true; the 3.2 backfill
workflow picks them up and embeds. No data lost between phases — the queue
is the GraphDB itself.
- RDF schema (docs/08) gains nexa:modality, nexa:mediaUri,
nexa:vectorCollection, nexa:pendingVisualIndex from day one.
- docs/02 roadmap split: 3.1 = text RAG (Path A), 3.2 = visual collection
(Path C), 3.4 = Ontotext GraphDB.
- docs/09 grows a "Phase add-on: visual collection (Phase 3.2)" section with
the TEI→infinity swap, second collection create, LiteLLM second model
registration, and the SPARQL-driven backfill query.
- New open questions: Q16 (queue ergonomics + does SAIA already proxy an
embed model?), Q17 (reuse Immich's CLIP for photo-library queries?).
- docs/03 + CLAUDE.md updated so future runs use the new collection names
and don't re-decide the staging.
- Q1 → Ontotext GraphDB (SPARQL). docs/08 fully rewritten with RDF schema,
example SPARQL queries (transitive deps via property paths, time-windowed
topic counts, cross-pillar joins via nexa:vectorId).
- Q2 → reuse qdrant_scientific with nexa_* collection prefix; docs/09 step 2
now points there explicitly.
- Q3 → no OpenAI embeddings. Self-host on the docker host. Use TEI
(HuggingFace text-embeddings-inference) — single Rust binary, ~500 MB image,
OpenAI-compatible — instead of Ollama, since we only need embeddings.
- docs/09 Phase-3.4 add-on simplified to a single Ontotext compose snippet
(Neo4j option dropped) plus repo creation curl.
- docs/11 Q3 marked resolved; new Q15 picks the model (bge-m3 vs nomic-embed)
and adds the open question of whether SAIA already proxies an embedding
model that would let us skip TEI entirely.
- docs/03 + CLAUDE.md updated with the new decisions so future runs don't
re-litigate.