-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
148 lines (142 loc) · 6.74 KB
/
Copy pathdocker-compose.yml
File metadata and controls
148 lines (142 loc) · 6.74 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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Odek in Docker Compose — Restricted (default) and Godmode (all permissions).
#
# Run from this directory (`cd docker`) so the relative paths and `.env`
# resolve correctly. Build context is the repo root (one level up).
#
# Profiles (opt into exactly one at a time):
# restricted Web UI + approval prompts (recommended)
# godmode No prompts; disposable container
# telegram-restricted Telegram bot; approvals via inline keyboards
# telegram-godmode Telegram bot; no prompts
#
# Examples:
# docker compose --profile restricted up --build
# docker compose --profile godmode run --rm odek-godmode run "create build.sh and run it"
# docker compose --profile telegram-restricted up --build -d
services:
# ── Restricted (default) — interactive Web UI with approval prompts ──
odek-restricted:
profiles: ["restricted"]
build:
context: ..
dockerfile: docker/Dockerfile
image: odek:local
env_file: .env
command: ["serve", "--addr", "0.0.0.0:8080", "--no-sandbox"]
ports:
- "127.0.0.1:8080:8080" # Web UI, bound to localhost only
volumes:
- ./workspace:/workspace
- ./config.restricted.json:/home/odek/.odek/config.json:ro
restart: "no"
depends_on: [searxng, llama-embeddings]
# ── Godmode (all permissions) — non-interactive, disposable container ──
odek-godmode:
profiles: ["godmode"]
build:
context: ..
dockerfile: docker/Dockerfile
image: odek:local
env_file: .env
# No published ports (no inbound needed). The container keeps default
# outbound networking — Odek MUST reach the LLM provider API to run.
# Isolation here is the container boundary + non-root + only ./workspace
# mounted, NOT network restriction. To also fence the agent's own egress,
# put it on a network behind an allowlisting proxy (advanced; see README).
command: ["serve", "--addr", "0.0.0.0:8080", "--no-sandbox"]
volumes:
- ./workspace:/workspace
- ./config.godmode.json:/home/odek/.odek/config.json:ro
restart: "no"
depends_on: [searxng, llama-embeddings]
# ── Telegram bot — Restricted (approvals via inline keyboards) ──
# State (sessions, skills, telegram.pid) lives in the local ./.odek folder —
# an external folder on the host, just like ./workspace. config.restricted.json
# is layered on top of ./.odek/config.json to set the approval policy.
odek-telegram-restricted:
profiles: ["telegram-restricted"]
build:
context: ..
dockerfile: docker/Dockerfile
image: odek:local
env_file: .env
command: ["telegram"]
# init: true runs Docker's built-in init (tini) as PID 1, which reaps any
# child processes the agent spawns (shell tool, sub-agents) and forwards
# SIGTERM from `docker stop` for a clean shutdown. The bot also hosts the
# native scheduler (see docs/SCHEDULES.md) — jobs live in ./.odek/schedules.json.
init: true
volumes:
- ./workspace:/workspace
- ./.odek:/home/odek/.odek
- ./config.restricted.json:/home/odek/.odek/config.json:ro
restart: unless-stopped
depends_on: [searxng, llama-embeddings]
# ── Telegram bot — Godmode (no prompts; unrestricted) ──
# Same ./.odek state folder; config.godmode.json is layered on top of
# ./.odek/config.json to force the unrestricted (action: allow) policy.
odek-telegram-godmode:
profiles: ["telegram-godmode"]
build:
context: ..
dockerfile: docker/Dockerfile
image: odek:local
env_file: .env
command: ["telegram"]
init: true # reap agent child processes + forward SIGTERM (see telegram-restricted)
volumes:
- ./workspace:/workspace
- ./.odek:/home/odek/.odek
- ./config.godmode.json:/home/odek/.odek/config.json:ro
restart: unless-stopped
depends_on: [searxng, llama-embeddings]
# ── llama.cpp embeddings — local backend for memory.embedding ──
# Co-starts with every odek profile so the memory system gets real semantic
# embeddings (recall, dedup, ranking, fact merge) out of the box — no cloud
# embeddings API, no keys. Reachable only by the odek containers over the
# compose network at http://llama-embeddings:8080 — NO host port is published
# (odek's memory system is the only consumer). The GGUF is baked into the
# image (see docker/Dockerfile.embeddings), so there is no first-run download
# and no volume. Both bundled configs point memory.embedding.base_url here.
# To run without local embeddings, comment this service and the matching
# depends_on entries, and drop the "embedding" block from the configs (memory
# then falls back to local RandomProjections — lexical, zero-cost).
llama-embeddings:
profiles: ["restricted", "godmode", "telegram-restricted", "telegram-godmode"]
build:
context: ..
dockerfile: docker/Dockerfile.embeddings
image: odek-embeddings:local
# Health is observability only — odek tolerates the server being briefly
# unavailable (recall degrades to "no context" and rebuilds back off 30s),
# so startup is not gated on it. The model is bundled, so load is quick.
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
interval: 10s
timeout: 5s
retries: 30
start_period: 60s
restart: unless-stopped
# ── SearXNG — self-hosted metasearch backing the `web_search` tool ──
# Co-starts with every odek profile so web search works out of the box.
# Reachable only by the odek containers over the compose network at
# http://searxng:8080 — NO host port is published (the agent is the only
# consumer). The bundled config enables the JSON API and disables the
# anti-bot limiter, so no Redis/Valkey is needed (single trusted consumer).
# Set SEARXNG_SECRET in .env. To run without web search, comment this service
# and the depends_on lines above, and drop "web_search" from the configs.
searxng:
profiles: ["restricted", "godmode", "telegram-restricted", "telegram-godmode"]
image: searxng/searxng:2026.6.8-f3fab143b # pinned; bump deliberately
environment:
- SEARXNG_BASE_URL=http://searxng:8080/
# SearXNG reads server.secret_key from this env var at app load, overriding
# settings.yml. Set SEARXNG_SECRET in .env. The fallback is the canonical
# "ultrasecretkey" sentinel so an unset secret triggers SearXNG's own
# "secret_key is not changed" warning rather than a silent weak literal.
- SEARXNG_SECRET=${SEARXNG_SECRET:-ultrasecretkey}
volumes:
- ./searxng/settings.yml:/etc/searxng/settings.yml:ro
# SearXNG needs outbound internet to query upstream engines (Google, Bing,
# DuckDuckGo, …). Behind the advanced allowlisting egress proxy, permit those.
restart: unless-stopped