Skip to content

NAS STORAGE CONVERGENCE PLAN — blueflyNAS DS224+

Status: DRAFT FOR THOMAS'S REVIEW — no physical migration is authorized by this document. Evidence: NAS-AUDIT-EVIDENCE.md (this directory) + dated snapshot in evidence/2026-08-02/. Historical note: staged during the audit at Engineering-Standard/infrastructure/nas (formerly staged at /volume1/AgentPlatform/Catalog, retired) (retired). Date: 2026-08-02. Wave 6 LLM SoR restated 2026-09-02 (owner: inference-topology.md).

1. What the NAS is for (target operating model)

One volume (Btrfs, 5.3 TB, 25% used) serving five separated authorities:

Authority Path Owns Must exclude
Source & engineering /volume1/AgentPlatform Applications (174 repos), curated docs (BluCity-Docs), LLM model library (SoR at LLM/; Mac/LM Studio is a client cache) live databases, container logs/caches, credentials, unmanaged .env, development worktrees
Container runtime /volume1/docker services/* persistent data, databases, runtime config, logs, caches, deployment materialization git clones (repos/), archives (_archive/), long-term backups, plaintext secret sprawl
User-private /volume1/homes/bluefly SSH identity (~/.ssh 0600 — already proven), personal CLI config, restricted credentials pending 1Password injection shared/service assets
Backup new share /volume1/Backups (recommended) scheduled DB dumps, Hyper Backup targets, oracle backups, restore-test evidence ad-hoc copies pretending to be backups
Archive new share /volume1/Archive (recommended) migrations, preservation kits, recycled repos, retired deployments, historical dumps anything still consumed

Secret authority is 1Password (op CLI already installed). GitLab remains delivery authority; Oracle remains runtime/Beads authority; nothing here changes that.

Why the DS224+ is best used this way: it is a 2-bay SMB/Btrfs box — its highest-impact roles are (a) canonical source library with snapshots, (b) model-weight SoR the Mac must not own (/volume1/AgentPlatform/LLM; topology: Engineering-Standard/standards/architecture/inference-topology.md), (c) always-on light runtime (NAS Ollama, litellm, qdrant, clickhouse, cloudflared — not Oracle weights), (d) backup/archive vault with Btrfs snapshots + retention. It should NOT be a build farm, a secrets store on 777 shares, a second GitLab clone, or a Mac/Oracle model dump.

2. Headline findings (what forces this plan)

  1. Secrets exposure (worst finding): five private SSH keys, a TLS private key, and an OCI API private key sit mode-777 on the SMB share (AgentPlatform/config/{.ssh,ssl}); TLS material duplicated in docker/ssl (root 777); ~10 plaintext .env files across docker/. 1Password exists on-box but isn't the injection path.
  2. No snapshots on the source share: only docker has snapshots; the share holding 174 repos (66 dirty) has none.
  3. runtime/source inversion: running qdrant writes RW inside Applications/; stopped containers (opencode, agent-ops) mounted the whole source share RW; git clones live inside the runtime share (docker/repos).
  4. Compose fiction: 13 compose mount declarations point at AgentPlatform/data/<service> paths that don't exist; the live stack actually uses docker/services/*. Compose in docker/compose + docker/services/* is mutable and not Git-owned.
  5. False backups: docker/backups/{postgres,redis} empty since January; one-off July dumps in AgentPlatform/data; no restore-test evidence; Hyper Backup state unknown (root-only).
  6. Two restart-looping containers (agent-tracer, cloudflared-contextcontrol) burning the small CPU.
  7. Naming/placement drift: AgentPlatform/data is archives wearing a runtime name; _archive lives inside the runtime share; four empty dirs (anythingllm, artifacts, projects, cloudflared) in docker/; BluTown-minify unclassified.

3. Dispositions (every current top-level entry)

KEEP (in place): AgentPlatform/{Applications, Knowledge, LLM, BluCity→, BluTown→, BluCity-Docs→ symlinks, #recycle}; docker/{services, agents, databases, cache, logs, .env†, config†, AGENTS.md}; homes/bluefly. (retention policy to set; †after Wave-1 secret extraction)

MOVE: Applications/qdrant/storage → docker/services/qdrant/storage (Wave 3); docker/repos/ → Applications/ after remote-identity match (Wave 5); docker/_archive → Archive authority; docker/backups → Backup authority; AgentPlatform/data/{backups,database_backups,oracle-audit,stash-preservation-,eadir-backup-*} → Backup/Archive authorities (Wave 4); share-resident secrets → ~/.ssh / 1Password (Wave 1).

RENAME: none required beyond the moves (no case-only renames proposed).

MERGE: docker/opencode + stale AgentPlatform OpenCode references → one location under docker/services/opencode (Wave 3, after INVESTIGATE).

ARCHIVE: everything under #recycle per retention policy; _Archives repo group stays archival (15 repos).

DELETE AFTER VERIFICATION (only after Wave-4 verification, operator-approved): docker/{anythingllm, artifacts, projects, cloudflared} (empty dirs), docker/config/.env.bak (once values live in 1Password), stale compose declarations.

INVESTIGATE: BluTown-minify; agent-tools (452 MB — does it contain source that belongs in Applications?); copaw-api; happy-server anonymous volume; the two restart loops; Knowledge & Scratch classification; docker/repos remote identities.

RUNTIME GENERATED: docker/{cache,logs}, service caches — get retention, not curation.

4. Execution waves (each = bounded receipt, own approval)

Wave 0 — Freeze & evidence (this document). Catalog created; inventories written; no further whole-share RW container mounts get started (operator discipline, no config change yet). RECOMMENDED OPERATOR ACTION (requires DSM administrator; NOT executed or authorized by this document itself): enable Snapshot Replication for AgentPlatform in DSM (~5 min) — the single cheapest risk reduction available.

Wave 1 — Secrets & ACL containment. Executor: NAS agent + operator. Approval: per-item. Move the 5 SSH keys to ~/.ssh (0600) or retire duplicates (bluefly key already canonical in ~/.ssh); OCI key + Termius creds + .op-env into 1Password; converge TLS to ONE restricted store; migrate .env values to op run injection per stack (start: docker/config/.env*, compose/.env). Update wiki-sync compose (only live consumer of config/.ssh). Verification: every service restarts green with injected secrets; no private key remains >0600 or SMB-exposed. Rollback: originals retained until each service verifies.

Wave 2 — Git/IaC ownership. Executor: Mac dev + GitLab MR. Approval: MR review. Import docker/compose + docker/services/*/compose into a Git-owned infra repo under Applications (or the existing __Infra group repo that already owns them — INVESTIGATE first, DON'T create a duplicate); fix the 13 dead AgentPlatform/data/<svc> mount declarations to the real docker/services paths; deployment = materialized artifact from the repo. Verification: docker compose config clean; live mounts == declared.

Wave 3 — Runtime path convergence. Executor: NAS agent. Approval: per-move. qdrant storage out of Applications (stop → same-fs mv → mount update → start → verify collection count); prohibit whole-share RW mounts (opencode/agent-ops patterns) in the corrected compose; consolidate opencode data; fix or retire the two restart-looping containers. Verification: zero container mounts under Applications; all services green.

Wave 4 — Backup & Archive authorities. Executor: operator (shares) + NAS agent (moves). Create /volume1/Backups + /volume1/Archive shares (DSM); move backup/archive material per migration map; schedule REAL recurring DB dumps; set retention (logs/cache/#recycle); then and only then delete the verified-empty dirs. Verification: restore one mariadb dump end-to-end and record it — a backup is proven by a restore.

Wave 5 — Repository deduplication. Executor: NAS agent, read-mostly. Approval: per-repo. Compare docker/repos/* remotes/HEADs to Applications copies → converge or retire; triage the 66 dirty repos (bounded batches of ~10: commit via MR, preserve branch, or classify as drift — same receipts pattern as the BLU convergence); classify BluTown-minify + _Archives group. Verification: one clone per remote on the NAS.

Wave 6 — LLM normalization. Recommendation: NO move off NAS. Topology owner: Engineering-Standard/standards/architecture/inference-topology.md (do not fork). /volume1/AgentPlatform/LLM is the only model-storage SoR (registry LLM/llms.txt before download; Ollama blobs at LLM/ollama/data). Do not relocate the library to Mac or Oracle. /volume1/docker/services/ollama-models is not SoR (wrong-tag residue, not AgentPlatform). Mac $HOME/.ollama pulls are a defect, not a second canonical store. Compose binds to /volume1/AgentPlatform/ollama/data are fiction (path missing). Actions: keep weights on NAS; prune empty taxonomy dirs if still empty; do not invent a second library. Compose/LiteLLM alias repair is agent-docker work, not a docs move.

Wave 7 — Retention, monitoring, restore proof. Executor: operator + NAS agent. Quarterly restore test; snapshot schedule review; catalog refresh cadence (regenerate nas_projects.json monthly); dirty-repo count and secrets-exposure count become the KPIs (both must trend to zero).

5. Follow-on Bead specifications (create on Oracle — NOT from the NAS)

  1. "Contain NAS share-resident secrets" — parent: NAS storage convergence. AC: zero private keys/tokens >0600 or SMB-exposed; 1Password injection live for migrated stacks; receipts per secret. Executor: NAS agent + operator.
  2. "Converge Docker runtime paths and compose truth" — AC: live mounts == Git-owned compose; zero mounts under Applications; stale declarations removed. Executor: Mac dev (MR) + NAS agent (moves).
  3. "Create Backup and Archive authorities with retention" — AC: /volume1/Backups + /volume1/Archive exist; material moved per map; scheduled dumps running; one verified restore recorded. Executor: operator + NAS agent.
  4. "Deduplicate NAS repository estate" — AC: docker/repos empty or retired; one clone per remote; dirty count from 66 → 0 via MR/preserve/classify receipts. Executor: NAS agent.
  5. "Normalize LLM model stores" — AC: one SoR (/volume1/AgentPlatform/LLM + LLM/llms.txt + LLM/ollama/data); docker/services/ollama-models not treated as canonical; empty taxonomy pruned; no relocation to Mac or Oracle. Executor: NAS agent. Topology: inference-topology.md.
  6. "Restore-test and monitoring cadence" — AC: quarterly restore proof; monthly catalog refresh; KPI dashboard row in MORNING-DASHBOARD. Executor: operator.

6. What this plan does NOT do

No moves, renames, deletions, SMB/ACL changes, container restarts, or model relocation are performed by this document. Every wave returns to Thomas for approval with exact commands, consumers, verification, and rollback — the same receipt discipline used for the BLU root convergence (see #recycle/blu-root-convergence-20260802-142848/MOVE-MANIFEST.md as the worked example).