feat(albok-service): unit 6 sealed wing personal/sealed — LUKS2 volume, gid 1513, rslave bind of /srv/albok/sealed
albok-dev's host ask under Prime's goal "land all of u6". A 20 GiB LUKS2 file with ext4, keyed only from the vault (piped over ssh, never on the host's disk). The mountpoint is immutable while unmounted, and the mounted root is 1500:1513 0750 with .albok-wing. The parent is bound into the container with rslave propagation: a lock then unlock with the service running showed through without a restart. The wing is not in albok.yaml yet (albok-dev's release). Runbook and backup posture are in the README.
This commit is contained in:
@@ -185,6 +185,7 @@ Every vLLM seat on a shared card (GPU 0, GPU 1) has byte-pinned KV (`--kv-cache-
|
||||
|
||||
## Recent decisions
|
||||
|
||||
- `[2026-10-16]` **albok unit 6: the first encrypted wing `personal/sealed` provisioned on nh3-albok** (Prime's goal "land all of u6", via albok-dev): a 20 GiB LUKS2 file + ext4, key ONLY in vault `albok/wing-key-personal-sealed`, gid 1513, mountpoint `/srv/albok/sealed/personal.sealed` (immutable while unmounted), the parent bound rslave. The lock/unlock lifecycle was tested with the container running. It is not in albok.yaml until albok-dev's release. Runbook: `stacks/albok-service/README.md` § Sealed. After an nh3-albok reboot the wing is LOCKED until someone unlocks it.
|
||||
- `[2026-10-13]` **pewpewstudio LIVE on nh3-docker :8185** (Prime via pewpew-dev): api + Caddy front; the Host allowlist must sit in a `route` (foreign Host 400); DB, assets and shop config on named volumes. → `stacks/pewpewstudio/README.md`
|
||||
- `[2026-10-13]` **infra-ops on esh-nas (CT 103) + per-host satellite keys (Prime)** — bootstrapped via pct from esh-pve-nas; satellite-1 authorized on esh-nas only (`playbooks/files/infra-ops-satellite-keys`); its login test + name pending.
|
||||
- `[2026-10-13]` **Worldtree memory gate: 0730 harness error (the tagger's MalformedClassification latched the writer), re-run `20261013T160414Z` PASS (median 0.83)** — the latch fix is worldtree-dev's (thread `01M4V035SF73XKVG3NRVX37XQ6`).
|
||||
|
||||
@@ -184,3 +184,32 @@ docker push gitea.phasefinal.com/pfi/albok-service:<ver> # then pin the new
|
||||
Mount `/srv/albok/store` **`:ro`**, `group_add` the read group's **numeric** gid (1510 / 1511), set
|
||||
`GIT_OPTIONAL_LOCKS=0`, and add `safe.directory` for the path as the viewer sees it. Nothing else
|
||||
may mount the store read-write.
|
||||
|
||||
## Sealed (encrypted) wings: unit 6 (2026-10-16)
|
||||
|
||||
The first is `personal/sealed`: restricted, default-deny, gid **1513 `albok-sealed`**. It is empty, has no Nemi source,
|
||||
and what goes in it is Prime's call. albok-dev provisioned it on Prime's goal "land all of u6". **It is not yet in
|
||||
`albok.yaml`**: albok-dev sends that stanza with the release that carries the encrypted-wing replay fix. Until then the
|
||||
service ignores the mount.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| container | `/srv/albok/luks/personal.sealed.img`: a 20 GiB file (root 0600, dir 0700), LUKS2 aes-xts, ext4 inside (label `personal.sealed`). The file grows later with `truncate` + `cryptsetup resize` + `resize2fs` |
|
||||
| key | vault **`albok/wing-key-personal-sealed`** (64 random base64 chars). It is never written to nh3-albok's disk: it is piped in over ssh, and infra-ops' sudo there logs output, not input |
|
||||
| mapping | `/dev/mapper/albok-personal-sealed` |
|
||||
| mountpoint | **`/srv/albok/sealed/personal.sealed`**: EMPTY and `chattr +i` while unmounted, so nothing can write plaintext into a locked wing (root's `touch` there fails, tested). The mounted root is `1500:1513 0750`, holding `.albok-wing` (`1500:1513 0640`) and ext4's `lost+found`. The service creates `store/` and `private/` there on its first start with the wing configured |
|
||||
| container view | the parent `/srv/albok/sealed` is bound with `propagation: rslave`, so a lock or unlock on the host shows inside the RUNNING container (tested both ways) |
|
||||
|
||||
```bash
|
||||
# UNLOCK (after a VM reboot the wing comes up LOCKED, by design: no crypttab). No service restart is needed.
|
||||
secret get albok/wing-key-personal-sealed | tr -d '\n' | ssh infra-ops@10.100.50.44 \
|
||||
'sudo -n cryptsetup open --type luks2 --key-file=- /srv/albok/luks/personal.sealed.img albok-personal-sealed \
|
||||
&& sudo -n mount /dev/mapper/albok-personal-sealed /srv/albok/sealed/personal.sealed'
|
||||
# LOCK: the service holds the wing's SQLite/Chroma open, so umount refuses while it runs.
|
||||
ssh infra-ops@10.100.50.44 'cd /opt/docker/compose/albok-service && sudo -n docker compose stop \
|
||||
&& sudo -n umount /srv/albok/sealed/personal.sealed && sudo -n cryptsetup close albok-personal-sealed \
|
||||
&& sudo -n docker compose start'
|
||||
```
|
||||
**Backups:** nh3-albok has NO file-level backup, so nothing ever copies the plaintext. Its whole-VM vzdump (nh3-pve-2,
|
||||
21:30) holds the LUKS file, which is ciphertext; the key lives only in the vault. Never add a file-level job that walks
|
||||
`/srv/albok/sealed`. ⚠ Losing the vault entry loses the wing.
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
# ⚠ Nothing else may mount /srv/albok/store read-write. Viewers mount it :ro with group_add by gid
|
||||
# (1510 albok-read, 1511 albok-personal) and need GIT_OPTIONAL_LOCKS=0 + a safe.directory entry.
|
||||
# 1512 albok-feedback (restricted wing personal/agent-feedback) is default-deny: no viewer gets it.
|
||||
# 1513 albok-sealed (encrypted wing personal/sealed, unit 6) likewise; its plaintext exists only while unlocked.
|
||||
services:
|
||||
albok-service:
|
||||
image: gitea.phasefinal.com/pfi/albok-service:0.1.23@sha256:026de87f3ca3907e9eb0a2a2489a7507f69f9f0eca50e8e8be3fcfcb36a03de3
|
||||
@@ -25,12 +26,20 @@ services:
|
||||
- "1510"
|
||||
- "1511"
|
||||
- "1512" # albok-feedback: restricted wing personal/agent-feedback
|
||||
- "1513" # albok-sealed: encrypted wing personal/sealed (unit 6, 2026-10-16)
|
||||
volumes:
|
||||
- /srv/albok/store:/srv/albok/store
|
||||
- /srv/albok/private:/srv/albok/private
|
||||
- /srv/albok/etc/albok.yaml:/etc/albok/albok.yaml:ro
|
||||
# the read groups must RESOLVE BY NAME inside the container (layout.py uses grp.getgrnam)
|
||||
- /opt/docker/conf/albok-service/group:/etc/group:ro
|
||||
# Unit 6 encrypted wings: the PARENT of the LUKS mountpoints, bound with slave propagation, so a wing unlocked
|
||||
# (cryptsetup open + mount) after the container started is visible inside it without a restart (README § Sealed).
|
||||
- type: bind
|
||||
source: /srv/albok/sealed
|
||||
target: /srv/albok/sealed
|
||||
bind:
|
||||
propagation: rslave
|
||||
mem_limit: 8g # 4g on nh3-docker (7.7 GiB shared host); 12 GiB VM to itself now
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8390/health', timeout=5).status == 200 else 1)"]
|
||||
|
||||
@@ -40,3 +40,4 @@ albok:x:1500:
|
||||
albok-read:x:1510:albok
|
||||
albok-personal:x:1511:albok
|
||||
albok-feedback:x:1512:albok
|
||||
albok-sealed:x:1513:albok
|
||||
|
||||
Reference in New Issue
Block a user