# Albert on the server. One volume (`albert-data` -> /data) holds all runtime state: # the subscription tokens, the kaeru memory vault, per-channel history, and the # scheduler alarms — so restarts and image rebuilds never lose anything. # # docker compose build # build the image (see README: add swap on 2 GB) # docker compose run --rm albert login # one-time: sign in with the ChatGPT subscription # docker compose up -d # run the service # docker compose logs -f # live logs # # Voice (hearing / speaking, long recordings included) and image generation run natively # on the ChatGPT subscription through Albert's own connectors, reading /data/auth.json as # the service user — nothing to set up beyond `login`. No sandboxed script reads the # token, so it stays 0600. services: albert: build: context: . dockerfile: docker/Dockerfile image: albert:latest container_name: albert restart: unless-stopped env_file: contrib/deploy/.env # The container runs as the unprivileged `albert` user (see docker/Dockerfile). # forkd drops skill scripts to `albert-scripts`, which from a non-root process needs # these two capabilities — the same ones the systemd unit grants as AmbientCapabilities. cap_add: - SETUID - SETGID volumes: - albert-data:/data # Connector manifests (owner_chat, which calendars) — mounted so you can edit # them without rebuilding the image. Read-write so the telegram ACL can persist. - ./config:/opt/albert/config # Persona + operating instructions, mounted so they can be edited live — # they're hot-reloaded by mtime (no rebuild, no restart). - ./soul.md:/opt/albert/soul.md:ro - ./system.md:/opt/albert/system.md:ro # Live config — an OPERATOR-OWNED, git-ignored file, NOT a tracked one. # Seed it once before the first run: cp contrib/deploy/albert.toml ./albert.local.toml # Mounted read-write: the self-config skill edits this exact file, so its changes # must land on a real persistent file, not the image's ephemeral layer. The tracked # contrib/deploy/albert.toml stays a pristine default. (Create it first — Docker # would otherwise make an empty directory in its place.) - ./albert.local.toml:/opt/albert/albert.toml # `albert login` needs an interactive terminal for the paste fallback. stdin_open: true tty: true volumes: albert-data: