AnyBot/deploy/server/docker-compose.yml

103 lines
5.5 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Everything on one small server: the account server (relay), HTTPS (Caddy), and AnyBot itself.
# Easiest: ./setup.sh (asks for the domain, account and keys, writes .env and Caddyfile, starts
# everything and checks it). By hand:
# 1. Point your domain at the server; copy ../../relay/Caddyfile here and put the domain in it.
# 2. Put your account name and password in .env (see .env.example).
# 3. docker compose up -d
# 4. On the phone open https://your-domain, create the account (first time), and use it.
# AI keys: set them in .env, or set ANYBOT_RESTORE_FROM_ACCOUNT=1 to start from the newest backup
# your Mac made (bots, chats, routines and the keys you set there).
#
# 大腦: this AnyBot is the brain of the account. It keeps the bots, chats, memory and routines,
# and works even while your computers sleep. On each of your computers: 設定 › 手機與帳號 ›
# 大腦 › 「改用它當大腦」. Those computers then show these bots, and the bots can use them as hands
# (screen, files, browser), asking you first as usual. A Linux computer without a screen can be
# hands too: run `anybot setup` there and pick this brain.
services:
relay:
build:
context: ../..
dockerfile: relay/Dockerfile
args: { JOBS: "${ANYBOT_BUILD_JOBS:-}" }
restart: unless-stopped
environment:
# Your public address (for the links of sites the bots publish), e.g. https://anybot.example.com
ANYBOT_RELAY_PUBLIC_URL: "${ANYBOT_RELAY_PUBLIC_URL:-}"
ANYBOT_RELAY_INVITE: "${ANYBOT_RELAY_INVITE:-}"
# Caddy (or `tailscale serve`) is in front: the caller's address is the one it reports.
# Without this every login attempt counts as coming from the proxy, and a few wrong
# passwords from anyone lock that account for everyone.
RELAY_TRUST_PROXY: "1"
volumes:
- relay-data:/data
caddy:
image: caddy:2
restart: unless-stopped
ports: ["80:80", "443:443"]
volumes:
# Written by setup.sh (your domain); ../../relay/Caddyfile is the template.
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
depends_on: [relay]
anybot:
build:
context: ../..
dockerfile: deploy/server/Dockerfile
args: { JOBS: "${ANYBOT_BUILD_JOBS:-}" }
restart: unless-stopped
depends_on: [relay]
# A second wall for the bots' computer (optional, Linux): install gVisor on this host
# (see gvisor.dev/docs "Installation" for the apt repository + `apt-get install runsc`,
# then register it in /etc/docker/daemon.json: {"runtimes": {"runsc": {"path": "runsc"}}}
# and `systemctl restart docker`). In AnyBot: 設定 › 電腦 › 在哪裡執行 › 容器隔離 →
# 「強隔離(gVisor)」, then rebuild the computer (更新). The box gets a virtualized
# kernel and Chromium's own sandbox comes back on. On a host without runsc the box won't
# start — switch 容器隔離 back to 標準.
environment:
ANYBOT_ACCOUNT: "http://relay:8080|${ANYBOT_USER}"
ANYBOT_ACCOUNT_PASSWORD: "${ANYBOT_PASSWORD}"
ANYBOT_HOST_NAME: "${ANYBOT_HOST_NAME:-雲端 AnyBot}"
# First start on a new server: make the account (the first one needs no invite).
ANYBOT_ACCOUNT_CREATE: "1"
ANYBOT_RELAY_INVITE: "${ANYBOT_RELAY_INVITE:-}"
XAI_API_KEY: "${XAI_API_KEY:-}"
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY:-}"
OPENAI_API_KEY: "${OPENAI_API_KEY:-}"
GEMINI_API_KEY: "${GEMINI_API_KEY:-}"
ANYBOT_RESTORE_FROM_ACCOUNT: "${ANYBOT_RESTORE_FROM_ACCOUNT:-}"
# The bots' computer goes by its own name: a desktop AnyBot on this same machine keeps
# "anybot-box" for itself (and used to pause the brain's one as idle).
ANYBOT_BOX_NAME: "anybot-brain-box"
# The Docker socket is not mounted here any more (a mounted socket is full control of this
# host). The bots' computer is driven through the filtered proxy below, which only answers
# the calls cloudbox.rs makes: containers (run/start/stop/rm/inspect/ps), exec, volumes,
# images and the box image build. DOCKER_HOST is the plain `docker` CLI default, which is
# what src/cloudbox.rs uses when its own docker_host setting is empty.
DOCKER_HOST: "tcp://docker-socket-proxy:2375"
volumes:
- anybot-data:/data
docker-socket-proxy:
# https://github.com/Tecnativa/docker-socket-proxy: a small nginx in front of the Docker
# socket with an endpoint allowlist. Keep this list minimal: adding an API here widens what
# a compromised brain can do on this host (no AUTH, no SECRETS, no SWARM, no plugins).
image: tecnativa/docker-socket-proxy:0.3.0
restart: unless-stopped
environment:
CONTAINERS: "1" # run, start, stop, rm, inspect, ps (the box's lifecycle)
EXEC: "1" # docker exec: every screen step, box_exec, snapshots
IMAGES: "1" # inspect/create the box image (build uploads it)
BUILD: "1" # 更新/重建 builds the box image
VOLUMES: "1" # anybot-box-home: inspect, create, rm (Reset/Restore)
NETWORKS: "1" # inspect/attach (docker run needs the bridge network)
POST: "1"
GET: "1"
# On a rootless-Docker host this has to be DOCKER_SOCKET=/run/user/<uid>/docker.sock in .env:
# setup.sh finds it and writes it (also into a kept .env). The rootful default is
# /var/run/docker.sock; on a rootless host that is another daemon and the proxy answers 503.
volumes:
- ${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock:ro
volumes:
relay-data:
caddy-data:
anybot-data: