--- globs: - "**/container/**" - "**/manifest*" - "**/*podman*" - "**/Containerfile" - "**/Dockerfile" - "**/first-boot*" - "**/container-doctor*" --- # Container Security Rules (Archipelago — Rootless Podman) ## Rootless Podman Architecture - Podman runs as `archipelago` user (UID 1000), NOT root — never use `sudo podman` - UID namespace mapping via subuid: container UID N → host UID (100000 + N) - Container images stored in `~/.local/share/containers/storage/` (NOT /var/lib/containers) - Container subnet: `10.89.0.0/16` (rootless), not `10.88.0.0/16` (rootful) - XDG_RUNTIME_DIR must be `/run/user/1000` — required for podman socket - `loginctl enable-linger archipelago` required for containers to survive logout ## Container Security (Non-Negotiable) - Drop ALL capabilities, add only what's required (`--cap-drop=ALL --cap-add=...`) - Set `--security-opt=no-new-privileges:true` on all containers - Use `--read-only` + tmpfs where possible (safe apps: searxng, grafana, filebrowser, electrumx, nostr-rs-relay, ollama, indeedhub) - Pin image versions — never use `:latest` tag - Mount secrets as read-only files, never pass as environment variables when possible - Set memory and CPU limits on all containers - All containers must have `--restart unless-stopped` ## Volume Ownership (Critical for Rootless) - Volume directories must be owned by the MAPPED UID, not the container UID - Formula: `host_uid = 100000 + container_uid` - UID 0 (most apps) → `sudo chown -R 100000:100000 /var/lib/archipelago/{app}` - UID 101 (bitcoin) → `sudo chown -R 100101:100101 /var/lib/archipelago/bitcoin` - UID 70 (postgres) → `sudo chown -R 100070:100070 /var/lib/archipelago/postgres-*` - UID 472 (grafana) → `sudo chown -R 100472:100472 /var/lib/archipelago/grafana` - UID 999 (mariadb) → `sudo chown -R 100999:100999 /var/lib/archipelago/mysql-*` ## Systemd Service Requirements - `ProtectHome=no` — podman needs `~/.local/share/containers/` - `PrivateTmp=no` — podman runtime uses `/tmp/podman-run-1000/` - `RestrictNamespaces=` must NOT be set — rootless podman creates user namespaces - `SystemCallFilter=` must NOT be set — rootless podman needs clone/unshare - UFW `DEFAULT_FORWARD_POLICY="ACCEPT"` — required for LAN access to container ports ## Network Rules - Apps needing inter-container DNS: use `--network=archy-net` (bitcoin, lnd, electrumx, mempool, btcpay, fedimint) - Standalone apps: default bridge network - Tailscale only: `--network=host` + `NET_ADMIN` + `NET_RAW` + `/dev/net/tun`