Files
serverAppConfigs/serverAppConfigs-docs/Architecture/Storage Policy.md
T
Frank 93d1181fee docs: OKF v0.1 compliance pass + fact-check + 3 research briefs
- Migrate all 127 non-reserved docs to OKF v0.1 frontmatter (type/description/tags/timestamp); fix 13 YAML issues, 2 duplicate-FM blocks, strip reserved-page FM
- Restructure log.md to OKF (## YYYY-MM-DD, newest-first)
- Fact-check against scripts/AGENTS.md ground truth: fix 6 false 'Active' banners on retired runbooks, 96->114 GiB GTT, deployment.md vs deploy-plan.py/deploy-remote.sh, Deployment Flow frank-medium=Quadlet, Calibre 9.9.0->9.15.0 + CVE-2025-7404 conflation, Copyparty v1.20.24, RomM 5.3.0 breaking change
- Move *arr docs to new FrankBook-Pro/ section (git mv, link-safe)
- Write active runbook bodies from ground truth (frank-large, frank-small)
- Add 3 research briefs + HTML report: Local TTS and Voice Cloning, AI Job Search and Resume Tools, Most Popular Self-Hosted AI Apps (Jun-Sep 2026)
- Add upstream-version rows to ComfyUI/OpenWebUI/Hermes app docs
- All 336 tests pass; 136 pages, 0 unresolved wikilinks
2026-09-22 02:09:41 -07:00

2.8 KiB

type, description, tags, timestamp
type description tags timestamp
reference All persistent data uses **bind mounts**: a host directory mapped directly into the container.
architecture
storage
2026-09-01

Storage Policy

All persistent data uses bind mounts: a host directory mapped directly into the container. No named volumes. This matches the preference of this repo and the existing Gitea stack on Dankclaw.

Why Bind Mounts

  • The exact host location of every byte is visible and controllable.
  • Backups are a simple tar of known host directories.
  • The data survives container recreation and podman-compose down.
  • Ownership is explicit: everything runs as UID 1000 (dank) so host tools can read it.

Conventions

Stack Host data root
Dankserver /home/dank/Containers/<svc>/ (romm, jellyfin, calibre-web, copyparty)
Dankclaw /home/dank/Containers/<svc>/ (caddy, gitea, authentik, hermes, …)

This layout was standardized on 2026-09-01. The old /opt/<service> roots were migrated by the deployers' migrate_data_root (merge-move, numeric ownership preserved); /opt holds no live container data on either host.

Ownership

Containers are rootless. Two regimes exist and the deployer must respect both:

  • PUID/PGID images (linuxserver calibre-web, jellyfin): data is owned by host uid 1000 (dank) — plain chown is safe.
  • Mapped-uid images (official mariadb, redis, authentik, postgres): files land in the subuid range (e.g. 100998 for container uid 999). Renaming such a directory requires root (rename needs write on the directory itself) and re-chowning to 1000 breaks the container's internal user. Migrations therefore use sudo mv (numeric-preserving) and skip the chown pass (migrate_data_root … keep).
stat -c '%u %n' /home/dank/Containers/romm/mariadb   # 100998 = mapped, leave it

Secrets

Secrets never live in bind-mounted configs that get committed. The quadlet convention on both hosts:

  1. One host-local env file per stack at /home/dank/Containers/<svc>/env (mode 0600), referenced from the unit's [Service] EnvironmentFile= so ${VAR} expansion works at ExecStart time; never committed.
  2. .env files in the checkout (git-ignored, .env.example committed as template) for compose-era and Caddy-rendered secrets.

Deployed units hold only variable expansions (${COPAY_ACCOUNT} …), never literals — enforced by the no secret material seams. The live Gitea database password exists only in /home/dank/Containers/gitea/env on Dankclaw. A test enforces that it never appears in this repo.

See Also