diff --git a/deploy/ci/server-compose.yml b/deploy/ci/server-compose.yml index c219f4c..46b60f6 100644 --- a/deploy/ci/server-compose.yml +++ b/deploy/ci/server-compose.yml @@ -53,10 +53,25 @@ services: OPENAI_API_KEY: "${OPENAI_API_KEY:-}" GEMINI_API_KEY: "${GEMINI_API_KEY:-}" ANYBOT_RESTORE_FROM_ACCOUNT: "${ANYBOT_RESTORE_FROM_ACCOUNT:-}" + # Same as deploy/server/docker-compose.yml: the socket goes through the filtered proxy, + # never mounted into the brain. + DOCKER_HOST: "tcp://docker-socket-proxy:2375" volumes: - anybot-data:/data - # The bot's own computer runs as a container next to this one. - - /var/run/docker.sock:/var/run/docker.sock + docker-socket-proxy: + image: tecnativa/docker-socket-proxy:0.3.0 + restart: unless-stopped + environment: + CONTAINERS: "1" + EXEC: "1" + IMAGES: "1" + BUILD: "1" + VOLUMES: "1" + NETWORKS: "1" + POST: "1" + GET: "1" + volumes: + - ${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock:ro volumes: relay-data: caddy-data: diff --git a/deploy/server/docker-compose.yml b/deploy/server/docker-compose.yml index 43eaafe..0b2388e 100644 --- a/deploy/server/docker-compose.yml +++ b/deploy/server/docker-compose.yml @@ -64,10 +64,33 @@ services: # 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 - # The bot's own computer runs as a container next to this one. - - /var/run/docker.sock:/var/run/docker.sock + 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 set DOCKER_SOCKET=/run/user//docker.sock in .env + # (setup.sh writes .env; the rootful default is /var/run/docker.sock). + volumes: + - ${DOCKER_SOCKET:-/var/run/docker.sock}:/var/run/docker.sock:ro volumes: relay-data: caddy-data: