-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
83 lines (76 loc) · 3.51 KB
/
Copy pathdocker-compose.yml
File metadata and controls
83 lines (76 loc) · 3.51 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
# Hardened local/edge runtime for protoAgent.
#
# `docker compose up --build` runs the agent locked down: read-only root
# filesystem, all Linux capabilities dropped, no privilege escalation, and
# the bundled deploy/seccomp-profile.json applied (Docker reads it from the
# host at compose time, not from the image). The few writable paths are
# explicit — /tmp + /home as ephemeral tmpfs, agent state in named volumes.
#
# Backported from the protoLabs fleet (pwnDeck), generalised to neutral
# defaults. Tune the resource ceiling and ports per deployment.
services:
agent:
build:
context: .
dockerfile: Dockerfile
image: ghcr.io/protolabsai/protoagent:latest
container_name: protoagent
restart: unless-stopped
# Readiness — /healthz is 200 only once the agent graph is ready (503 during
# cold start). With restart:unless-stopped this lets the daemon detect a
# hung-but-alive process. start_period covers the first-compile boot.
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:7870/healthz"]
interval: 30s
timeout: 3s
start_period: 60s
retries: 3
# ── Hardening ──────────────────────────────────────────────────────────
security_opt:
- no-new-privileges:true
- seccomp=deploy/seccomp-profile.json
cap_drop:
- ALL
read_only: true
# ── Writable surfaces ──────────────────────────────────────────────────
# Ephemeral scratch (tmpfs); uid/gid match the image's non-root sandbox
# user (Dockerfile SANDBOX_UID=1001). PYTHONDONTWRITEBYTECODE avoids
# __pycache__ writes against the read-only /opt/protoagent tree.
tmpfs:
- /tmp:size=256M,uid=1001,gid=1001
- /home/sandbox:size=64M,uid=1001,gid=1001
# Persistent state: /sandbox IS the instance root (PROTOAGENT_HOME=/sandbox) —
# live config + secrets + setup marker + SOUL.md (/sandbox/config/*), plugins
# (/sandbox/plugins), knowledge DB, audit log, scheduler jobs all under /sandbox.
volumes:
- protoagent-sandbox:/sandbox
# Published to LOOPBACK only by default: the container binds 0.0.0.0
# internally (entrypoint), so this host-side port binding is the network
# boundary. To expose the agent beyond this machine, set A2A_AUTH_TOKEN
# below AND widen the binding (e.g. "7870:7870").
ports:
- "127.0.0.1:7870:7870"
environment:
- PYTHONDONTWRITEBYTECODE=1
- AGENT_NAME=${AGENT_NAME:-protoagent}
# Bearer for the A2A + operator API — REQUIRED if the port is exposed
# beyond loopback. With the default 127.0.0.1 publish above, the
# in-container 0.0.0.0 bind is fenced by the port binding, so the
# token-less boot gate is opted out via PROTOAGENT_ALLOW_OPEN below.
- A2A_AUTH_TOKEN=${A2A_AUTH_TOKEN:-}
- PROTOAGENT_ALLOW_OPEN=${PROTOAGENT_ALLOW_OPEN:-1}
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
# Optional Langfuse tracing — left blank disables it.
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY:-}
- LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY:-}
- LANGFUSE_HOST=${LANGFUSE_HOST:-}
# Modest ceiling so a runaway run can't starve the host. Tune per deploy.
deploy:
resources:
limits:
cpus: "2"
memory: 2G
reservations:
memory: 256M
volumes:
protoagent-sandbox: