Ctrl K
ComunidadGuías…

docs/adr/0003-backup-helper-container.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Backup uses one standalone helper container, the single exception to the Compose mutation boundary

App files can be owned by the container user namespace, not the CLI's, so the CLI cannot read or restore their owners directly. Backup and Restore therefore run a standalone `docker run --rm` helper outside the Compose Project, pinned to the digest `docker.io/library/alpine@sha256:5291449c3df73caf6ed85e649dec1b9e818b39a5d8c871e97afc13e9cd5e8fa8` (pulled only when missing). This is the only sanctioned exception to "one Compose project is the mutation boundary": it mounts exactly one selected App directory at `/owned` (read-only while archiving, read-write while applying metadata or removing that App's files), never the Docker socket, and is otherwise confined by `--network none`, `--read-only`, `--user 0:0`, `--security-opt no-new-privileges` and `--cap-drop ALL`, re-adding only `DAC_OVERRIDE`, plus `CHOWN` and `FOWNER` for a metadata run. The directory must resolve inside its Project with no unowned symlink ancestor. Its generated name, `selfhost-backup-` plus 16 hex characters, scopes cleanup: on any error the CLI `docker rm --force`es that exact name, tolerates an already-removed container, and waits until that name is gone rather than touching anything else.

## Symlink policy

A Backup keeps relative symlinks whose lexical destination is also inside the selected App, and a Restore recreates them only when that destination is among the selected paths. Absolute symlinks and relative links that leave the selected App are refused, at archive time and again at restore time, naming the link and its target: a Restore may run as root, so following a link outside the App could mutate paths the Backup never owned, and a Backup covers only its selected Apps. The refusal message points here (`see docs/adr/0003-backup-helper-container.md`).