archy/.claude/rules/containers.md
Dorian 5008cb6d1f fix: rootless UID mapping corrections + credential injection
- Correct off-by-one in UID mapping: container UID N → host UID
  (100000 + N - 1), not (100000 + N)
- Deploy script auto-fixes UID ownership on every deploy
- Bitcoin UI nginx uses __BITCOIN_RPC_AUTH__ placeholder injected
  from secrets at deploy time
- container rules updated for rootless podman architecture

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:57:16 +00:00

2.5 KiB

globs
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