LXC 126 stopped and destroyed on hubris. Remove all live references: inventory, container doc, host file, README, containers index, auto-deploy pipeline, DNS entry, SSH access table, nfs-export mount list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
90 lines
6.5 KiB
Markdown
90 lines
6.5 KiB
Markdown
# 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](../vms/100-zimaos.md), 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 for `nfs-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](../infrastructure/media-permissions.md).
|
||
|
||
## 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)
|
||
|
||
1. **`all_squash,anonuid=33,anongid=10000`.** Every write from ZimaOS records on disk as `www-data:media` (uid 33, gid 10000), the same identity Nextcloud and mule-images use. Keeps the existing tree convention from drifting. See [`project_media_perms`](../infrastructure/media-permissions.md).
|
||
3. **Subnet restriction `192.168.8.0/24`.** No public/mesh access; LAN only.
|
||
4. **`no_subtree_check`** + **`sec=sys`** — standard performance/auth pair for a homelab.
|
||
5. **No `crossmnt`** because `/mnt/library` is 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 like `documents/`, `notes/`, `heaper/` aren't readable by `media` group, 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](../investigations/index.md)). 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](https://git.hubris.network/dtoro/Homelab-Docs) `/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 via `nofail`)
|
||
- **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 into `documents/`, `notes/`, `heaper/`, etc. — though those private subdirs are already invisible to `media`-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](../vms/100-zimaos.md) — the only consumer today
|
||
- [media permissions](../infrastructure/media-permissions.md) — uid 33 / gid 10000 standard
|
||
- [DNS](../infrastructure/dns.md) — `nfs-export.hubris.network` entry (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.
|