-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathcompose.yml
More file actions
211 lines (205 loc) · 7.51 KB
/
Copy pathcompose.yml
File metadata and controls
211 lines (205 loc) · 7.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
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
services:
router:
build:
context: .
image: unhardcoded:local
restart: unless-stopped
env_file:
- ./.env.secrets
environment:
LLM_POLICY_DIR: /app
# local Ollama sidecar (compose service `ollama`); discovery hits
# $OLLAMA_BASE_URL/api/tags, chat the OpenAI-compat endpoint. Unset in k8s
# -> the source falls back to localhost and simply finds nothing.
OLLAMA_BASE_URL: http://ollama:11434
# the provider declares auth_env=OLLAMA_API_KEY (for Ollama Cloud); LOCAL
# ollama needs no auth but the host's auth resolver still wants the var, so
# give it a dummy the local server ignores. Override with a real key (and
# OLLAMA_CLOUD=1) to use Ollama Cloud instead.
OLLAMA_API_KEY: ${OLLAMA_API_KEY:-ollama-local}
# compose runs antseed on its own network; socat re-exposes the
# localhost-only buyer proxy on :8378 (k8s leaves this unset -> localhost)
ANTSEED_BASE_URL: http://antseed:8378/v1
# wallet control server in the sidecar (deposit/withdraw/refresh from the
# dashboard). Unset token -> the wallet endpoints return 503. k8s: same pod
# -> http://127.0.0.1:8379.
ANTSEED_CONTROL_URL: http://antseed:8379
ANTSEED_CONTROL_TOKEN: ${ANTSEED_CONTROL_TOKEN:-}
# Operational store (router reads operator config from it). Prod = RDS.
DATABASE_URL: ${DATABASE_URL:-postgresql://hoststore:hoststore@postgres:5432/hoststore}
depends_on:
postgres:
condition: service_healthy
command:
- python
- serve.py
- --config
- config.live.lua
- --metrics
- metrics.live.lua
- --default-profile
- default
- --host
- 0.0.0.0
- --port
- "18080"
- --timeout-s
- "45"
- --codex-auth
- /codex/auth.json
volumes:
- ${CODEX_AUTH_PATH:-./codex-auth.json}:/codex/auth.json
# dashboard-added Codex accounts + the account selection, shared with
# ingress so accounts added in the dashboard actually reach the router.
- codex-accounts:/codex/accounts
# operator-added providers (dashboard "Add provider"): read at startup
- ./secrets:/run/llm-router/secrets:ro
expose:
- "18080"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request,sys,json; r=urllib.request.urlopen('http://127.0.0.1:18080/healthz', timeout=3); sys.exit(0 if json.load(r).get('ok') else 1)"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
llm-router-internal:
aliases:
- router.internal
ingress:
image: unhardcoded:local
restart: unless-stopped
depends_on:
router:
condition: service_healthy
postgres:
condition: service_healthy
env_file:
- ./.env.secrets
environment:
ROUTER_UPSTREAM: http://router:18080
# Operational store: the ingress is the writer (consumer keys, the ledger,
# operator-config writes). Prod = RDS.
DATABASE_URL: ${DATABASE_URL:-postgresql://hoststore:hoststore@postgres:5432/hoststore}
RATE_PER_MIN: ${RATE_PER_MIN:-600}
BURST: ${BURST:-200}
LOG_LEVEL: ${LOG_LEVEL:-INFO}
DASHBOARD_KEY_ENV_PATH: /run/llm-router/.env.secrets
# env_file carries the HOST path; inside the container the file is the
# bind mount below (needed by the provider-key reveal endpoint)
CODEX_AUTH_PATH: /codex/auth.json
volumes:
- ./.env.secrets:/run/llm-router/.env.secrets
- ./secrets:/run/llm-router/secrets
- ${CODEX_AUTH_PATH:-./codex-auth.json}:/codex/auth.json
- codex-accounts:/codex/accounts
command:
- uvicorn
- auth_proxy:app
- --host
- 0.0.0.0
- --port
- "8080"
- --proxy-headers
ports:
- "127.0.0.1:${LLM_ROUTER_HOST_PORT:-8080}:8080"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request,sys,json; r=urllib.request.urlopen('http://127.0.0.1:8080/healthz', timeout=3); sys.exit(0 if json.load(r).get('ok') else 1)"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
llm-router-internal:
aliases:
- llm-router.internal
genlayer-web:
aliases:
- llm-router-ingress
# One AntSeed buyer (no tiers). Browse mode (no --peer): it discovers sellers
# on the network; the policy sets the per-call price ceiling, so the cap here
# is just a wide outer bound. Writes the marketplace book (browse) and the
# buyer status into the host store (peer_offers / buyer_status), both read by
# sources/antseed.py — no shared market volume any more. Needs a funded
# wallet (antseed buyer deposit) to actually transact.
antseed:
build:
context: .
dockerfile: Dockerfile.antseed
image: unhardcoded-antseed:local
profiles: ["antseed"]
restart: unless-stopped
environment:
ANTSEED_DATA_DIR: /data
# Durable buyer identity. Unset -> the CLI generates one in the data
# volume (lost with the volume). Set to keep a funded wallet across
# volume loss. See docs/PROVIDERS.md.
ANTSEED_IDENTITY_HEX: ${ANTSEED_IDENTITY_HEX:-}
# Buyer spend rails — wide; the real per-call price ceiling is the
# caller's Σ_pol policy (and antseed.market_price_cap in config.live.lua).
ANTSEED_MAX_INPUT: ${ANTSEED_MAX_INPUT:-1000}
ANTSEED_MAX_OUTPUT: ${ANTSEED_MAX_OUTPUT:-1000}
# Wallet control server (deposit/withdraw/status from the dashboard).
# Shared secret with the router; unset -> control.js does not start.
ANTSEED_CONTROL_PORT: ${ANTSEED_CONTROL_PORT:-8379}
ANTSEED_CONTROL_TOKEN: ${ANTSEED_CONTROL_TOKEN:-}
# The sidecar writes the marketplace book (peer_offers) into the shared
# host store; same DATABASE_URL as router/ingress. Prod = RDS.
DATABASE_URL: ${DATABASE_URL:-postgresql://hoststore:hoststore@postgres:5432/hoststore}
volumes:
- antseed-data:/data
depends_on:
router:
condition: service_healthy
postgres:
condition: service_healthy
# Own network (alias `antseed`, proxy exposed by socat on :8378) — NOT
# `network_mode: service:router`, whose orphaned netns silently zeroed
# discovery whenever the router was recreated without antseed.
networks:
llm-router-internal:
aliases:
- antseed
# Local Ollama, for exercising the ollama provider end to end (the @ollama
# BDD flow). Kept deliberately tiny — pull a small model after `up`, e.g.
# docker compose exec ollama ollama pull qwen2.5:0.5b
# The router discovers it via OLLAMA_BASE_URL=http://ollama:11434.
ollama:
image: ollama/ollama:latest
restart: unless-stopped
volumes:
- ollama-data:/root/.ollama
networks:
llm-router-internal:
aliases:
- ollama
# Operational store shared by router + ingress (dev). Prod = RDS via DATABASE_URL.
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: hoststore
POSTGRES_PASSWORD: hoststore
POSTGRES_DB: hoststore
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U hoststore -d hoststore"]
interval: 5s
timeout: 3s
retries: 10
start_period: 5s
networks:
llm-router-internal:
aliases:
- postgres
networks:
llm-router-internal:
name: llm-router-internal
genlayer-web:
external: true
volumes:
codex-accounts:
antseed-data:
ollama-data:
postgres-data: