Problem: node and cross-cutting narratives lived at the repo root
(containers/, vms/, infrastructure/, host .md files), interleaved with the
machine-readable substrate.
Change:
- Move containers/ -> knowledge/wiki/containers/, vms/ -> knowledge/wiki/vms/,
infrastructure/ -> knowledge/wiki/infrastructure/, hosts/{hubris,strong}.md ->
knowledge/wiki/hosts/, infrastructure/references/ -> knowledge/sources/references/,
GLOSSARY.md -> knowledge/GLOSSARY.md.
- Add knowledge/{index.md,log.md,sources/index.md} scaffolding.
- Rewrite all relative links repo-wide via a path-resolving mapper (inbound +
outbound + between-moved-files), including .hermes/, runbooks, operations,
investigations, plans, README, AGENTS.
- Repoint inventory.yaml doc_page fields and regenerate hosts/*.yaml (which
embed doc_page); update oikos/gen-topology.py output path, candidate doc
paths, and footer links; update code-comment doc paths.
Substrate untouched in place: inventory.yaml, hosts/*.yaml (regenerated,
idempotent), oikos/ code, mcp/, secrets/, bin/.
Verification:
- Logical broken-link set identical to pre-move baseline (net 128 -> 127; the
topology regen fixed one, introduced none). Remaining are pre-existing refs
to destroyed/archived nodes, out of scope for this move.
- gen-topology.py --check exit 0 (in sync); cards carry knowledge/wiki/ doc paths.
- build_host_files.py idempotent; all inventory doc_page targets resolve.
- MCP contract verified: get_page/search_docs/get_changelog resolve moved pages.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.5 KiB
102 — nfs-export
Dedicated, single-purpose LXC that re-exports /mnt/library over NFSv4 to clients that can't use the host's PVE virtiofs path — currently only 100-zimaos, which ships a kernel without virtiofs support.
At a glance
- Hostname:
nfs-export - IP:
192.168.8.200(static; LAN-only, no Caddy in front because NFS is L4) - LAN DNS:
nfs-export.hubris.network→192.168.8.200(direct, no Caddy) - Privilege: privileged (
unprivileged: 0) +lxc.apparmor.profile: unconfined— required fornfs-kernel-server - Resources: 1 core / 512 MiB RAM / 2 GiB rootfs / 256 MiB swap
- Mounts: host
/mnt/library↔ container/mnt/library(same path on both sides — matches the bind-mount convention used by jellyfin, paperless, arriman, nextcloud, mule-images, apps)
What it does
/mnt/library (host ext4 on nvme1n1)
│
├── bind-mounted into 7 other LXCs (jellyfin, paperless, …)
└── bind-mounted into LXC 102
│
└── nfs-kernel-server exports /mnt/library
│
└── consumed by VM 100 (ZimaOS)
Same inodes, same page cache. The NFS server is just one more access path on top of a tree that 8 other consumers already share — see media permissions.
Export config
/etc/exports:
/mnt/library 192.168.8.0/24(rw,all_squash,anonuid=33,anongid=10000,no_subtree_check,sec=sys)
Initially started as ro; promoted to rw on 2026-05-14 after the Files-UI evaluation confirmed (a) the library renders correctly as a folder under /DATA, (b) thumbnails are generated, (c) the squash works — a write from ZimaOS appears on /mnt/library as www-data:media (uid 33, gid 10000), matching the existing tree convention used by Nextcloud and mule-images.
Guardrails (in order of importance)
all_squash,anonuid=33,anongid=10000. Every write from ZimaOS records on disk aswww-data:media(uid 33, gid 10000), the same identity Nextcloud and mule-images use. Keeps the existing tree convention from drifting. Seeproject_media_perms.- Subnet restriction
192.168.8.0/24. No public/mesh access; LAN only. no_subtree_check+sec=sys— standard performance/auth pair for a homelab.- No
crossmntbecause/mnt/libraryis a single ext4 filesystem on the host (no nested mounts to traverse).
What we're not doing yet
- No per-subdir export. ZimaOS sees the whole tree; access is controlled by filesystem permissions (
drwxr-x---private dirs likedocuments/,notes/,heaper/aren't readable bymediagroup, so ZimaOS-as-squashed-uid won't see them either). - No write-back. Until we promote to
rw, ZimaOS can't write — eliminates the lock-domain split concern between NFS clients (NLM/v4) and local LXCs (POSIX flock). - No Authentik / forward-auth. NFS doesn't sit behind HTTP, so the standard caddy+authentik path doesn't apply. Subnet ACL is the only auth.
Why this LXC exists (vs serving from host)
We considered three options before building this:
| Option | Outcome |
|---|---|
| NFS on hubris bare-metal host | Best performance, but adds long-lived NFS/RPC daemons to a host with a recent crash episode (hubris crash 2026-04-21/22). Rejected. |
| SMB on host | Same host-blast-radius problem, plus 30–50% lower throughput than NFS on Linux↔Linux. Rejected. |
| NFS in a dedicated LXC ← this | Within ~2% of host performance (LXC is namespace isolation; IO path is unchanged), zero new daemons on hubris, matches the existing fleet pattern. Selected. |
Rationale lives in the install plan /root/.claude/plans/i-wannt-you-to-nifty-muffin.md on hubris.
Operations
- Reload exports after editing
/etc/exports:pct exec 102 -- exportfs -ra - List active exports:
pct exec 102 -- exportfs -v - Watch from outside:
showmount -e 192.168.8.200 - Service health:
pct exec 102 -- systemctl is-active nfs-server rpcbind - Restart cleanly:
pct restart 102(ZimaOS will retry the mount vianofail) - Destroy + rebuild:
pct stop 102 && pct destroy 102 --purge— reversible in seconds; only ZimaOS notices
Open items
- Consider tightening the export to subdirs (e.g.
movies,tv,music,audiobooks,books,images,podcasts,roms) if you don't want ZimaOS reachable intodocuments/,notes/,heaper/, etc. — though those private subdirs are already invisible tomedia-group perms. - ZimaOS architecture finding: the Drives panel only enumerates physical/block devices via
GET /v2/local_storage/storages(read-only API, no POST). Network shares cannot appear as Drives — they show up as folders in Files. This is intentional in CasaOS's design; don't try to work around it. Library-as-folder is the supported model. - Consider adding Samba to this LXC if a future Mac/iOS client needs SMB on the same tree — same LXC, no host changes.
- No PBS backup (no PBS configured on hubris); the container is fully described in this page +
pct config 102, rebuild from scratch in <2 min if lost.
Related
- 100-zimaos — the only consumer today
- media permissions — uid 33 / gid 10000 standard
- DNS —
nfs-export.hubris.networkentry (direct, no Caddy)
Changelog
2026-05-14 — Promoted to rw; squash behaviour verified
After ZimaOS Files UI evaluation passed (library renders as folder under /DATA, thumbnails work, ZimaOS Drives panel ignores NFS by design), flipped export to rw. Tested: writing /DATA/library/.zimaos-rw-test from ZimaOS appears on hubris's /mnt/library owned www-data:media (uid 33, gid 10000), confirming all_squash,anonuid=33,anongid=10000 works as designed. Also discovered the dead end: ZimaOS's GET /v2/local_storage/storages is the source of the Drives panel; it returns only physical storage and rejects POST/PUT — network shares cannot be promoted to Drives.
2026-05-14 — LXC built; NFS export live (read-only)
Privileged Debian 13 container created with bind-mount /mnt/library. nfs-kernel-server installed and enabled; export /mnt/library to 192.168.8.0/24 with ro,all_squash,anonuid=33,anongid=10000. Smoke-tested from hubris host (mounted, listed library tree, confirmed RO). nfs-export.hubris.network added to LXC 124 dnsmasq.