Release builds on Gitea Actions: macOS app, Ubuntu, headless Linux, server
- .gitea/workflows/release.yml: on a v* tag, a Linux runner builds and
packages the Ubuntu, headless and server bundles; a Mac runner makes
AnyBot.app. Both attach their files to the tag's release.
- deploy/ci: the Linux build image (Ubuntu 22.04), packaging, release
upload, runner settings, and a server bundle that runs the prebuilt
binaries (no compiling on the server).
- deploy/mac/bundle.sh: AnyBot.app with its icon, signed ad hoc, zipped.
- relay/Dockerfile: copy src/wire.rs too (the relay needs it since the
lasting connection).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 14:07:46 +00:00
|
|
|
|
# The server from a release package (prebuilt binaries in ../../bin). Made from deploy/server/docker-compose.yml.
|
|
|
|
|
|
# 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: deploy/server/Dockerfile.server-relay
|
|
|
|
|
|
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:-}"
|
Bug sweep: gates, relay 2FA, Windows input, snapshots, encodings
Permissions and reach
- a file leaving a computer passes the same questions as reading it;
"looking" shell commands that do more than look ask first
- a symlink out of the work/sealed folder counts as outside it
(real paths, not just lexical ones); the search walk skips links
- web_fetch and skill_install read the public web only: localhost, the
LAN and cloud metadata are refused, at every redirect
- preview shows a file without running it; browser_upload may ask
- vault: logins no longer match across shared suffixes (pages.dev,
com.tw, ...); registrable_domain knows public suffixes
- axwrite: found elements are retained (use-after-free)
Relay
- replacing or turning off 2FA needs the current code (rate-limited);
new recovery codes only count once enrollment is verified
- a removed computer loses its socket and its `call` access
- a site name taken by another account answers 409
- RELAY_TRUST_PROXY: the login lock counts the caller's address, not
the proxy's (compose files and README)
- httpd: half a body is not a request
Desktop
- sign-in, join and restore work with 2FA on (code field; --serve reads
ANYBOT_ACCOUNT_CODE; the setup wizard points to a pairing code)
- Windows: text was typed twice; modifiers are held through click, drag
and scroll; horizontal scroll; screen control is no longer refused
- a recording that hits the limit is transcribed, not thrown away
- bot's computer: a new home volume restores the snapshot; a snapshot
is read through before the home is wiped; a failed volume removal
stops reset/restore
- events of a stopped turn no longer land in the next one; each channel
message gets a turn of its own
- saving a bot's settings keeps what it got meanwhile (three-way merge);
a save file that cannot be read is kept
- pages in Big5/GBK/Shift_JIS are read in their own encoding
(encoding_rs); osascript output past 64 KB no longer stalls
- pick_tab keeps a job's own non-http tab; pictures larger than the
texture limit are fitted; the auto-update time field takes typing
- skills live in <data>/skills; memories are unnumbered in the prompt;
the phone may skillify and skill_install
CI
- the test step fails when the tests fail (it piped into tail)
Tests: anybot 268 passed, 27 ignored; relay 16 passed; clippy unchanged.
Not run: Windows on a real machine (win.rs type-checked alone), the
Docker paths of the bot's computer, the live accessibility writes.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-10 03:46:17 +00:00
|
|
|
|
# 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"
|
Release builds on Gitea Actions: macOS app, Ubuntu, headless Linux, server
- .gitea/workflows/release.yml: on a v* tag, a Linux runner builds and
packages the Ubuntu, headless and server bundles; a Mac runner makes
AnyBot.app. Both attach their files to the tag's release.
- deploy/ci: the Linux build image (Ubuntu 22.04), packaging, release
upload, runner settings, and a server bundle that runs the prebuilt
binaries (no compiling on the server).
- deploy/mac/bundle.sh: AnyBot.app with its icon, signed ad hoc, zipped.
- relay/Dockerfile: copy src/wire.rs too (the relay needs it since the
lasting connection).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 14:07:46 +00:00
|
|
|
|
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.server-anybot
|
|
|
|
|
|
restart: unless-stopped
|
|
|
|
|
|
depends_on: [relay]
|
|
|
|
|
|
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:-}"
|
2026-11-09 08:36:51 +00:00
|
|
|
|
# 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"
|
Release builds on Gitea Actions: macOS app, Ubuntu, headless Linux, server
- .gitea/workflows/release.yml: on a v* tag, a Linux runner builds and
packages the Ubuntu, headless and server bundles; a Mac runner makes
AnyBot.app. Both attach their files to the tag's release.
- deploy/ci: the Linux build image (Ubuntu 22.04), packaging, release
upload, runner settings, and a server bundle that runs the prebuilt
binaries (no compiling on the server).
- deploy/mac/bundle.sh: AnyBot.app with its icon, signed ad hoc, zipped.
- relay/Dockerfile: copy src/wire.rs too (the relay needs it since the
lasting connection).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 14:07:46 +00:00
|
|
|
|
volumes:
|
|
|
|
|
|
- anybot-data:/data
|
2026-11-09 08:36:51 +00:00
|
|
|
|
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
|
Release builds on Gitea Actions: macOS app, Ubuntu, headless Linux, server
- .gitea/workflows/release.yml: on a v* tag, a Linux runner builds and
packages the Ubuntu, headless and server bundles; a Mac runner makes
AnyBot.app. Both attach their files to the tag's release.
- deploy/ci: the Linux build image (Ubuntu 22.04), packaging, release
upload, runner settings, and a server bundle that runs the prebuilt
binaries (no compiling on the server).
- deploy/mac/bundle.sh: AnyBot.app with its icon, signed ad hoc, zipped.
- relay/Dockerfile: copy src/wire.rs too (the relay needs it since the
lasting connection).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
2026-11-04 14:07:46 +00:00
|
|
|
|
volumes:
|
|
|
|
|
|
relay-data:
|
|
|
|
|
|
caddy-data:
|
|
|
|
|
|
anybot-data:
|