Files
serverAppConfigs/serverAppConfigs-docs/Architecture/Storage Policy.md
T
Frank 272ef6f0b0 docs: record quadlet standardization of dankserver media + dankclaw data roots
Phase 1/2 of the podman standardization plan: service pages updated to the
quadlet reality (units, Containers data roots, env-file secret convention,
the v1-generator findings each caught live), Storage Policy documents the
two rootless ownership regimes and the merge-move migration, Deployment
Flow's service-manager table no longer claims dankserver media is bare
inventory-only. Bundle change log entry added.
2026-09-01 13:57:33 -07:00

61 lines
2.6 KiB
Markdown

# 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`).
```bash
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
- [[Deployment Flow]]
- [[Gitea]] — the original bind-mount stack, now on the Containers layout
- [[Backblaze Integration]] — future backup target for these mounts