Repository navigation
Expand file tree
/
Copy pathcompose.yaml
More file actions
85 lines (80 loc) · 3.12 KB
/
Copy pathcompose.yaml
File metadata and controls
85 lines (80 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Boxes: personal AI agent orchestrator.
#
# docker compose up -d -> http://localhost:3000
#
# The orchestrator serves the dashboard, the API and the /ws gateway on one
# published port. To put it on the internet, add a reverse proxy in front.
# That proxy must forward the WebSocket upgrade on /ws.
#
# The orchestrator creates the box containers at runtime, each on its own
# internal network.
name: boxes
services:
orchestrator:
build:
context: .
dockerfile: orchestrator/Dockerfile
container_name: boxes-orchestrator
restart: unless-stopped
# Optional. The orchestrator validates every setting in it and supplies
# the defaults. Credentials are entered on the settings page instead.
# Keep it outside the repo with: BOXES_ENV=~/.config/boxes.env
env_file:
- path: ${BOXES_ENV:-.env}
required: false
volumes:
# The socket gives access equal to root on the host. The fixed HostConfig
# template, no user strings in a shell, and the authentication of the
# reverse proxy in front limit the risk.
- /var/run/docker.sock:/var/run/docker.sock
# The orchestrator keeps its database, its generated keys and every
# box's files here. /data is the default of DATA_DIR. To mount the
# volume elsewhere, set DATA_DIR to match.
- boxes-data:/data
# The memory limit is a ceiling. The orchestrator buffers a whole attachment
# upload (MAX_ATTACHMENT_MB) and a whole WebSocket frame (16 MiB) in
# memory per request, and holds the ACP connections of every running box.
#
# The process limit covers the threads of node and the git processes that
# fetch the skill repositories.
mem_limit: 1g
pids_limit: 512
ports:
# Loopback by default, because the orchestrator has no authentication
# of its own and controls the host's Docker daemon. A reverse proxy on
# this host reaches it here. A reverse proxy in a container joins this
# project's network and uses orchestrator:3000 instead.
- "${BIND_ADDR:-127.0.0.1}:${HOST_PORT:-3000}:3000"
networks:
- default
depends_on:
- egress-proxy
egress-proxy:
build:
context: .
dockerfile: proxy/Dockerfile
# The orchestrator attaches this container to every box network by this
# name, the default of EGRESS_PROXY_CONTAINER. To rename it, set that
# variable too, or boxes get no egress at all.
container_name: boxes-egress-proxy
restart: unless-stopped
# read_only works because the proxy keeps its policy, its credentials and
# its CA in memory.
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
# The default network carries external egress and the control channel
# the orchestrator pushes the egress policy over. The orchestrator also
# connects the proxy to each box's internal network at runtime.
networks:
- default
# The proxy holds no database and no box state. It buffers each request to
# a credential host in memory, to swap the credential in.
mem_limit: 512m
pids_limit: 256
volumes:
boxes-data:
networks:
default: