-
Notifications
You must be signed in to change notification settings - Fork 3k
Expand file tree
/
Copy pathdocker-compose.dev.yml
More file actions
292 lines (289 loc) · 16.6 KB
/
Copy pathdocker-compose.dev.yml
File metadata and controls
292 lines (289 loc) · 16.6 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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# OpenWA - Local smoke / quick-start compose
#
# This builds and runs the PRODUCTION image (same Dockerfile) against a local SQLite DB
# with a bind-mounted ./data — it is a single-container local smoke test, NOT a
# hot-reload development environment (there is no source mount or `start:dev`).
# DATABASE_SYNCHRONIZE=true keeps the SQLite schema zero-config for local use; the
# production compose (docker-compose.yml) never forces synchronize (it defaults to false).
#
# Quick Start: docker compose -f docker-compose.dev.yml up -d
services:
# API Backend
openwa:
build:
context: .
dockerfile: Dockerfile
container_name: openwa-api
# Container hardening — same posture as production (same Dockerfile/entrypoint).
security_opt:
- 'no-new-privileges:true'
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
read_only: true
tmpfs:
- /tmp
# Per-container PID ceiling (cgroup pids.max). 2048 fits several whatsapp-web.js sessions, which
# each run a multi-process Chromium; Baileys (no Chromium) uses far fewer. A fork-bomb guard, not
# an allocation — raising it is free for light containers. Do NOT use -1 (drops the guard). #636
pids_limit: ${OPENWA_PIDS_LIMIT:-2048}
mem_limit: ${OPENWA_MEM_LIMIT:-2g}
ports:
# Bind to localhost by default; set BIND_HOST=0.0.0.0 in .env to reach it from another host.
- '${BIND_HOST:-127.0.0.1}:2785:2785'
# User-facing settings read from the environment (or .env) with a sane default fallback
# (${VAR:-default}); override any of them without editing this file. The data paths default
# under /app/data (the ./data bind mount) so they persist out of the box — override only if you
# also mount that target. Truly container-internal values (HOME, XDG_*, PORT) stay fixed: they
# must match the image/entrypoint. Same convention as the production docker-compose.yml.
environment:
- NODE_ENV=${NODE_ENV:-development}
- PORT=2785
- HOME=/tmp
# Chromium reads its home from the passwd entry (no /home/openwa), so it needs writable, existing
# config/cache dirs on the tmpfs or it hard-crashes at launch; the entrypoint pre-creates them. (#254)
- XDG_CONFIG_HOME=/tmp/.config
- XDG_CACHE_HOME=/tmp/.cache
- LOG_LEVEL=${LOG_LEVEL:-info}
# Restart-resilience: auto-start previously authenticated sessions on boot. The liveness
# watchdog (#798) only covers a RUNNING container — a `compose down/up` or rebuild kills every
# engine, and without this flag sessions sit at `disconnected` until started by hand. Default
# ON for the dev compose (single-operator box); the app-level default stays OFF.
- AUTO_START_SESSIONS=${AUTO_START_SESSIONS:-true}
- DATABASE_TYPE=${DATABASE_TYPE:-sqlite}
- DATABASE_NAME=${DATABASE_NAME:-}
- DATABASE_SYNCHRONIZE=${DATABASE_SYNCHRONIZE:-true}
# Engine. Forwarded empty by default so the dashboard (Infrastructure > Engine) selects the
# active engine via data/.env.generated (default whatsapp-web.js); main.ts treats a blank
# ENGINE_TYPE as unset, so .env.generated wins. Set ENGINE_TYPE in your .env/host to pin an
# engine (e.g. baileys) — a real value flows through here and keeps top precedence.
- ENGINE_TYPE=${ENGINE_TYPE:-}
- SESSION_DATA_PATH=${SESSION_DATA_PATH:-/app/data/sessions}
- PUPPETEER_HEADLESS=${PUPPETEER_HEADLESS:-true}
- PUPPETEER_ARGS=${PUPPETEER_ARGS:---no-sandbox,--disable-setuid-sandbox,--disable-dev-shm-usage,--disable-gpu}
# Optional WhatsApp Web version override. DEFAULT (empty, "latest", or "auto"): OpenWA auto-resolves a
# settled build from the third-party wppconnect-team/wa-version registry and pins its remote HTML
# (fetched into the web.whatsapp.com origin without an integrity check). Set "off" to disable pinning
# and use the first-party build served by WhatsApp, or an exact version to pin a specific build.
- WWEBJS_WEB_VERSION=${WWEBJS_WEB_VERSION:-}
- WWEBJS_WEB_VERSION_REMOTE_PATH=${WWEBJS_WEB_VERSION_REMOTE_PATH:-}
# Raise whatsapp-web.js's first-boot init wait (default 30000ms) on slow boots. Empty = default.
- WWEBJS_AUTH_TIMEOUT_MS=${WWEBJS_AUTH_TIMEOUT_MS:-}
# Forward the plain-HTTP dashboard CSP override; unset preserves the application default.
- CSP_UPGRADE_INSECURE_REQUESTS=${CSP_UPGRADE_INSECURE_REQUESTS:-}
- STORAGE_TYPE=${STORAGE_TYPE:-local}
- STORAGE_LOCAL_PATH=${STORAGE_LOCAL_PATH:-/app/data/media}
# Install plugins into the writable, persistent data volume (the root FS is read-only). Matches
# docker-compose.yml and the application default; set explicitly so the path stays correct even
# if the volume moves.
- PLUGINS_DIR=${PLUGINS_DIR:-/app/data/plugins}
- PLUGIN_STATE_DIR=${PLUGIN_STATE_DIR:-}
# Plugin install-from-URL redirect policy (ssrf-guard): off unless the exact string 'true'.
- PLUGIN_DOWNLOAD_ALLOW_INSECURE_REDIRECTS=${PLUGIN_DOWNLOAD_ALLOW_INSECURE_REDIRECTS:-false}
- WEBHOOK_TIMEOUT=${WEBHOOK_TIMEOUT:-10000}
- WEBHOOK_RETRY_DELAY=${WEBHOOK_RETRY_DELAY:-5000}
- WEBHOOK_DISPATCH_CONCURRENCY=${WEBHOOK_DISPATCH_CONCURRENCY:-16}
- WEBHOOK_DISPATCH_MAX_QUEUED=${WEBHOOK_DISPATCH_MAX_QUEUED:-1000}
# Mirrors docker-compose.yml: flags with no dashboard route, which a .env value could not
# otherwise reach the container at all.
- WEBHOOK_CONTACT_DETAILS=${WEBHOOK_CONTACT_DETAILS:-}
- BAILEYS_MARK_ONLINE_ON_CONNECT=${BAILEYS_MARK_ONLINE_ON_CONNECT:-}
- BAILEYS_SYNC_FULL_HISTORY=${BAILEYS_SYNC_FULL_HISTORY:-}
- BAILEYS_WA_VERSION=${BAILEYS_WA_VERSION:-}
- ALLOW_UNSIGNED_INGRESS=${ALLOW_UNSIGNED_INGRESS:-}
- STORE_EPHEMERAL_MESSAGES=${STORE_EPHEMERAL_MESSAGES:-}
- RESOLVE_LID_TO_PHONE=${RESOLVE_LID_TO_PHONE:-}
- SIMULATE_TYPING=${SIMULATE_TYPING:-}
- MCP_ENABLED=${MCP_ENABLED:-}
- SEARCH_ENABLED=${SEARCH_ENABLED:-}
- SERVE_DASHBOARD=${SERVE_DASHBOARD:-}
- CACHE_ENABLED=${CACHE_ENABLED:-}
- DATABASE_LOGGING=${DATABASE_LOGGING:-}
- MAIN_DATABASE_SYNCHRONIZE=${MAIN_DATABASE_SYNCHRONIZE:-}
- RATE_LIMIT_SHORT_TTL=${RATE_LIMIT_SHORT_TTL:-}
- RATE_LIMIT_SHORT_LIMIT=${RATE_LIMIT_SHORT_LIMIT:-}
- RATE_LIMIT_MEDIUM_TTL=${RATE_LIMIT_MEDIUM_TTL:-}
- RATE_LIMIT_MEDIUM_LIMIT=${RATE_LIMIT_MEDIUM_LIMIT:-}
- RATE_LIMIT_LONG_TTL=${RATE_LIMIT_LONG_TTL:-}
- RATE_LIMIT_LONG_LIMIT=${RATE_LIMIT_LONG_LIMIT:-}
# Max request body size. Base64 media sends ride in the JSON body, so the default is generous;
# raise this for large documents (e.g. BODY_SIZE_LIMIT=50mb). Blank keeps the app default of 25mb.
- BODY_SIZE_LIMIT=${BODY_SIZE_LIMIT:-}
- TRUSTED_PROXIES=${TRUSTED_PROXIES:-}
- QUEUE_ENABLED=${QUEUE_ENABLED:-false}
# Opt-in feature flags. Forwarded explicitly for the same reason as docker-compose.yml: this
# file has no env_file, so a variable absent from this list never reaches the container and
# the feature it gates stays off however the operator's .env is written.
- CHAT_MEDIA_ARCHIVE_ENABLED=${CHAT_MEDIA_ARCHIVE_ENABLED:-}
- CHAT_MEDIA_ARCHIVE_OUTBOUND=${CHAT_MEDIA_ARCHIVE_OUTBOUND:-}
- CHAT_MEDIA_ARCHIVE_MAX_BYTES=${CHAT_MEDIA_ARCHIVE_MAX_BYTES:-}
- CHAT_MEDIA_ARCHIVE_TTL_DAYS=${CHAT_MEDIA_ARCHIVE_TTL_DAYS:-}
- CHAT_MEDIA_ORPHAN_SWEEP_INTERVAL_MS=${CHAT_MEDIA_ORPHAN_SWEEP_INTERVAL_MS:-}
- CHAT_MEDIA_ORPHAN_GRACE_MS=${CHAT_MEDIA_ORPHAN_GRACE_MS:-}
- SEND_PACING_ENABLED=${SEND_PACING_ENABLED:-}
- SEND_PACING_WARMUP_SCHEDULE=${SEND_PACING_WARMUP_SCHEDULE:-}
- SEND_PACING_COLD_DAILY_CAP=${SEND_PACING_COLD_DAILY_CAP:-}
- SEND_PACING_BREAKER_THRESHOLD=${SEND_PACING_BREAKER_THRESHOLD:-}
- SEND_PACING_BREAKER_COOLDOWN_MS=${SEND_PACING_BREAKER_COOLDOWN_MS:-}
- MESSAGE_LIST_INLINE_MEDIA_BUDGET_BYTES=${MESSAGE_LIST_INLINE_MEDIA_BUDGET_BYTES:-}
- MEDIA_DOWNLOAD_ENABLED=${MEDIA_DOWNLOAD_ENABLED:-}
- MEDIA_DOWNLOAD_MAX_BYTES=${MEDIA_DOWNLOAD_MAX_BYTES:-}
- MEDIA_DOWNLOAD_TIMEOUT_MS=${MEDIA_DOWNLOAD_TIMEOUT_MS:-}
- INBOUND_MEDIA_CONCURRENCY=${INBOUND_MEDIA_CONCURRENCY:-}
- MEDIA_CONVERSION_ENABLED=${MEDIA_CONVERSION_ENABLED:-}
- FFMPEG_PATH=${FFMPEG_PATH:-}
- MEDIA_CONVERSION_TIMEOUT_MS=${MEDIA_CONVERSION_TIMEOUT_MS:-}
- MEDIA_CONVERSION_MAX_OUTPUT_BYTES=${MEDIA_CONVERSION_MAX_OUTPUT_BYTES:-}
- MEDIA_CONVERSION_CONCURRENCY=${MEDIA_CONVERSION_CONCURRENCY:-}
- NODE_ID=${NODE_ID:-}
- NODE_URL=${NODE_URL:-}
- SESSION_LEASE_TTL_MS=${SESSION_LEASE_TTL_MS:-}
- SESSION_LEASE_HEARTBEAT_MS=${SESSION_LEASE_HEARTBEAT_MS:-}
- SESSION_TAKEOVER_SWEEP_MS=${SESSION_TAKEOVER_SWEEP_MS:-}
- SESSION_PROXY_TIMEOUT_MS=${SESSION_PROXY_TIMEOUT_MS:-}
# Security / boot knobs the app reads. Like the blocks above, this list is the only path into
# the container; compose-parity.spec.ts derives the required set from .env.example.
- API_MASTER_KEY=${API_MASTER_KEY:-}
- ALLOW_DEV_API_KEY=${ALLOW_DEV_API_KEY:-}
- API_KEY_PEPPER=${API_KEY_PEPPER:-}
- BOOTSTRAP_KEY_FILE=${BOOTSTRAP_KEY_FILE:-}
- ENABLE_SWAGGER=${ENABLE_SWAGGER:-}
- VALIDATION_ERROR_DETAIL=${VALIDATION_ERROR_DETAIL:-}
- MCP_READONLY=${MCP_READONLY:-}
- MCP_RATE_LIMIT_MAX=${MCP_RATE_LIMIT_MAX:-}
- MCP_RATE_LIMIT_WINDOW_MS=${MCP_RATE_LIMIT_WINDOW_MS:-}
- MCP_IP_RATE_LIMIT_MAX=${MCP_IP_RATE_LIMIT_MAX:-}
- MCP_IP_RATE_LIMIT_WINDOW_MS=${MCP_IP_RATE_LIMIT_WINDOW_MS:-}
- METRICS_TOKEN=${METRICS_TOKEN:-}
- CORS_ORIGINS=${CORS_ORIGINS:-}
- SSRF_ALLOWED_HOSTS=${SSRF_ALLOWED_HOSTS:-}
- SSRF_DNS_TIMEOUT_MS=${SSRF_DNS_TIMEOUT_MS:-}
- WEBHOOK_SSRF_REDIRECTS=${WEBHOOK_SSRF_REDIRECTS:-}
# Postgres / S3 details (selection keys are forwarded above; blank lets a real host value pin).
- DATABASE_HOST=${DATABASE_HOST:-}
- DATABASE_PORT=${DATABASE_PORT:-}
- DATABASE_USERNAME=${DATABASE_USERNAME:-}
- DATABASE_PASSWORD=${DATABASE_PASSWORD:-}
- POSTGRES_SCHEMA=${POSTGRES_SCHEMA:-}
- S3_ENDPOINT=${S3_ENDPOINT:-}
- S3_BUCKET=${S3_BUCKET:-}
- S3_REGION=${S3_REGION:-}
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID:-}
- S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY:-}
- REDIS_ENABLED=${REDIS_ENABLED:-}
- REDIS_HOST=${REDIS_HOST:-}
- REDIS_PORT=${REDIS_PORT:-}
- REDIS_USERNAME=${REDIS_USERNAME:-}
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
- REDIS_CONNECT_TIMEOUT_MS=${REDIS_CONNECT_TIMEOUT_MS:-}
# Fetch statuses on ready (off unless the exact string 'true', matching docker-compose.yml).
- STATUS_SEED_ON_READY=${STATUS_SEED_ON_READY:-false}
- AUTOMATION_MAX_PER_SESSION=${AUTOMATION_MAX_PER_SESSION:-}
# HTTP server tuning.
- REQUEST_TIMEOUT_MS=${REQUEST_TIMEOUT_MS:-}
- HEADERS_TIMEOUT_MS=${HEADERS_TIMEOUT_MS:-}
- KEEPALIVE_TIMEOUT_MS=${KEEPALIVE_TIMEOUT_MS:-}
- INFLIGHT_BODY_BUDGET_BYTES=${INFLIGHT_BODY_BUDGET_BYTES:-}
# Webhook delivery tuning and retention.
- WEBHOOK_SHUTDOWN_DRAIN_MS=${WEBHOOK_SHUTDOWN_DRAIN_MS:-}
- WEBHOOK_MEDIA_INLINE_MAX_BYTES=${WEBHOOK_MEDIA_INLINE_MAX_BYTES:-}
- WEBHOOK_MAX_PAYLOAD_BYTES=${WEBHOOK_MAX_PAYLOAD_BYTES:-}
- WEBHOOK_MAX_PER_SESSION=${WEBHOOK_MAX_PER_SESSION:-}
- WEBHOOK_FAILURE_RETENTION_DAYS=${WEBHOOK_FAILURE_RETENTION_DAYS:-}
- WEBHOOK_WORKER_CONCURRENCY=${WEBHOOK_WORKER_CONCURRENCY:-}
# Integration Fabric ingress: fairness, retries, retention, reconciler, workers.
- INGRESS_INSTANCE_LIMIT=${INGRESS_INSTANCE_LIMIT:-}
- INGRESS_INSTANCE_TTL=${INGRESS_INSTANCE_TTL:-}
- INGRESS_IP_LIMIT=${INGRESS_IP_LIMIT:-}
- INGRESS_MAX_ATTEMPTS=${INGRESS_MAX_ATTEMPTS:-}
- INGRESS_RETRY_DELAY_MS=${INGRESS_RETRY_DELAY_MS:-}
- INGRESS_DEDUP_RETENTION_DAYS=${INGRESS_DEDUP_RETENTION_DAYS:-}
- INGRESS_RETENTION_DAYS=${INGRESS_RETENTION_DAYS:-}
- INGRESS_TIMESTAMP_TOLERANCE_SEC=${INGRESS_TIMESTAMP_TOLERANCE_SEC:-}
- INGRESS_RECONCILE_INTERVAL_MS=${INGRESS_RECONCILE_INTERVAL_MS:-}
- INGRESS_RECONCILE_GRACE_MS=${INGRESS_RECONCILE_GRACE_MS:-}
- INGRESS_RECONCILE_BATCH_SIZE=${INGRESS_RECONCILE_BATCH_SIZE:-}
- INGRESS_RECONCILE_MAX_ATTEMPTS=${INGRESS_RECONCILE_MAX_ATTEMPTS:-}
- WEBHOOK_RECONCILE_INTERVAL_MS=${WEBHOOK_RECONCILE_INTERVAL_MS:-}
- WEBHOOK_RECONCILE_GRACE_MS=${WEBHOOK_RECONCILE_GRACE_MS:-}
- WEBHOOK_RECONCILE_BATCH_SIZE=${WEBHOOK_RECONCILE_BATCH_SIZE:-}
- WEBHOOK_RECONCILE_MAX_ATTEMPTS=${WEBHOOK_RECONCILE_MAX_ATTEMPTS:-}
- WEBHOOK_OUTBOX_RETENTION_DAYS=${WEBHOOK_OUTBOX_RETENTION_DAYS:-}
- INGRESS_WORKER_CONCURRENCY=${INGRESS_WORKER_CONCURRENCY:-}
# WebSocket gateway limits.
- WS_RATE_LIMIT_FRAME_PER_SECOND=${WS_RATE_LIMIT_FRAME_PER_SECOND:-}
- WS_RATE_LIMIT_FRAME_BURST=${WS_RATE_LIMIT_FRAME_BURST:-}
- WS_RATE_LIMIT_HANDSHAKE_MAX=${WS_RATE_LIMIT_HANDSHAKE_MAX:-}
- WS_RATE_LIMIT_HANDSHAKE_WINDOW_MS=${WS_RATE_LIMIT_HANDSHAKE_WINDOW_MS:-}
- WS_MAX_SOCKETS_PER_KEY=${WS_MAX_SOCKETS_PER_KEY:-}
# Database connection tuning.
- DATABASE_POOL_SIZE=${DATABASE_POOL_SIZE:-}
- DATABASE_STATEMENT_TIMEOUT_MS=${DATABASE_STATEMENT_TIMEOUT_MS:-}
- DATABASE_IDLE_TIMEOUT_MS=${DATABASE_IDLE_TIMEOUT_MS:-}
- DATABASE_CONNECTION_TIMEOUT_MS=${DATABASE_CONNECTION_TIMEOUT_MS:-}
- MAIN_DATABASE_NAME=${MAIN_DATABASE_NAME:-}
# Engine / session tuning.
- MAX_CONCURRENT_SESSIONS=${MAX_CONCURRENT_SESSIONS:-}
- BAILEYS_AUTH_DIR=${BAILEYS_AUTH_DIR:-}
- BAILEYS_BROWSER_NAME=${BAILEYS_BROWSER_NAME:-}
- BAILEYS_LOG_LEVEL=${BAILEYS_LOG_LEVEL:-}
- BAILEYS_MESSAGE_STORE_LIMIT=${BAILEYS_MESSAGE_STORE_LIMIT:-}
- BAILEYS_SESSION_STORE_MAX_ENTRIES=${BAILEYS_SESSION_STORE_MAX_ENTRIES:-}
- WWEBJS_ONBOARDING_CONTINUE_LABELS=${WWEBJS_ONBOARDING_CONTINUE_LABELS:-}
# Default matches the image's ENV (Dockerfile); a blank forward would shadow it and make
# puppeteer fall back to a bundled Chromium the image does not ship. compose-parity.spec.ts
# asserts the default stays in sync with the Dockerfile value.
- PUPPETEER_EXECUTABLE_PATH=${PUPPETEER_EXECUTABLE_PATH:-/usr/local/bin/puppeteer-chrome}
- SHUTDOWN_DELAY_MS=${SHUTDOWN_DELAY_MS:-}
- SIMULATE_TYPING_MAX_MS=${SIMULATE_TYPING_MAX_MS:-}
- LID_MAPPING_CACHE_MAX=${LID_MAPPING_CACHE_MAX:-}
# Media / storage budgets and sweeps.
- EXPORT_INLINE_MEDIA_BUDGET_BYTES=${EXPORT_INLINE_MEDIA_BUDGET_BYTES:-}
- CHAT_HISTORY_MEDIA_BUDGET_BYTES=${CHAT_HISTORY_MEDIA_BUDGET_BYTES:-}
- STATUS_MEDIA_MAX_BYTES=${STATUS_MEDIA_MAX_BYTES:-}
- STATUS_ORPHAN_SWEEP_INTERVAL_MS=${STATUS_ORPHAN_SWEEP_INTERVAL_MS:-}
- STATUS_ORPHAN_GRACE_MS=${STATUS_ORPHAN_GRACE_MS:-}
- STORAGE_LIST_MAX_FILES=${STORAGE_LIST_MAX_FILES:-}
- STORAGE_IMPORT_MAX_BYTES=${STORAGE_IMPORT_MAX_BYTES:-}
- STORAGE_IMPORT_MAX_ENTRIES=${STORAGE_IMPORT_MAX_ENTRIES:-}
- STORAGE_EXPORT_TTL_MS=${STORAGE_EXPORT_TTL_MS:-}
- STORAGE_EXPORT_SWEEP_MAX_AGE_MS=${STORAGE_EXPORT_SWEEP_MAX_AGE_MS:-}
- S3_REPROBE_INTERVAL_MS=${S3_REPROBE_INTERVAL_MS:-}
- MESSAGE_REAPER_INTERVAL_MS=${MESSAGE_REAPER_INTERVAL_MS:-}
- MESSAGE_REAPER_GRACE_MS=${MESSAGE_REAPER_GRACE_MS:-}
- MESSAGE_REAPER_BATCH_SIZE=${MESSAGE_REAPER_BATCH_SIZE:-}
# Plugin sandbox limits and the install trust knobs.
- PLUGIN_DOWNLOAD_MAX_BYTES=${PLUGIN_DOWNLOAD_MAX_BYTES:-}
- PLUGIN_INSTALL_REQUIRE_PIN=${PLUGIN_INSTALL_REQUIRE_PIN:-}
- PLUGIN_CATALOG_URL=${PLUGIN_CATALOG_URL:-}
- PLUGIN_CAP_TIMEOUT_MS=${PLUGIN_CAP_TIMEOUT_MS:-}
- PLUGIN_STORAGE_MAX_BYTES=${PLUGIN_STORAGE_MAX_BYTES:-}
# Misc application tuning.
- AUDIT_RETENTION_DAYS=${AUDIT_RETENTION_DAYS:-}
- BULK_MAX_CONCURRENT_BATCHES=${BULK_MAX_CONCURRENT_BATCHES:-}
- TEMPLATE_RENDER_MAX_CHARS=${TEMPLATE_RENDER_MAX_CHARS:-}
- STATS_CACHE_TTL_MS=${STATS_CACHE_TTL_MS:-}
- SEARCH_PROVIDER=${SEARCH_PROVIDER:-}
- SEARCH_LIMIT_MAX=${SEARCH_LIMIT_MAX:-}
- LOG_FORMAT=${LOG_FORMAT:-}
- BASE_URL=${BASE_URL:-}
- DASHBOARD_URL=${DASHBOARD_URL:-}
volumes:
- ./data:/app/data
restart: unless-stopped
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:2785/api/health/ready']
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
# The dashboard SPA is bundled into the image and served by NestJS on the same port:
# open http://localhost:2785 — there is no separate dashboard container.
networks:
default:
name: openwa-network