-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Expand file tree
/
Copy pathdocker-compose.dev.yml
More file actions
158 lines (155 loc) · 8.82 KB
/
Copy pathdocker-compose.dev.yml
File metadata and controls
158 lines (155 loc) · 8.82 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
# 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 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:-}
- 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:-}
- 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:-}
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