fadenstack 0.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- faden_cli/__init__.py +16 -0
- faden_cli/__main__.py +9 -0
- faden_cli/bundle/shared/.gitignore +25 -0
- faden_cli/bundle/shared/LICENSE +187 -0
- faden_cli/bundle/shared/NOTICE +15 -0
- faden_cli/bundle/shared/OFFICIAL.md +9 -0
- faden_cli/bundle/shared/README.md +16 -0
- faden_cli/bundle/shared/agent-binaries/.gitignore +5 -0
- faden_cli/bundle/shared/alloy/config.alloy +40 -0
- faden_cli/bundle/shared/clickhouse/config.d/system-logs.xml +26 -0
- faden_cli/bundle/shared/docker-compose.gpu.yaml +34 -0
- faden_cli/bundle/shared/docker-compose.yaml +998 -0
- faden_cli/bundle/shared/grafana/dashboards/templates/vllm-runtime.json +2099 -0
- faden_cli/bundle/shared/grafana/provisioning/dashboards/dashboard.yml +10 -0
- faden_cli/bundle/shared/grafana/provisioning/dashboards/json/faden-overview.json +211 -0
- faden_cli/bundle/shared/grafana/provisioning/datasources/ds.yaml +9 -0
- faden_cli/bundle/shared/grafana/provisioning/datasources/prometheus.yaml +15 -0
- faden_cli/bundle/shared/initdb/01-init.sql +32 -0
- faden_cli/bundle/shared/loki/local-config.yaml +32 -0
- faden_cli/bundle/shared/nginx/locations.conf +245 -0
- faden_cli/bundle/shared/nginx/maintenance.html +239 -0
- faden_cli/bundle/shared/nginx/nginx-tls.conf +79 -0
- faden_cli/bundle/shared/nginx/nginx.conf +44 -0
- faden_cli/bundle/shared/nginx/rate-limits.conf +42 -0
- faden_cli/bundle/shared/nginx/security-headers.conf +22 -0
- faden_cli/bundle/shared/nginx/select-config.sh +37 -0
- faden_cli/bundle/shared/prometheus/prometheus.yml +40 -0
- faden_cli/bundle/shared/rabbitmq/definitions.json.example +37 -0
- faden_cli/bundle/shared/tls/README.md +30 -0
- faden_cli/cli.py +158 -0
- faden_cli/commands/__init__.py +1 -0
- faden_cli/commands/admin.py +161 -0
- faden_cli/commands/backup.py +159 -0
- faden_cli/commands/config.py +146 -0
- faden_cli/commands/deploy.py +949 -0
- faden_cli/commands/dev/__init__.py +1 -0
- faden_cli/commands/dev/dev_doctor.py +46 -0
- faden_cli/commands/dev/dev_down.py +241 -0
- faden_cli/commands/dev/dev_group.py +24 -0
- faden_cli/commands/dev/dev_init.py +710 -0
- faden_cli/commands/dev/dev_pull.py +297 -0
- faden_cli/commands/dev/dev_status.py +151 -0
- faden_cli/commands/dev/dev_up.py +1392 -0
- faden_cli/commands/doctor.py +225 -0
- faden_cli/commands/down.py +75 -0
- faden_cli/commands/logs_cmd.py +41 -0
- faden_cli/commands/maintenance.py +74 -0
- faden_cli/commands/module.py +113 -0
- faden_cli/commands/observe.py +95 -0
- faden_cli/commands/ports.py +91 -0
- faden_cli/commands/rebuild.py +158 -0
- faden_cli/commands/restore.py +139 -0
- faden_cli/commands/runtime_images.py +174 -0
- faden_cli/commands/status.py +71 -0
- faden_cli/commands/tls.py +722 -0
- faden_cli/commands/tune.py +37 -0
- faden_cli/commands/up.py +64 -0
- faden_cli/commands/upgrade.py +470 -0
- faden_cli/commands/version.py +78 -0
- faden_cli/core/__init__.py +1 -0
- faden_cli/core/api_client.py +77 -0
- faden_cli/core/backup.py +717 -0
- faden_cli/core/bootstrap.py +291 -0
- faden_cli/core/bundle.py +110 -0
- faden_cli/core/clickhouse.py +61 -0
- faden_cli/core/compose.py +484 -0
- faden_cli/core/console.py +106 -0
- faden_cli/core/detect.py +580 -0
- faden_cli/core/dev_modules.py +149 -0
- faden_cli/core/docker_env.py +147 -0
- faden_cli/core/edge.py +94 -0
- faden_cli/core/env_gen.py +598 -0
- faden_cli/core/git.py +219 -0
- faden_cli/core/install.py +288 -0
- faden_cli/core/installation.py +186 -0
- faden_cli/core/local_node.py +719 -0
- faden_cli/core/maintenance.py +82 -0
- faden_cli/core/private_files.py +133 -0
- faden_cli/core/registry.py +574 -0
- faden_cli/core/release_feed.py +342 -0
- faden_cli/core/rmq.py +135 -0
- faden_cli/core/runtime_images.py +309 -0
- faden_cli/core/schedule.py +278 -0
- faden_cli/core/settings.py +159 -0
- faden_cli/core/sysinfo.py +303 -0
- faden_cli/core/tls.py +790 -0
- faden_cli/core/tune.py +154 -0
- faden_cli/core/update_check.py +254 -0
- faden_cli/core/workspace.py +155 -0
- faden_cli/templates/env.j2 +33 -0
- faden_cli/tui/__init__.py +1 -0
- faden_cli/tui/widgets/__init__.py +1 -0
- faden_cli/tui/wizard/__init__.py +1 -0
- fadenstack-0.4.2.dist-info/METADATA +304 -0
- fadenstack-0.4.2.dist-info/RECORD +99 -0
- fadenstack-0.4.2.dist-info/WHEEL +4 -0
- fadenstack-0.4.2.dist-info/entry_points.txt +3 -0
- fadenstack-0.4.2.dist-info/licenses/LICENSE +187 -0
- fadenstack-0.4.2.dist-info/licenses/NOTICE +15 -0
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
# Secrets: this file has no fallback for any password, key or token. Each one
|
|
2
|
+
# is ${NAME:?...}, and compose stops naming the first that .env lacks.
|
|
3
|
+
# `faden deploy` writes them all at random; `faden upgrade` adds what a
|
|
4
|
+
# release introduces. Started by hand, set them yourself (Help: Installing,
|
|
5
|
+
# Secrets in .env). The services refuse the development values that are
|
|
6
|
+
# published with the source code.
|
|
7
|
+
#
|
|
8
|
+
# The project name decides the volume names (fadenstack_pg_data, ...).
|
|
9
|
+
# Fixed, so an install keeps its data whichever directory it runs from: a
|
|
10
|
+
# source checkout's shared, or the directory `faden deploy`
|
|
11
|
+
# unpacks the release into (~/fadenstack by default).
|
|
12
|
+
name: fadenstack
|
|
13
|
+
|
|
14
|
+
services:
|
|
15
|
+
# -----------------------------
|
|
16
|
+
# Platform base image (build-only, no runtime container)
|
|
17
|
+
# -----------------------------
|
|
18
|
+
faden-base:
|
|
19
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
|
|
20
|
+
build:
|
|
21
|
+
context: ./base
|
|
22
|
+
dockerfile: Dockerfile
|
|
23
|
+
profiles: ["_build"]
|
|
24
|
+
|
|
25
|
+
# -----------------------------
|
|
26
|
+
# Reverse proxy — single public entrypoint
|
|
27
|
+
# -----------------------------
|
|
28
|
+
nginx:
|
|
29
|
+
image: nginx:1-alpine
|
|
30
|
+
container_name: faden-nginx
|
|
31
|
+
restart: unless-stopped
|
|
32
|
+
ports:
|
|
33
|
+
- "${FADEN_HTTP_PORT:-80}:80"
|
|
34
|
+
# Served once ./tls holds a certificate and key (nginx/select-config.sh);
|
|
35
|
+
# until then nothing listens here.
|
|
36
|
+
- "${FADEN_HTTPS_PORT:-443}:443"
|
|
37
|
+
environment:
|
|
38
|
+
FADEN_HTTPS_PORT: ${FADEN_HTTPS_PORT:-443}
|
|
39
|
+
# Strict-Transport-Security max-age sent over HTTPS. Opt-in: 0 (off) by
|
|
40
|
+
# default, which also tells browsers to forget it. With a self-signed
|
|
41
|
+
# certificate or a private CA, HSTS leaves a browser that does not trust
|
|
42
|
+
# it yet no way past the warning (nginx-tls.conf, Help: HTTPS).
|
|
43
|
+
FADEN_HSTS_MAX_AGE: ${FADEN_HSTS_MAX_AGE:-0}
|
|
44
|
+
# select-config.sh installs the plain-HTTP or the HTTPS server config,
|
|
45
|
+
# then nginx runs as usual (the image's own entrypoint still runs first).
|
|
46
|
+
command: ["/bin/sh", "-c", "sh /etc/nginx/faden/select-config.sh && exec nginx -g 'daemon off;'"]
|
|
47
|
+
volumes:
|
|
48
|
+
- ./nginx:/etc/nginx/faden:ro
|
|
49
|
+
# The edge certificate and key: written by the backend's TLS admin API
|
|
50
|
+
# (/api/admin/tls), or copied in by the operator. See tls/README.md.
|
|
51
|
+
- ./tls:/etc/faden/tls:ro
|
|
52
|
+
depends_on:
|
|
53
|
+
faden-backend:
|
|
54
|
+
condition: service_healthy
|
|
55
|
+
faden-frontend:
|
|
56
|
+
condition: service_started
|
|
57
|
+
healthcheck:
|
|
58
|
+
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://127.0.0.1:80/healthz || exit 1"]
|
|
59
|
+
interval: 5s
|
|
60
|
+
timeout: 3s
|
|
61
|
+
retries: 10
|
|
62
|
+
start_period: 10s
|
|
63
|
+
|
|
64
|
+
# -----------------------------
|
|
65
|
+
# Database for RAG + Langfuse state
|
|
66
|
+
# -----------------------------
|
|
67
|
+
postgres:
|
|
68
|
+
image: pgvector/pgvector:pg17
|
|
69
|
+
container_name: faden-postgres
|
|
70
|
+
restart: unless-stopped
|
|
71
|
+
# Parallel index builds (pgvector HNSW) work in shared memory; Docker's
|
|
72
|
+
# default 64 MB /dev/shm fails them ("could not resize shared memory
|
|
73
|
+
# segment"). pgvector's README asks for more.
|
|
74
|
+
shm_size: 1g
|
|
75
|
+
# Every worker of every service keeps its own pool, and they all share this
|
|
76
|
+
# server: with PII, MCP and skills an install from this file alone can open
|
|
77
|
+
# about 130 connections at its peak, past Postgres' default of 100 (see
|
|
78
|
+
# docs/help/pages/operate/requirements.md, The server). A connection is a
|
|
79
|
+
# process of about 6 MB, so 250 at once is about 1.5 GB.
|
|
80
|
+
command: ["postgres", "-c", "max_connections=${POSTGRES_MAX_CONNECTIONS:-250}"]
|
|
81
|
+
environment:
|
|
82
|
+
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
|
83
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
84
|
+
POSTGRES_DB: ${POSTGRES_DB:-postgres}
|
|
85
|
+
TZ: UTC
|
|
86
|
+
PGTZ: UTC
|
|
87
|
+
ports:
|
|
88
|
+
- "127.0.0.1:5432:5432"
|
|
89
|
+
volumes:
|
|
90
|
+
- pg_data:/var/lib/postgresql/data
|
|
91
|
+
- ./initdb:/docker-entrypoint-initdb.d:ro
|
|
92
|
+
healthcheck:
|
|
93
|
+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
|
|
94
|
+
interval: 3s
|
|
95
|
+
timeout: 3s
|
|
96
|
+
retries: 15
|
|
97
|
+
start_period: 120s
|
|
98
|
+
|
|
99
|
+
# -----------------------------
|
|
100
|
+
# Langfuse (v3) dependencies
|
|
101
|
+
# -----------------------------
|
|
102
|
+
clickhouse:
|
|
103
|
+
# Pinned: tags >= ~25.11 require AVX2. On QEMU/emulated CPUs that
|
|
104
|
+
# expose only SSE4.2 the binary crashes with "Illegal instruction"
|
|
105
|
+
# (SIGILL) and the container crash-loops. Override via .env:
|
|
106
|
+
# CLICKHOUSE_IMAGE=clickhouse/clickhouse-server:<tag>
|
|
107
|
+
image: ${CLICKHOUSE_IMAGE:-clickhouse/clickhouse-server:25.10}
|
|
108
|
+
container_name: faden-clickhouse
|
|
109
|
+
restart: unless-stopped
|
|
110
|
+
user: "101:101"
|
|
111
|
+
environment:
|
|
112
|
+
CLICKHOUSE_DB: default
|
|
113
|
+
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-clickhouse}
|
|
114
|
+
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
115
|
+
ports:
|
|
116
|
+
- "127.0.0.1:8123:8123"
|
|
117
|
+
- "127.0.0.1:9000:9000"
|
|
118
|
+
volumes:
|
|
119
|
+
- ch_data:/var/lib/clickhouse
|
|
120
|
+
- ch_logs:/var/log/clickhouse-server
|
|
121
|
+
# Its own diagnostic logs off or capped: trace_log alone filled a
|
|
122
|
+
# 98 GB disk in two weeks. See the file.
|
|
123
|
+
- ./clickhouse/config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:ro
|
|
124
|
+
healthcheck:
|
|
125
|
+
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"]
|
|
126
|
+
interval: 5s
|
|
127
|
+
timeout: 5s
|
|
128
|
+
retries: 10
|
|
129
|
+
start_period: 2s
|
|
130
|
+
|
|
131
|
+
redis:
|
|
132
|
+
image: redis:7.2
|
|
133
|
+
container_name: faden-redis
|
|
134
|
+
restart: unless-stopped
|
|
135
|
+
command: >
|
|
136
|
+
--requirepass ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)} --maxmemory-policy noeviction
|
|
137
|
+
ports:
|
|
138
|
+
- "127.0.0.1:6379:6379"
|
|
139
|
+
healthcheck:
|
|
140
|
+
test: ["CMD", "redis-cli", "-a", "${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}", "ping"]
|
|
141
|
+
interval: 3s
|
|
142
|
+
timeout: 10s
|
|
143
|
+
retries: 10
|
|
144
|
+
|
|
145
|
+
minio:
|
|
146
|
+
image: cgr.dev/chainguard/minio:latest
|
|
147
|
+
container_name: faden-minio
|
|
148
|
+
restart: unless-stopped
|
|
149
|
+
entrypoint: sh
|
|
150
|
+
command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
|
|
151
|
+
environment:
|
|
152
|
+
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minio}
|
|
153
|
+
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
154
|
+
ports:
|
|
155
|
+
- "127.0.0.1:9090:9000"
|
|
156
|
+
- "127.0.0.1:9091:9001"
|
|
157
|
+
volumes:
|
|
158
|
+
- minio_data:/data
|
|
159
|
+
healthcheck:
|
|
160
|
+
test: ["CMD", "mc", "ready", "local"]
|
|
161
|
+
interval: 2s
|
|
162
|
+
timeout: 5s
|
|
163
|
+
retries: 10
|
|
164
|
+
start_period: 2s
|
|
165
|
+
|
|
166
|
+
# -----------------------------
|
|
167
|
+
# Langfuse v3 (web + worker)
|
|
168
|
+
# -----------------------------
|
|
169
|
+
langfuse-worker:
|
|
170
|
+
image: docker.io/langfuse/langfuse-worker:3
|
|
171
|
+
container_name: faden-worker
|
|
172
|
+
restart: unless-stopped
|
|
173
|
+
depends_on:
|
|
174
|
+
postgres:
|
|
175
|
+
condition: service_healthy
|
|
176
|
+
clickhouse:
|
|
177
|
+
condition: service_healthy
|
|
178
|
+
redis:
|
|
179
|
+
condition: service_healthy
|
|
180
|
+
minio:
|
|
181
|
+
condition: service_healthy
|
|
182
|
+
ports:
|
|
183
|
+
- "127.0.0.1:3030:3030"
|
|
184
|
+
environment:
|
|
185
|
+
NEXTAUTH_URL: ${LANGFUSE_NEXTAUTH_URL:-http://localhost:3000}
|
|
186
|
+
DATABASE_URL: ${LANGFUSE_DATABASE_URL:-postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}@postgres:5432/langfuse}
|
|
187
|
+
SALT: ${LANGFUSE_SALT:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
188
|
+
ENCRYPTION_KEY: ${LANGFUSE_ENCRYPTION_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
189
|
+
# Off: Langfuse reports usage to its makers unless told not to.
|
|
190
|
+
TELEMETRY_ENABLED: ${LANGFUSE_TELEMETRY_ENABLED:-false}
|
|
191
|
+
|
|
192
|
+
CLICKHOUSE_MIGRATION_URL: ${CLICKHOUSE_MIGRATION_URL:-clickhouse://clickhouse:9000}
|
|
193
|
+
CLICKHOUSE_URL: ${CLICKHOUSE_URL:-http://clickhouse:8123}
|
|
194
|
+
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-clickhouse}
|
|
195
|
+
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
196
|
+
CLICKHOUSE_CLUSTER_ENABLED: "false"
|
|
197
|
+
|
|
198
|
+
REDIS_HOST: redis
|
|
199
|
+
REDIS_PORT: 6379
|
|
200
|
+
REDIS_AUTH: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
201
|
+
|
|
202
|
+
# S3-compatible storage (MinIO)
|
|
203
|
+
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: ${LANGFUSE_S3_EVENT_UPLOAD_BUCKET:-langfuse}
|
|
204
|
+
LANGFUSE_S3_EVENT_UPLOAD_REGION: ${LANGFUSE_S3_EVENT_UPLOAD_REGION:-auto}
|
|
205
|
+
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minio}
|
|
206
|
+
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
207
|
+
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: ${LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT:-http://minio:9000}
|
|
208
|
+
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
|
|
209
|
+
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: events/
|
|
210
|
+
|
|
211
|
+
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: ${LANGFUSE_S3_MEDIA_UPLOAD_BUCKET:-langfuse}
|
|
212
|
+
LANGFUSE_S3_MEDIA_UPLOAD_REGION: ${LANGFUSE_S3_MEDIA_UPLOAD_REGION:-auto}
|
|
213
|
+
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minio}
|
|
214
|
+
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
215
|
+
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT:-http://minio:9000}
|
|
216
|
+
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: "true"
|
|
217
|
+
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: media/
|
|
218
|
+
|
|
219
|
+
langfuse-web:
|
|
220
|
+
image: docker.io/langfuse/langfuse:3
|
|
221
|
+
container_name: faden-web
|
|
222
|
+
restart: unless-stopped
|
|
223
|
+
ports:
|
|
224
|
+
# LLM observability UI (traces / evals / datasets), plain HTTP: on this
|
|
225
|
+
# machine only by default, so a password typed into it never crosses the
|
|
226
|
+
# network in the clear (reach it through an SSH tunnel). Its sign-in
|
|
227
|
+
# also expects http://localhost (LANGFUSE_NEXTAUTH_URL).
|
|
228
|
+
# LANGFUSE_BIND=0.0.0.0 publishes it on the network.
|
|
229
|
+
- "${LANGFUSE_BIND:-127.0.0.1}:3002:3000"
|
|
230
|
+
depends_on:
|
|
231
|
+
postgres:
|
|
232
|
+
condition: service_healthy
|
|
233
|
+
clickhouse:
|
|
234
|
+
condition: service_healthy
|
|
235
|
+
redis:
|
|
236
|
+
condition: service_healthy
|
|
237
|
+
minio:
|
|
238
|
+
condition: service_healthy
|
|
239
|
+
environment:
|
|
240
|
+
NEXTAUTH_URL: ${LANGFUSE_NEXTAUTH_URL:-http://localhost:3000}
|
|
241
|
+
NEXTAUTH_SECRET: ${LANGFUSE_NEXTAUTH_SECRET:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
242
|
+
DATABASE_URL: ${LANGFUSE_DATABASE_URL:-postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}@postgres:5432/langfuse}
|
|
243
|
+
SALT: ${LANGFUSE_SALT:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
244
|
+
ENCRYPTION_KEY: ${LANGFUSE_ENCRYPTION_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
245
|
+
# Off: Langfuse reports usage to its makers unless told not to.
|
|
246
|
+
TELEMETRY_ENABLED: ${LANGFUSE_TELEMETRY_ENABLED:-false}
|
|
247
|
+
|
|
248
|
+
CLICKHOUSE_MIGRATION_URL: ${CLICKHOUSE_MIGRATION_URL:-clickhouse://clickhouse:9000}
|
|
249
|
+
CLICKHOUSE_URL: ${CLICKHOUSE_URL:-http://clickhouse:8123}
|
|
250
|
+
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-clickhouse}
|
|
251
|
+
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
252
|
+
CLICKHOUSE_CLUSTER_ENABLED: "false"
|
|
253
|
+
|
|
254
|
+
REDIS_HOST: redis
|
|
255
|
+
REDIS_PORT: 6379
|
|
256
|
+
REDIS_AUTH: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
257
|
+
|
|
258
|
+
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: ${LANGFUSE_S3_EVENT_UPLOAD_BUCKET:-langfuse}
|
|
259
|
+
LANGFUSE_S3_EVENT_UPLOAD_REGION: ${LANGFUSE_S3_EVENT_UPLOAD_REGION:-auto}
|
|
260
|
+
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minio}
|
|
261
|
+
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
262
|
+
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: ${LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT:-http://minio:9000}
|
|
263
|
+
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
|
|
264
|
+
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: events/
|
|
265
|
+
|
|
266
|
+
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: ${LANGFUSE_S3_MEDIA_UPLOAD_BUCKET:-langfuse}
|
|
267
|
+
LANGFUSE_S3_MEDIA_UPLOAD_REGION: ${LANGFUSE_S3_MEDIA_UPLOAD_REGION:-auto}
|
|
268
|
+
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-minio}
|
|
269
|
+
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
270
|
+
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT:-http://minio:9000}
|
|
271
|
+
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: "true"
|
|
272
|
+
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: media/
|
|
273
|
+
|
|
274
|
+
# Initial admin user seeding (set by faden deploy)
|
|
275
|
+
LANGFUSE_INIT_USER_EMAIL: ${LANGFUSE_INIT_USER_EMAIL:-}
|
|
276
|
+
LANGFUSE_INIT_USER_PASSWORD: ${LANGFUSE_INIT_USER_PASSWORD:-}
|
|
277
|
+
LANGFUSE_INIT_USER_NAME: ${LANGFUSE_INIT_USER_NAME:-Admin}
|
|
278
|
+
LANGFUSE_INIT_ORG_ID: ${LANGFUSE_INIT_ORG_ID:-faden-org}
|
|
279
|
+
LANGFUSE_INIT_ORG_NAME: ${LANGFUSE_INIT_ORG_NAME:-fadenstack}
|
|
280
|
+
LANGFUSE_INIT_PROJECT_ID: ${LANGFUSE_INIT_PROJECT_ID:-faden-project}
|
|
281
|
+
LANGFUSE_INIT_PROJECT_NAME: ${LANGFUSE_INIT_PROJECT_NAME:-fadenstack}
|
|
282
|
+
LANGFUSE_INIT_PROJECT_PUBLIC_KEY: ${LANGFUSE_INIT_PROJECT_PUBLIC_KEY:-}
|
|
283
|
+
LANGFUSE_INIT_PROJECT_SECRET_KEY: ${LANGFUSE_INIT_PROJECT_SECRET_KEY:-}
|
|
284
|
+
|
|
285
|
+
# -----------------------------
|
|
286
|
+
# Shared RabbitMQ broker (API + RAG + local backend dev)
|
|
287
|
+
# -----------------------------
|
|
288
|
+
faden-rmq:
|
|
289
|
+
image: rabbitmq:4.2.1-management-alpine
|
|
290
|
+
container_name: faden-rmq
|
|
291
|
+
restart: unless-stopped
|
|
292
|
+
ports:
|
|
293
|
+
- "127.0.0.1:5672:5672"
|
|
294
|
+
- "127.0.0.1:15672:15672"
|
|
295
|
+
environment:
|
|
296
|
+
# Management/admin account — used for console login and as
|
|
297
|
+
# fallback when definitions.json is absent (dev mode).
|
|
298
|
+
RABBITMQ_DEFAULT_USER: ${RABBITMQ_ADMIN_USER:-admin}
|
|
299
|
+
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_ADMIN_PASS:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
300
|
+
RABBITMQ_DEFAULT_VHOST: "/"
|
|
301
|
+
# Limit Erlang schedulers and disable busy-wait to avoid CPU spin at idle.
|
|
302
|
+
# -S 2:2 — 2 online schedulers (enough for a message broker)
|
|
303
|
+
# +sbwt/+sbwtdcpu/+sbwtdio none — disable scheduler busy-waiting
|
|
304
|
+
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS: "+S 2:2 +sbwt none +sbwtdcpu none +sbwtdio none"
|
|
305
|
+
volumes:
|
|
306
|
+
# Per-service user definitions (generated by faden deploy).
|
|
307
|
+
# In dev mode these files may not exist — RabbitMQ falls back
|
|
308
|
+
# to RABBITMQ_DEFAULT_USER/PASS.
|
|
309
|
+
- ./rabbitmq/10-faden.conf:/etc/rabbitmq/conf.d/10-faden.conf:ro
|
|
310
|
+
- ./rabbitmq/definitions.json:/etc/rabbitmq/definitions.json:ro
|
|
311
|
+
deploy:
|
|
312
|
+
resources:
|
|
313
|
+
limits:
|
|
314
|
+
cpus: "1"
|
|
315
|
+
memory: 512M
|
|
316
|
+
healthcheck:
|
|
317
|
+
test: rabbitmq-diagnostics check_running -q
|
|
318
|
+
interval: 3s
|
|
319
|
+
timeout: 3s
|
|
320
|
+
retries: 50
|
|
321
|
+
|
|
322
|
+
faden-gateway-migrator:
|
|
323
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/gateway:${VERSION:-latest}
|
|
324
|
+
container_name: faden-gateway-migrator
|
|
325
|
+
restart: on-failure:5
|
|
326
|
+
command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
|
|
327
|
+
depends_on:
|
|
328
|
+
postgres:
|
|
329
|
+
condition: service_healthy
|
|
330
|
+
environment:
|
|
331
|
+
FADEN_GATEWAY_DB_HOST: postgres
|
|
332
|
+
FADEN_GATEWAY_DB_PORT: 5432
|
|
333
|
+
FADEN_GATEWAY_DB_USER: ${POSTGRES_USER:-postgres}
|
|
334
|
+
FADEN_GATEWAY_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
335
|
+
FADEN_GATEWAY_DB_BASE: faden_gateway
|
|
336
|
+
|
|
337
|
+
# -----------------------------
|
|
338
|
+
# faden_gateway (OpenAI-compatible endpoint gateway)
|
|
339
|
+
# -----------------------------
|
|
340
|
+
faden-gateway:
|
|
341
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/gateway:${VERSION:-latest}
|
|
342
|
+
build:
|
|
343
|
+
context: ../gateway
|
|
344
|
+
dockerfile: Dockerfile
|
|
345
|
+
target: prod
|
|
346
|
+
args:
|
|
347
|
+
BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
|
|
348
|
+
container_name: faden-gateway
|
|
349
|
+
restart: unless-stopped
|
|
350
|
+
depends_on:
|
|
351
|
+
postgres:
|
|
352
|
+
condition: service_healthy
|
|
353
|
+
redis:
|
|
354
|
+
condition: service_healthy
|
|
355
|
+
faden-rmq:
|
|
356
|
+
condition: service_healthy
|
|
357
|
+
faden-gateway-migrator:
|
|
358
|
+
condition: service_completed_successfully
|
|
359
|
+
ports:
|
|
360
|
+
- "127.0.0.1:8001:8000"
|
|
361
|
+
environment:
|
|
362
|
+
FADEN_GATEWAY_HOST: 0.0.0.0
|
|
363
|
+
FADEN_GATEWAY_PORT: 8000
|
|
364
|
+
# Behind nginx, which sets X-Forwarded-Proto/For; uvicorn honours them
|
|
365
|
+
# only from these addresses (its default is 127.0.0.1, which nginx is
|
|
366
|
+
# not here). Every peer is on the compose network; the host port above
|
|
367
|
+
# is loopback-only.
|
|
368
|
+
FORWARDED_ALLOW_IPS: "*"
|
|
369
|
+
FADEN_GATEWAY_RELOAD: "false"
|
|
370
|
+
FADEN_GATEWAY_ENVIRONMENT: ${FADEN_GATEWAY_ENVIRONMENT:-production}
|
|
371
|
+
# JWT secret is read from backend DB at startup (faden_gateway.jwt_secret system setting).
|
|
372
|
+
# These two env vars enable that path; no static JWT_SECRET env var is needed.
|
|
373
|
+
FADEN_GATEWAY_BACKEND_DB_BASE: faden_backend
|
|
374
|
+
FADEN_GATEWAY_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
375
|
+
# An install that has stored data under the published development key may
|
|
376
|
+
# keep it, with a warning at every start, until it is changed (Help:
|
|
377
|
+
# Installing, Secrets in .env). Outside development the service refuses it otherwise.
|
|
378
|
+
FADEN_GATEWAY_ALLOW_PUBLISHED_KEYS: ${FADEN_ALLOW_PUBLISHED_KEYS:-false}
|
|
379
|
+
# The key chats are encrypted with at rest: messages, titles, memory, a
|
|
380
|
+
# reply's events in Redis. `faden deploy` writes one into .env; it never
|
|
381
|
+
# reached the gateway, and every install stored its chats in plain text
|
|
382
|
+
# (2026-10-02). Empty still stores plain text. Rows from before stay
|
|
383
|
+
# readable. Without this key the encrypted chats cannot be read: .env
|
|
384
|
+
# belongs in every backup (`faden backup` takes it; --db-only does not).
|
|
385
|
+
FADEN_GATEWAY_ENCRYPTION_KEY: ${FADEN_GATEWAY_ENCRYPTION_KEY:-}
|
|
386
|
+
FADEN_GATEWAY_JWT_ALGORITHM: HS256
|
|
387
|
+
FADEN_GATEWAY_DB_HOST: postgres
|
|
388
|
+
FADEN_GATEWAY_DB_PORT: 5432
|
|
389
|
+
FADEN_GATEWAY_DB_USER: ${POSTGRES_USER:-postgres}
|
|
390
|
+
FADEN_GATEWAY_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
391
|
+
FADEN_GATEWAY_DB_BASE: faden_gateway
|
|
392
|
+
FADEN_GATEWAY_REDIS_HOST: redis
|
|
393
|
+
FADEN_GATEWAY_REDIS_PORT: 6379
|
|
394
|
+
FADEN_GATEWAY_REDIS_PASS: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
395
|
+
FADEN_GATEWAY_REDIS_BASE: 1
|
|
396
|
+
FADEN_GATEWAY_RABBIT_HOST: faden-rmq
|
|
397
|
+
FADEN_GATEWAY_RABBIT_PORT: 5672
|
|
398
|
+
FADEN_GATEWAY_RABBIT_USER: faden-gateway
|
|
399
|
+
FADEN_GATEWAY_RABBIT_PASS: ${RABBITMQ_API_PASS:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
400
|
+
FADEN_GATEWAY_RABBIT_VHOST: /
|
|
401
|
+
FADEN_GATEWAY_LANGFUSE_ENABLED: ${FADEN_GATEWAY_LANGFUSE_ENABLED:-false}
|
|
402
|
+
FADEN_GATEWAY_LANGFUSE_HOST: ${FADEN_GATEWAY_LANGFUSE_HOST:-http://langfuse-web:3000}
|
|
403
|
+
FADEN_GATEWAY_LANGFUSE_PUBLIC_KEY: ${FADEN_GATEWAY_LANGFUSE_PUBLIC_KEY:-}
|
|
404
|
+
FADEN_GATEWAY_LANGFUSE_SECRET_KEY: ${FADEN_GATEWAY_LANGFUSE_SECRET_KEY:-}
|
|
405
|
+
# PII module integration (set via .env or COMPOSE_PROFILES)
|
|
406
|
+
FADEN_GATEWAY_PII_ENABLED: ${FADEN_GATEWAY_PII_ENABLED:-false}
|
|
407
|
+
FADEN_GATEWAY_PII_SERVICE_URL: ${FADEN_GATEWAY_PII_SERVICE_URL:-http://faden-pii:8000}
|
|
408
|
+
# MCP tool registry integration (set via .env or COMPOSE_PROFILES)
|
|
409
|
+
FADEN_GATEWAY_MCP_ENABLED: ${FADEN_GATEWAY_MCP_ENABLED:-false}
|
|
410
|
+
FADEN_GATEWAY_MCP_SERVICE_URL: ${FADEN_GATEWAY_MCP_SERVICE_URL:-http://faden-mcp:8000}
|
|
411
|
+
FADEN_GATEWAY_MCP_SERVICE_TOKEN: ${FADEN_GATEWAY_MCP_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
412
|
+
# Skills registry integration (set via .env or COMPOSE_PROFILES)
|
|
413
|
+
FADEN_GATEWAY_SKILLS_ENABLED: ${FADEN_GATEWAY_SKILLS_ENABLED:-false}
|
|
414
|
+
FADEN_GATEWAY_SKILLS_SERVICE_URL: ${FADEN_GATEWAY_SKILLS_SERVICE_URL:-http://faden-skills:8000}
|
|
415
|
+
FADEN_GATEWAY_SKILLS_SERVICE_TOKEN: ${FADEN_GATEWAY_SKILLS_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
416
|
+
# Knowledge search runs in the backend. The default, 127.0.0.1:8000, is this container's own port:
|
|
417
|
+
# every search reached the gateway itself and failed with 404.
|
|
418
|
+
FADEN_GATEWAY_RAG_LITE_BACKEND_URL: ${FADEN_GATEWAY_RAG_LITE_BACKEND_URL:-http://faden-backend:8000}
|
|
419
|
+
# Media URLs in chat requests are fetched by the gateway, from public addresses only, and reach the
|
|
420
|
+
# model as data: URLs. Internal hosts, *.patterns or networks to fetch from too, comma-separated;
|
|
421
|
+
# the most a request's URLs may bring in (bytes) and the time one may take; false turns it all off.
|
|
422
|
+
FADEN_GATEWAY_MEDIA_URL_CHECK: ${FADEN_GATEWAY_MEDIA_URL_CHECK:-true}
|
|
423
|
+
FADEN_GATEWAY_MEDIA_URL_ALLOWED_HOSTS: ${FADEN_GATEWAY_MEDIA_URL_ALLOWED_HOSTS:-}
|
|
424
|
+
FADEN_GATEWAY_MEDIA_URL_MAX_BYTES: ${FADEN_GATEWAY_MEDIA_URL_MAX_BYTES:-20971520}
|
|
425
|
+
FADEN_GATEWAY_MEDIA_URL_TIMEOUT_SEC: ${FADEN_GATEWAY_MEDIA_URL_TIMEOUT_SEC:-20}
|
|
426
|
+
# Scalability tuning (set via faden tune)
|
|
427
|
+
FADEN_GATEWAY_WORKERS_COUNT: ${FADEN_GATEWAY_WORKERS_COUNT:-4}
|
|
428
|
+
# Chat replies one user may have written at once, across their chats.
|
|
429
|
+
FADEN_GATEWAY_CHAT_TURNS_PER_USER: ${FADEN_GATEWAY_CHAT_TURNS_PER_USER:-3}
|
|
430
|
+
FADEN_GATEWAY_DB_POOL_SIZE: ${FADEN_GATEWAY_DB_POOL_SIZE:-5}
|
|
431
|
+
FADEN_GATEWAY_DB_MAX_OVERFLOW: ${FADEN_GATEWAY_DB_MAX_OVERFLOW:-5}
|
|
432
|
+
FADEN_GATEWAY_RABBIT_POOL_SIZE: ${FADEN_GATEWAY_RABBIT_POOL_SIZE:-2}
|
|
433
|
+
FADEN_GATEWAY_RABBIT_CHANNEL_POOL_SIZE: ${FADEN_GATEWAY_RABBIT_CHANNEL_POOL_SIZE:-10}
|
|
434
|
+
healthcheck:
|
|
435
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health', timeout=3).read()"]
|
|
436
|
+
interval: 5s
|
|
437
|
+
timeout: 5s
|
|
438
|
+
retries: 20
|
|
439
|
+
|
|
440
|
+
# -----------------------------
|
|
441
|
+
# faden_backend (control-plane)
|
|
442
|
+
# -----------------------------
|
|
443
|
+
faden-backend-migrator:
|
|
444
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/backend:${VERSION:-latest}
|
|
445
|
+
container_name: faden-backend-migrator
|
|
446
|
+
restart: on-failure:5
|
|
447
|
+
command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
|
|
448
|
+
depends_on:
|
|
449
|
+
postgres:
|
|
450
|
+
condition: service_healthy
|
|
451
|
+
environment:
|
|
452
|
+
FADEN_BACKEND_DB_HOST: postgres
|
|
453
|
+
FADEN_BACKEND_DB_PORT: 5432
|
|
454
|
+
FADEN_BACKEND_DB_USER: ${POSTGRES_USER:-postgres}
|
|
455
|
+
FADEN_BACKEND_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
456
|
+
FADEN_BACKEND_DB_BASE: faden_backend
|
|
457
|
+
|
|
458
|
+
faden-backend:
|
|
459
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/backend:${VERSION:-latest}
|
|
460
|
+
build:
|
|
461
|
+
context: ../backend
|
|
462
|
+
dockerfile: Dockerfile
|
|
463
|
+
target: prod
|
|
464
|
+
# The runtime manifests the Dockerfile copies in (see there).
|
|
465
|
+
additional_contexts:
|
|
466
|
+
runtime_manifests: ../runtime-image
|
|
467
|
+
args:
|
|
468
|
+
BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
|
|
469
|
+
container_name: faden-backend
|
|
470
|
+
restart: unless-stopped
|
|
471
|
+
depends_on:
|
|
472
|
+
postgres:
|
|
473
|
+
condition: service_healthy
|
|
474
|
+
redis:
|
|
475
|
+
condition: service_healthy
|
|
476
|
+
faden-rmq:
|
|
477
|
+
condition: service_healthy
|
|
478
|
+
faden-backend-migrator:
|
|
479
|
+
condition: service_completed_successfully
|
|
480
|
+
# No host port — accessed via nginx reverse proxy
|
|
481
|
+
environment:
|
|
482
|
+
FADEN_BACKEND_HOST: 0.0.0.0
|
|
483
|
+
FADEN_BACKEND_PORT: 8000
|
|
484
|
+
# Behind nginx, which sets X-Forwarded-Proto/For; uvicorn honours them
|
|
485
|
+
# only from these addresses (its default is 127.0.0.1, which nginx is
|
|
486
|
+
# not here). Only the compose network reaches the backend, so any peer
|
|
487
|
+
# is ours. Without this the backend believes every request is plain
|
|
488
|
+
# HTTP: it would refuse a TLS upload and never mark a cookie Secure.
|
|
489
|
+
FORWARDED_ALLOW_IPS: "*"
|
|
490
|
+
FADEN_BACKEND_RELOAD: "false"
|
|
491
|
+
FADEN_BACKEND_ENVIRONMENT: ${FADEN_BACKEND_ENVIRONMENT:-production}
|
|
492
|
+
FADEN_BACKEND_DB_HOST: postgres
|
|
493
|
+
FADEN_BACKEND_DB_PORT: 5432
|
|
494
|
+
FADEN_BACKEND_DB_USER: ${POSTGRES_USER:-postgres}
|
|
495
|
+
FADEN_BACKEND_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
496
|
+
FADEN_BACKEND_DB_BASE: faden_backend
|
|
497
|
+
FADEN_BACKEND_REDIS_HOST: redis
|
|
498
|
+
FADEN_BACKEND_REDIS_PORT: 6379
|
|
499
|
+
FADEN_BACKEND_REDIS_PASS: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
500
|
+
FADEN_BACKEND_RABBIT_HOST: faden-rmq
|
|
501
|
+
FADEN_BACKEND_RABBIT_PORT: 5672
|
|
502
|
+
FADEN_BACKEND_RABBIT_USER: faden-backend
|
|
503
|
+
FADEN_BACKEND_RABBIT_PASS: ${RABBITMQ_BACKEND_PASS:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
504
|
+
FADEN_BACKEND_RABBIT_VHOST: /
|
|
505
|
+
FADEN_BACKEND_GATEWAY_URL: ${FADEN_BACKEND_GATEWAY_URL:-http://faden-gateway:8000}
|
|
506
|
+
FADEN_BACKEND_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
507
|
+
# An install that has stored data under the published development key may
|
|
508
|
+
# keep it, with a warning at every start, until it is changed (Help:
|
|
509
|
+
# Installing, Secrets in .env). Outside development the service refuses it otherwise.
|
|
510
|
+
FADEN_BACKEND_ALLOW_PUBLISHED_KEYS: ${FADEN_ALLOW_PUBLISHED_KEYS:-false}
|
|
511
|
+
FADEN_BACKEND_LLM_GRAPH_DB_HOST: postgres
|
|
512
|
+
FADEN_BACKEND_LLM_GRAPH_DB_USER: ${POSTGRES_USER:-postgres}
|
|
513
|
+
FADEN_BACKEND_LLM_GRAPH_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
514
|
+
FADEN_BACKEND_LOKI_BASE_URL: http://faden-loki:3100
|
|
515
|
+
FADEN_BACKEND_COOKIE_SECURE: "false"
|
|
516
|
+
USERS_SECRET: ${USERS_SECRET:-}
|
|
517
|
+
# Asked for before the first administrator is created (POST /api/bootstrap);
|
|
518
|
+
# `faden deploy` writes it into .env and sends it. Empty: bootstrap is refused.
|
|
519
|
+
FADEN_BACKEND_BOOTSTRAP_TOKEN: ${FADEN_BACKEND_BOOTSTRAP_TOKEN:-}
|
|
520
|
+
# The update check (Settings > Updates overrides it): `faden deploy` asks whether to read
|
|
521
|
+
# the public list of releases once a day. The release this install runs and how the CLI
|
|
522
|
+
# was installed give the console the upgrade commands to show.
|
|
523
|
+
FADEN_BACKEND_UPDATES_CHECK_ENABLED: ${FADEN_UPDATE_CHECK:-true}
|
|
524
|
+
# A copy of the release list in your network, for a server without internet (Settings > Updates too).
|
|
525
|
+
FADEN_BACKEND_UPDATES_FEED_URL: ${FADEN_UPDATE_FEED_URL:-}
|
|
526
|
+
FADEN_BACKEND_INSTALL_RELEASE: ${VERSION:-}
|
|
527
|
+
FADEN_BACKEND_CLI_INSTALLER: ${FADEN_CLI_INSTALLER:-}
|
|
528
|
+
# Module enabled flags + service URLs (Docker-internal for health probes)
|
|
529
|
+
FADEN_BACKEND_PII_ENABLED: ${FADEN_BACKEND_PII_ENABLED:-false}
|
|
530
|
+
FADEN_BACKEND_PII_SERVICE_URL: ${FADEN_BACKEND_PII_SERVICE_URL:-http://faden-pii:8000/api}
|
|
531
|
+
FADEN_BACKEND_INTERNAL_TOKEN: ${FADEN_BACKEND_INTERNAL_TOKEN:-}
|
|
532
|
+
FADEN_BACKEND_MCP_ENABLED: ${FADEN_BACKEND_MCP_ENABLED:-false}
|
|
533
|
+
FADEN_BACKEND_MCP_SERVICE_URL: ${FADEN_BACKEND_MCP_SERVICE_URL:-http://faden-mcp:8000}
|
|
534
|
+
FADEN_BACKEND_MCP_SERVICE_TOKEN: ${FADEN_BACKEND_MCP_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
535
|
+
FADEN_BACKEND_SKILLS_ENABLED: ${FADEN_BACKEND_SKILLS_ENABLED:-false}
|
|
536
|
+
FADEN_BACKEND_MAILER_SERVICE_URL: ${FADEN_BACKEND_MAILER_SERVICE_URL:-http://faden-mailer:8000}
|
|
537
|
+
FADEN_BACKEND_AUTH_SERVICE_URL: ${FADEN_BACKEND_AUTH_SERVICE_URL:-http://faden-auth:8000}
|
|
538
|
+
FADEN_BACKEND_DOCLING_SERVICE_URL: ${FADEN_BACKEND_DOCLING_SERVICE_URL:-http://faden-docling:8000}
|
|
539
|
+
FADEN_BACKEND_SKILLS_SERVICE_URL: ${FADEN_BACKEND_SKILLS_SERVICE_URL:-http://faden-skills:8000}
|
|
540
|
+
FADEN_BACKEND_SKILLS_SERVICE_TOKEN: ${FADEN_BACKEND_SKILLS_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
541
|
+
# Scalability tuning (set via faden tune)
|
|
542
|
+
FADEN_BACKEND_WORKERS_COUNT: ${FADEN_BACKEND_WORKERS_COUNT:-4}
|
|
543
|
+
FADEN_BACKEND_DB_POOL_SIZE: ${FADEN_BACKEND_DB_POOL_SIZE:-5}
|
|
544
|
+
FADEN_BACKEND_DB_MAX_OVERFLOW: ${FADEN_BACKEND_DB_MAX_OVERFLOW:-5}
|
|
545
|
+
FADEN_BACKEND_RABBIT_POOL_SIZE: ${FADEN_BACKEND_RABBIT_POOL_SIZE:-2}
|
|
546
|
+
FADEN_BACKEND_RABBIT_CHANNEL_POOL_SIZE: ${FADEN_BACKEND_RABBIT_CHANNEL_POOL_SIZE:-10}
|
|
547
|
+
FADEN_BACKEND_MODEL_STORE_ROOT: /srv/faden/models
|
|
548
|
+
FADEN_BACKEND_HOST_HF_CACHE_DIR: ${FADEN_BACKEND_HOST_HF_CACHE_DIR:-}
|
|
549
|
+
# Runtime monitoring: the clusters' and runtimes' scrape targets for the
|
|
550
|
+
# Prometheus above and their Grafana dashboards. The cluster page and the
|
|
551
|
+
# providers' live figures read it. Off with
|
|
552
|
+
# FADEN_BACKEND_LLM_MONITORING_ENABLED=false.
|
|
553
|
+
FADEN_BACKEND_LLM_MONITORING_ENABLED: ${FADEN_BACKEND_LLM_MONITORING_ENABLED:-true}
|
|
554
|
+
FADEN_BACKEND_PROM_URL: http://prometheus:9090
|
|
555
|
+
FADEN_BACKEND_PROM_TARGETS_FILE: /opt/faden/monitoring/prometheus/targets.json
|
|
556
|
+
FADEN_BACKEND_PROM_DASHBOARD_DIR: /opt/faden/monitoring/dashboards
|
|
557
|
+
FADEN_BACKEND_DASH_TEMPLATE: /opt/faden/monitoring/templates/vllm-runtime.json
|
|
558
|
+
FADEN_BACKEND_DASH_FOLDER: "LLM Runtimes"
|
|
559
|
+
volumes:
|
|
560
|
+
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
561
|
+
- faden_models:/srv/faden/models
|
|
562
|
+
# Knowledge base uploads (rag_lite.file_store_root): written here, read by faden-backend-worker,
|
|
563
|
+
# which ingests them. Each container had its own: the worker found no file, every ingest failed,
|
|
564
|
+
# and the uploads went with the container.
|
|
565
|
+
- faden_rag_lite:/data/faden/rag-lite
|
|
566
|
+
# Runtime monitoring — shared with the prometheus + grafana
|
|
567
|
+
# services (see their mounts). The backend generates
|
|
568
|
+
# prometheus/targets.json and dashboards/*.json here; grafana
|
|
569
|
+
# reads the same json dir via its provisioning mount.
|
|
570
|
+
- ./prometheus/targets.json:/opt/faden/monitoring/prometheus/targets.json:rw
|
|
571
|
+
- ./grafana/provisioning/dashboards/json:/opt/faden/monitoring/dashboards:rw
|
|
572
|
+
- ./grafana/dashboards/templates:/opt/faden/monitoring/templates:ro
|
|
573
|
+
# Agent builds the install line hands out (faden-agent-linux-<arch>).
|
|
574
|
+
# Without a copy here a machine can only fetch the published release,
|
|
575
|
+
# which an air-gapped site cannot reach and a new agent may not be yet.
|
|
576
|
+
- ./agent-binaries:/srv/faden/agent-binaries:ro
|
|
577
|
+
# The edge certificate and key the TLS admin API writes; nginx mounts
|
|
578
|
+
# the same directory read-only and serves HTTPS from it.
|
|
579
|
+
- ./tls:/etc/faden/tls:rw
|
|
580
|
+
extra_hosts:
|
|
581
|
+
- "host.docker.internal:host-gateway"
|
|
582
|
+
healthcheck:
|
|
583
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health', timeout=3).read()"]
|
|
584
|
+
interval: 5s
|
|
585
|
+
timeout: 5s
|
|
586
|
+
retries: 20
|
|
587
|
+
|
|
588
|
+
faden-backend-worker:
|
|
589
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/backend:${VERSION:-latest}
|
|
590
|
+
container_name: faden-backend-worker
|
|
591
|
+
restart: unless-stopped
|
|
592
|
+
command:
|
|
593
|
+
- taskiq
|
|
594
|
+
- worker
|
|
595
|
+
- faden_backend.tkq:broker
|
|
596
|
+
- --fs-discover
|
|
597
|
+
# Processes: two, or one on a server short of memory (set via faden tune).
|
|
598
|
+
- --workers
|
|
599
|
+
- ${FADEN_BACKEND_TASK_WORKERS:-2}
|
|
600
|
+
depends_on:
|
|
601
|
+
postgres:
|
|
602
|
+
condition: service_healthy
|
|
603
|
+
faden-rmq:
|
|
604
|
+
condition: service_healthy
|
|
605
|
+
faden-backend-migrator:
|
|
606
|
+
condition: service_completed_successfully
|
|
607
|
+
environment:
|
|
608
|
+
FADEN_BACKEND_ENVIRONMENT: ${FADEN_BACKEND_ENVIRONMENT:-production}
|
|
609
|
+
FADEN_BACKEND_DB_HOST: postgres
|
|
610
|
+
FADEN_BACKEND_DB_PORT: 5432
|
|
611
|
+
FADEN_BACKEND_DB_USER: ${POSTGRES_USER:-postgres}
|
|
612
|
+
FADEN_BACKEND_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
613
|
+
FADEN_BACKEND_DB_BASE: faden_backend
|
|
614
|
+
FADEN_BACKEND_REDIS_HOST: redis
|
|
615
|
+
FADEN_BACKEND_REDIS_PORT: 6379
|
|
616
|
+
FADEN_BACKEND_REDIS_PASS: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
617
|
+
FADEN_BACKEND_RABBIT_HOST: faden-rmq
|
|
618
|
+
FADEN_BACKEND_RABBIT_PORT: 5672
|
|
619
|
+
FADEN_BACKEND_RABBIT_USER: faden-backend
|
|
620
|
+
FADEN_BACKEND_RABBIT_PASS: ${RABBITMQ_BACKEND_PASS:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
621
|
+
FADEN_BACKEND_RABBIT_VHOST: /
|
|
622
|
+
FADEN_BACKEND_GATEWAY_URL: ${FADEN_BACKEND_GATEWAY_URL:-http://faden-gateway:8000}
|
|
623
|
+
FADEN_BACKEND_SETTINGS_MASTER_KEY: ${FADEN_BACKEND_SETTINGS_MASTER_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
624
|
+
FADEN_BACKEND_LLM_GRAPH_DB_HOST: postgres
|
|
625
|
+
FADEN_BACKEND_LLM_GRAPH_DB_USER: ${POSTGRES_USER:-postgres}
|
|
626
|
+
FADEN_BACKEND_LLM_GRAPH_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
627
|
+
FADEN_BACKEND_LOKI_BASE_URL: http://faden-loki:3100
|
|
628
|
+
FADEN_BACKEND_COOKIE_SECURE: "false"
|
|
629
|
+
USERS_SECRET: ${USERS_SECRET:-}
|
|
630
|
+
# Module enabled flags + service URLs (Docker-internal for health probes)
|
|
631
|
+
FADEN_BACKEND_MCP_ENABLED: ${FADEN_BACKEND_MCP_ENABLED:-false}
|
|
632
|
+
FADEN_BACKEND_SKILLS_ENABLED: ${FADEN_BACKEND_SKILLS_ENABLED:-false}
|
|
633
|
+
FADEN_BACKEND_PII_SERVICE_URL: ${FADEN_BACKEND_PII_SERVICE_URL:-http://faden-pii:8000/api}
|
|
634
|
+
FADEN_BACKEND_INTERNAL_TOKEN: ${FADEN_BACKEND_INTERNAL_TOKEN:-}
|
|
635
|
+
FADEN_BACKEND_MCP_SERVICE_URL: ${FADEN_BACKEND_MCP_SERVICE_URL:-http://faden-mcp:8000}
|
|
636
|
+
FADEN_BACKEND_MCP_SERVICE_TOKEN: ${FADEN_BACKEND_MCP_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
637
|
+
FADEN_BACKEND_MAILER_SERVICE_URL: ${FADEN_BACKEND_MAILER_SERVICE_URL:-http://faden-mailer:8000}
|
|
638
|
+
FADEN_BACKEND_AUTH_SERVICE_URL: ${FADEN_BACKEND_AUTH_SERVICE_URL:-http://faden-auth:8000}
|
|
639
|
+
FADEN_BACKEND_DOCLING_SERVICE_URL: ${FADEN_BACKEND_DOCLING_SERVICE_URL:-http://faden-docling:8000}
|
|
640
|
+
FADEN_BACKEND_SKILLS_SERVICE_URL: ${FADEN_BACKEND_SKILLS_SERVICE_URL:-http://faden-skills:8000}
|
|
641
|
+
FADEN_BACKEND_SKILLS_SERVICE_TOKEN: ${FADEN_BACKEND_SKILLS_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
642
|
+
# Scalability tuning (set via faden tune)
|
|
643
|
+
FADEN_BACKEND_DB_POOL_SIZE: ${FADEN_BACKEND_DB_POOL_SIZE:-5}
|
|
644
|
+
FADEN_BACKEND_DB_MAX_OVERFLOW: ${FADEN_BACKEND_DB_MAX_OVERFLOW:-5}
|
|
645
|
+
FADEN_BACKEND_RABBIT_POOL_SIZE: ${FADEN_BACKEND_RABBIT_POOL_SIZE:-2}
|
|
646
|
+
FADEN_BACKEND_RABBIT_CHANNEL_POOL_SIZE: ${FADEN_BACKEND_RABBIT_CHANNEL_POOL_SIZE:-10}
|
|
647
|
+
FADEN_BACKEND_MODEL_STORE_ROOT: /srv/faden/models
|
|
648
|
+
FADEN_BACKEND_HOST_HF_CACHE_DIR: ${FADEN_BACKEND_HOST_HF_CACHE_DIR:-}
|
|
649
|
+
# Ranges a model download fetches at once, up to 64 MB each in memory
|
|
650
|
+
# (set via faden tune: fewer on a server short of memory).
|
|
651
|
+
HF_XET_NUM_CONCURRENT_RANGE_GETS: ${FADEN_BACKEND_DOWNLOAD_RANGES:-16}
|
|
652
|
+
volumes:
|
|
653
|
+
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
654
|
+
- faden_models:/srv/faden/models
|
|
655
|
+
- faden_rag_lite:/data/faden/rag-lite
|
|
656
|
+
|
|
657
|
+
# -----------------------------
|
|
658
|
+
# frontend (React admin console)
|
|
659
|
+
# -----------------------------
|
|
660
|
+
faden-frontend:
|
|
661
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/frontend:${VERSION:-latest}
|
|
662
|
+
build:
|
|
663
|
+
context: ../frontend
|
|
664
|
+
dockerfile: Dockerfile
|
|
665
|
+
# Help is built into the image from docs/help and docs/theme and served at /help.
|
|
666
|
+
additional_contexts:
|
|
667
|
+
docs: ../docs
|
|
668
|
+
container_name: faden-frontend
|
|
669
|
+
restart: unless-stopped
|
|
670
|
+
depends_on:
|
|
671
|
+
faden-backend:
|
|
672
|
+
condition: service_healthy
|
|
673
|
+
# No host port — accessed via nginx reverse proxy
|
|
674
|
+
environment:
|
|
675
|
+
BACKEND_URL: http://faden-backend:8000
|
|
676
|
+
API_URL: http://faden-gateway:8000
|
|
677
|
+
|
|
678
|
+
# =====================================================================
|
|
679
|
+
# PII Protection (profile: pii)
|
|
680
|
+
#
|
|
681
|
+
# Core redact-only mode. EE extends with tokenize/detokenize.
|
|
682
|
+
# Activate with: --profile pii (or COMPOSE_PROFILES=pii)
|
|
683
|
+
# =====================================================================
|
|
684
|
+
faden-pii:
|
|
685
|
+
profiles: ["pii"]
|
|
686
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/pii:${VERSION:-latest}
|
|
687
|
+
build:
|
|
688
|
+
context: ../pii
|
|
689
|
+
dockerfile: Dockerfile
|
|
690
|
+
target: prod
|
|
691
|
+
args:
|
|
692
|
+
BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
|
|
693
|
+
container_name: faden-pii
|
|
694
|
+
restart: unless-stopped
|
|
695
|
+
depends_on:
|
|
696
|
+
faden-rmq:
|
|
697
|
+
condition: service_healthy
|
|
698
|
+
environment:
|
|
699
|
+
FADEN_PII_HOST: 0.0.0.0
|
|
700
|
+
FADEN_PII_PORT: 8000
|
|
701
|
+
FADEN_PII_RELOAD: "false"
|
|
702
|
+
FADEN_PII_ENVIRONMENT: ${FADEN_PII_ENVIRONMENT:-production}
|
|
703
|
+
FADEN_PII_BACKEND_URL: http://faden-backend:8000
|
|
704
|
+
FADEN_PII_BACKEND_TOKEN: ${FADEN_PII_BACKEND_TOKEN:-}
|
|
705
|
+
FADEN_PII_RABBIT_HOST: faden-rmq
|
|
706
|
+
FADEN_PII_RABBIT_PORT: 5672
|
|
707
|
+
FADEN_PII_RABBIT_USER: faden-pii
|
|
708
|
+
FADEN_PII_RABBIT_PASS: ${RABBITMQ_PII_PASS:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
709
|
+
FADEN_PII_RABBIT_VHOST: /
|
|
710
|
+
# Scalability tuning (set via faden tune)
|
|
711
|
+
FADEN_PII_WORKERS_COUNT: ${FADEN_PII_WORKERS_COUNT:-4}
|
|
712
|
+
FADEN_PII_DB_POOL_SIZE: ${FADEN_PII_DB_POOL_SIZE:-5}
|
|
713
|
+
FADEN_PII_DB_MAX_OVERFLOW: ${FADEN_PII_DB_MAX_OVERFLOW:-5}
|
|
714
|
+
healthcheck:
|
|
715
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health', timeout=3).read()"]
|
|
716
|
+
interval: 5s
|
|
717
|
+
timeout: 5s
|
|
718
|
+
retries: 20
|
|
719
|
+
|
|
720
|
+
faden-pii-worker:
|
|
721
|
+
profiles: ["pii"]
|
|
722
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/pii:${VERSION:-latest}
|
|
723
|
+
container_name: faden-pii-worker
|
|
724
|
+
restart: unless-stopped
|
|
725
|
+
command:
|
|
726
|
+
- taskiq
|
|
727
|
+
- worker
|
|
728
|
+
- faden_pii.tkq:broker
|
|
729
|
+
- --fs-discover
|
|
730
|
+
depends_on:
|
|
731
|
+
faden-rmq:
|
|
732
|
+
condition: service_healthy
|
|
733
|
+
environment:
|
|
734
|
+
FADEN_PII_ENVIRONMENT: ${FADEN_PII_ENVIRONMENT:-production}
|
|
735
|
+
FADEN_PII_BACKEND_URL: http://faden-backend:8000
|
|
736
|
+
FADEN_PII_BACKEND_TOKEN: ${FADEN_PII_BACKEND_TOKEN:-}
|
|
737
|
+
FADEN_PII_RABBIT_HOST: faden-rmq
|
|
738
|
+
FADEN_PII_RABBIT_PORT: 5672
|
|
739
|
+
FADEN_PII_RABBIT_USER: faden-pii
|
|
740
|
+
FADEN_PII_RABBIT_PASS: ${RABBITMQ_PII_PASS:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
741
|
+
FADEN_PII_RABBIT_VHOST: /
|
|
742
|
+
|
|
743
|
+
# =====================================================================
|
|
744
|
+
# MCP Tool Registry (profile: mcp)
|
|
745
|
+
#
|
|
746
|
+
# Generic MCP server registry + tool discovery.
|
|
747
|
+
# Activate with: --profile mcp (or COMPOSE_PROFILES=mcp)
|
|
748
|
+
# =====================================================================
|
|
749
|
+
faden-mcp-migrator:
|
|
750
|
+
profiles: ["mcp"]
|
|
751
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/mcp:${VERSION:-latest}
|
|
752
|
+
container_name: faden-mcp-migrator
|
|
753
|
+
restart: on-failure:5
|
|
754
|
+
command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
|
|
755
|
+
depends_on:
|
|
756
|
+
postgres:
|
|
757
|
+
condition: service_healthy
|
|
758
|
+
environment:
|
|
759
|
+
FADEN_MCP_DB_HOST: postgres
|
|
760
|
+
FADEN_MCP_DB_PORT: 5432
|
|
761
|
+
FADEN_MCP_DB_USER: ${POSTGRES_USER:-postgres}
|
|
762
|
+
FADEN_MCP_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
763
|
+
FADEN_MCP_DB_BASE: faden_mcp
|
|
764
|
+
|
|
765
|
+
faden-mcp:
|
|
766
|
+
profiles: ["mcp"]
|
|
767
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/mcp:${VERSION:-latest}
|
|
768
|
+
build:
|
|
769
|
+
context: ../mcp
|
|
770
|
+
dockerfile: Dockerfile
|
|
771
|
+
target: prod
|
|
772
|
+
args:
|
|
773
|
+
BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
|
|
774
|
+
container_name: faden-mcp
|
|
775
|
+
restart: unless-stopped
|
|
776
|
+
depends_on:
|
|
777
|
+
postgres:
|
|
778
|
+
condition: service_healthy
|
|
779
|
+
redis:
|
|
780
|
+
condition: service_healthy
|
|
781
|
+
faden-mcp-migrator:
|
|
782
|
+
condition: service_completed_successfully
|
|
783
|
+
environment:
|
|
784
|
+
FADEN_MCP_HOST: 0.0.0.0
|
|
785
|
+
FADEN_MCP_PORT: 8000
|
|
786
|
+
FADEN_MCP_RELOAD: "false"
|
|
787
|
+
FADEN_MCP_ENVIRONMENT: ${FADEN_MCP_ENVIRONMENT:-production}
|
|
788
|
+
FADEN_MCP_DB_HOST: postgres
|
|
789
|
+
FADEN_MCP_DB_PORT: 5432
|
|
790
|
+
FADEN_MCP_DB_USER: ${POSTGRES_USER:-postgres}
|
|
791
|
+
FADEN_MCP_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
792
|
+
FADEN_MCP_DB_BASE: faden_mcp
|
|
793
|
+
FADEN_MCP_REDIS_HOST: redis
|
|
794
|
+
FADEN_MCP_REDIS_PORT: 6379
|
|
795
|
+
FADEN_MCP_REDIS_PASS: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
796
|
+
FADEN_MCP_REDIS_BASE: 3
|
|
797
|
+
FADEN_MCP_PII_SERVICE_URL: ${FADEN_MCP_PII_SERVICE_URL:-http://faden-pii:8000}
|
|
798
|
+
FADEN_MCP_SERVICE_TOKEN: ${FADEN_MCP_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
799
|
+
FADEN_MCP_ENCRYPTION_KEY: ${FADEN_MCP_ENCRYPTION_KEY:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
800
|
+
# An install that has stored data under the published development key may
|
|
801
|
+
# keep it, with a warning at every start, until it is changed (Help:
|
|
802
|
+
# Installing, Secrets in .env). Outside development the service refuses it otherwise.
|
|
803
|
+
FADEN_MCP_ALLOW_PUBLISHED_KEYS: ${FADEN_ALLOW_PUBLISHED_KEYS:-false}
|
|
804
|
+
FADEN_MCP_WORKERS_COUNT: ${FADEN_MCP_WORKERS_COUNT:-1}
|
|
805
|
+
healthcheck:
|
|
806
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health', timeout=3).read()"]
|
|
807
|
+
interval: 5s
|
|
808
|
+
timeout: 5s
|
|
809
|
+
retries: 20
|
|
810
|
+
extra_hosts:
|
|
811
|
+
- "host.docker.internal:host-gateway"
|
|
812
|
+
|
|
813
|
+
# =====================================================================
|
|
814
|
+
# Skills Registry (profile: skills)
|
|
815
|
+
#
|
|
816
|
+
# Centralized LLM skill management with versioning & assignments.
|
|
817
|
+
# Activate with: --profile skills (or COMPOSE_PROFILES=skills)
|
|
818
|
+
# =====================================================================
|
|
819
|
+
faden-skills-migrator:
|
|
820
|
+
profiles: ["skills"]
|
|
821
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/skills:${VERSION:-latest}
|
|
822
|
+
container_name: faden-skills-migrator
|
|
823
|
+
restart: on-failure:5
|
|
824
|
+
command: ["sh", "-c", "sleep 5 && alembic upgrade head"]
|
|
825
|
+
depends_on:
|
|
826
|
+
postgres:
|
|
827
|
+
condition: service_healthy
|
|
828
|
+
environment:
|
|
829
|
+
FADEN_SKILLS_DB_HOST: postgres
|
|
830
|
+
FADEN_SKILLS_DB_PORT: 5432
|
|
831
|
+
FADEN_SKILLS_DB_USER: ${POSTGRES_USER:-postgres}
|
|
832
|
+
FADEN_SKILLS_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
833
|
+
FADEN_SKILLS_DB_BASE: faden_skills
|
|
834
|
+
|
|
835
|
+
faden-skills:
|
|
836
|
+
profiles: ["skills"]
|
|
837
|
+
image: ${REGISTRY:-ghcr.io/fadenstack}/skills:${VERSION:-latest}
|
|
838
|
+
build:
|
|
839
|
+
context: ../skills
|
|
840
|
+
dockerfile: Dockerfile
|
|
841
|
+
target: prod
|
|
842
|
+
args:
|
|
843
|
+
BASE_IMAGE: ${REGISTRY:-ghcr.io/fadenstack}/base:${VERSION:-latest}
|
|
844
|
+
container_name: faden-skills
|
|
845
|
+
restart: unless-stopped
|
|
846
|
+
depends_on:
|
|
847
|
+
postgres:
|
|
848
|
+
condition: service_healthy
|
|
849
|
+
redis:
|
|
850
|
+
condition: service_healthy
|
|
851
|
+
faden-skills-migrator:
|
|
852
|
+
condition: service_completed_successfully
|
|
853
|
+
environment:
|
|
854
|
+
FADEN_SKILLS_HOST: 0.0.0.0
|
|
855
|
+
FADEN_SKILLS_PORT: 8000
|
|
856
|
+
FADEN_SKILLS_RELOAD: "false"
|
|
857
|
+
FADEN_SKILLS_ENVIRONMENT: ${FADEN_SKILLS_ENVIRONMENT:-production}
|
|
858
|
+
FADEN_SKILLS_DB_HOST: postgres
|
|
859
|
+
FADEN_SKILLS_DB_PORT: 5432
|
|
860
|
+
FADEN_SKILLS_DB_USER: ${POSTGRES_USER:-postgres}
|
|
861
|
+
FADEN_SKILLS_DB_PASS: ${POSTGRES_PASSWORD:?set it in .env; an install that ran without it keeps its data only with the old default value (Help, Installing, Secrets in .env)}
|
|
862
|
+
FADEN_SKILLS_DB_BASE: faden_skills
|
|
863
|
+
FADEN_SKILLS_REDIS_HOST: redis
|
|
864
|
+
FADEN_SKILLS_REDIS_PORT: 6379
|
|
865
|
+
FADEN_SKILLS_REDIS_PASS: ${REDIS_AUTH:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
866
|
+
FADEN_SKILLS_REDIS_BASE: 4
|
|
867
|
+
FADEN_SKILLS_SERVICE_TOKEN: ${FADEN_SKILLS_SERVICE_TOKEN:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
868
|
+
FADEN_SKILLS_WORKERS_COUNT: ${FADEN_SKILLS_WORKERS_COUNT:-1}
|
|
869
|
+
healthcheck:
|
|
870
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health', timeout=3).read()"]
|
|
871
|
+
interval: 5s
|
|
872
|
+
timeout: 5s
|
|
873
|
+
retries: 20
|
|
874
|
+
|
|
875
|
+
# -----------------------------
|
|
876
|
+
# Observability: Loki + Grafana + Alloy + Prometheus
|
|
877
|
+
# -----------------------------
|
|
878
|
+
prometheus:
|
|
879
|
+
# Scrape targets for LLM runtime (vLLM) /metrics endpoints.
|
|
880
|
+
# targets.json is GENERATED by the backend's monitoring
|
|
881
|
+
# provisioner (bound rw below); the service never binds a public
|
|
882
|
+
# host port — Grafana and the backend reach it on the compose
|
|
883
|
+
# network. Set PROM_BIND=127.0.0.1 is the safe default (loopback
|
|
884
|
+
# for debugging); omit the port entirely if you want it
|
|
885
|
+
# compose-private.
|
|
886
|
+
image: prom/prometheus:v2.53.0
|
|
887
|
+
container_name: faden-prometheus
|
|
888
|
+
restart: unless-stopped
|
|
889
|
+
ports:
|
|
890
|
+
# Not 9090 on the host: MinIO's API is published there in this stack,
|
|
891
|
+
# and with that default an upgrade stopped on "Bind for 127.0.0.1:9090
|
|
892
|
+
# failed: port is already allocated". Inside the compose network
|
|
893
|
+
# Prometheus is always :9090, which is what Grafana and the backend use.
|
|
894
|
+
- "${PROM_BIND:-127.0.0.1}:${PROM_PORT:-9099}:9090"
|
|
895
|
+
command:
|
|
896
|
+
- --config.file=/etc/prometheus/prometheus.yml
|
|
897
|
+
- --storage.tsdb.path=/prometheus
|
|
898
|
+
- --storage.tsdb.retention.time=14d
|
|
899
|
+
- --web.enable-lifecycle
|
|
900
|
+
volumes:
|
|
901
|
+
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
|
902
|
+
# Generated by faden-backend — do not hand-edit.
|
|
903
|
+
- ./prometheus/targets.json:/etc/prometheus/targets.json:rw
|
|
904
|
+
- prom_data:/prometheus
|
|
905
|
+
extra_hosts:
|
|
906
|
+
# Lets us scrape LOCAL_DOCKER runtimes on this host (mirrors the
|
|
907
|
+
# backend service's host-gateway mapping).
|
|
908
|
+
- "host.docker.internal:host-gateway"
|
|
909
|
+
|
|
910
|
+
loki:
|
|
911
|
+
image: grafana/loki:3.0.0
|
|
912
|
+
container_name: faden-loki
|
|
913
|
+
restart: unless-stopped
|
|
914
|
+
# Loki has no authentication — it must never be reachable from the
|
|
915
|
+
# network. Default to the loopback interface only; set LOKI_BIND
|
|
916
|
+
# deliberately if you need to expose it behind a firewall/proxy.
|
|
917
|
+
ports:
|
|
918
|
+
- "${LOKI_BIND:-127.0.0.1}:3100:3100"
|
|
919
|
+
command: -config.file=/etc/loki/local-config.yaml
|
|
920
|
+
volumes:
|
|
921
|
+
- ./loki/local-config.yaml:/etc/loki/local-config.yaml:ro
|
|
922
|
+
- loki_data:/loki
|
|
923
|
+
|
|
924
|
+
grafana:
|
|
925
|
+
# 12.4, the last 12.x line, security-supported until May 2027 (11.6 ended in
|
|
926
|
+
# June 2026), pinned by digest. It carries the fixes for the XSS advisories
|
|
927
|
+
# 11.5.2 lacked (CVE-2025-2703, CVE-2025-4123, CVE-2025-6023 and its bypass).
|
|
928
|
+
# The dashboards use only core panels, which 12 still ships. Grafana
|
|
929
|
+
# migrates its database on the first start (tested from 11.5.2); going
|
|
930
|
+
# back needs the backup the upgrade makes.
|
|
931
|
+
image: grafana/grafana:12.4.12@sha256:a3b504df900c24db125e5ec0646f3ac3428db38161302d69f05d0db70a330a90
|
|
932
|
+
container_name: faden-grafana
|
|
933
|
+
restart: unless-stopped
|
|
934
|
+
ports:
|
|
935
|
+
# Dashboards, anonymous read-only (login form disabled), plain HTTP. The
|
|
936
|
+
# console reaches them through nginx at /grafana/ -- over HTTPS when that
|
|
937
|
+
# is on -- so the port itself stays on this machine by default; published
|
|
938
|
+
# on the network it bypassed HTTPS and showed every dashboard to anyone.
|
|
939
|
+
# GRAFANA_BIND=0.0.0.0 publishes it.
|
|
940
|
+
- "${GRAFANA_BIND:-127.0.0.1}:3001:3000"
|
|
941
|
+
environment:
|
|
942
|
+
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
|
|
943
|
+
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:?set it in .env, as faden deploy and faden upgrade do (Help, Installing, Secrets in .env)}
|
|
944
|
+
GF_SECURITY_ALLOW_EMBEDDING: "true"
|
|
945
|
+
GF_SECURITY_COOKIE_SAMESITE: "disabled"
|
|
946
|
+
GF_AUTH_ANONYMOUS_ENABLED: "true"
|
|
947
|
+
GF_AUTH_ANONYMOUS_ORG_ROLE: Viewer
|
|
948
|
+
GF_AUTH_ANONYMOUS_ORG_NAME: Main Org.
|
|
949
|
+
GF_AUTH_DISABLE_LOGIN_FORM: "true"
|
|
950
|
+
GF_AUTH_BASIC_ENABLED: "false"
|
|
951
|
+
GF_SERVER_ROOT_URL: "%(protocol)s://%(domain)s:%(http_port)s/grafana/"
|
|
952
|
+
GF_SERVER_SERVE_FROM_SUB_PATH: "true"
|
|
953
|
+
GF_PLUGINS_PREINSTALL: ""
|
|
954
|
+
GF_PATHS_PROVISIONING: /etc/grafana/provisioning
|
|
955
|
+
# Nothing leaves this server: no usage reports, no update or plugin
|
|
956
|
+
# checks against grafana.com, no news feed, no Gravatar pictures.
|
|
957
|
+
GF_ANALYTICS_REPORTING_ENABLED: "false"
|
|
958
|
+
GF_ANALYTICS_CHECK_FOR_UPDATES: "false"
|
|
959
|
+
GF_ANALYTICS_CHECK_FOR_PLUGIN_UPDATES: "false"
|
|
960
|
+
GF_NEWS_NEWS_FEED_ENABLED: "false"
|
|
961
|
+
GF_SECURITY_DISABLE_GRAVATAR: "true"
|
|
962
|
+
volumes:
|
|
963
|
+
- grafana_data:/var/lib/grafana
|
|
964
|
+
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
|
965
|
+
depends_on:
|
|
966
|
+
- loki
|
|
967
|
+
|
|
968
|
+
alloy:
|
|
969
|
+
# Pinned, not :latest: an install otherwise ran whatever was published
|
|
970
|
+
# last. --disable-reporting: no usage reports to Grafana Labs.
|
|
971
|
+
image: grafana/alloy:v1.20.1@sha256:2aa2099af76c0098d4af7a4d6e48f86cb66dc1a000222ad927a1c67c6542d13f
|
|
972
|
+
container_name: faden-alloy
|
|
973
|
+
restart: unless-stopped
|
|
974
|
+
ports:
|
|
975
|
+
- "127.0.0.1:12345:12345"
|
|
976
|
+
command: >
|
|
977
|
+
run --server.http.listen-addr=0.0.0.0:12345
|
|
978
|
+
--disable-reporting
|
|
979
|
+
/etc/alloy/config.alloy
|
|
980
|
+
volumes:
|
|
981
|
+
- ./alloy/config.alloy:/etc/alloy/config.alloy:ro
|
|
982
|
+
# Docker Desktop on Windows exposes the socket here; Linux path is /var/run/docker.sock
|
|
983
|
+
- //var/run/docker.sock:/var/run/docker.sock:ro
|
|
984
|
+
depends_on:
|
|
985
|
+
- loki
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
volumes:
|
|
990
|
+
pg_data:
|
|
991
|
+
ch_data:
|
|
992
|
+
ch_logs:
|
|
993
|
+
minio_data:
|
|
994
|
+
loki_data:
|
|
995
|
+
grafana_data:
|
|
996
|
+
prom_data:
|
|
997
|
+
faden_models:
|
|
998
|
+
faden_rag_lite:
|