Configuration
Complete environment variable reference for every WaSphere service.
Configuration
All WaSphere configuration is driven by environment variables in the .env file at the project root. Copy .env.example to .env and edit it before starting the stack.
cp .env.example .env
Variables are grouped by the service that consumes them. Some variables are shared between services — when a value must match across services (like WA_TOKEN or INTERNAL_WEBHOOK_SECRET), that is noted in the description.
Never commit your .env file to source control. The .gitignore in the repository excludes it, but double-check before every git add.
There is no admin-by-environment variable. The first account you register in the Dashboard UI becomes the admin, after which registration locks automatically. See Quick Start.
Dashboard API
The Dashboard API (NestJS, port 3000) is the main backend. It handles authentication, session management, message proxying, webhooks, and the REST API your applications call.
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
DATABASE_URL | string | — | Yes | PostgreSQL connection string in the format postgresql://USER:PASSWORD@HOST:PORT/DATABASE. Inside Docker, use postgresql://wasphere:changeme@postgres:5432/wasphere. |
JWT_SECRET | string | — | Yes | Secret key used to sign JWT access tokens. Generate with openssl rand -hex 32. Rotating this invalidates all existing dashboard sessions. |
ENCRYPTION_KEY | string | — | Yes | 32-byte key (exactly 64 hex characters) used to encrypt secrets at rest — most importantly the stored WA Server token. Generate with openssl rand -hex 32. |
INTERNAL_WEBHOOK_SECRET | string | — | Yes | Shared secret used to authenticate internal audit/event callbacks from the WA Server to the Dashboard API. Must match the value in the WA Server section. Generate with openssl rand -hex 32. |
CORS_ORIGIN | string | — | Yes | Allowed browser origin for the Dashboard UI — e.g. http://localhost:3004 or https://app.your-domain.com. |
DASHBOARD_PORT | number | 3000 | No | Port the Dashboard API listens on. Only change if running without Docker. |
WA Server
The WA Server (NestJS + Baileys, port 3001) manages WhatsApp connections. It only accepts requests carrying the shared WA_TOKEN, which the Dashboard API injects automatically.
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
WA_TOKEN | string | — | Yes | Shared secret the Dashboard API sends as the X-Api-Token header to authenticate with the WA Server. Requests without a valid token are rejected with 401. Generate with openssl rand -hex 32. |
PORT | number | 3001 | No | Port the WA Server listens on. Only change if running without Docker. |
WEBHOOK_SIGNING_SECRET | string | — | Yes | Global HMAC-SHA256 secret used to sign every outgoing webhook payload. Your endpoint verifies deliveries against this value. Generate with openssl rand -hex 32. |
INTERNAL_WEBHOOK_SECRET | string | — | Yes | Shared secret used to authenticate internal audit callbacks to the Dashboard API. Must match the value in the Dashboard API section. |
CORS_ORIGIN | string | — | No | Allowed origin for direct browser access (e.g. QR streaming). Typically the Dashboard UI URL. |
AUDIT_DASHBOARD_URL | string | http://dashboard-api:3000 | No | Internal URL the WA Server uses to post audit events back to the Dashboard API. In Docker this is the service name. |
SESSIONS_DIR | string | /app/sessions | No | Directory where Baileys stores session credentials. Map this to a Docker volume to persist sessions across container restarts. |
MAX_SESSIONS | number | — | No | Maximum number of concurrent WhatsApp sessions the WA Server will run. |
MAX_RECONNECT_ATTEMPTS | number | 5 | No | Number of automatic reconnect attempts before a session is marked disconnected. |
RATE_LIMIT_MAX | number | — | No | Maximum requests allowed per rate-limit window. |
RATE_LIMIT_WINDOW_MS | number | — | No | Rate-limit window length in milliseconds. |
Dashboard UI
The Dashboard UI (Next.js, port 3004) is a browser application served by a Next.js server. Both variables are read server-side.
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
DASHBOARD_API_URL | string | — | Yes | URL of the Dashboard API the UI calls. In Docker this is http://dashboard-api:3000; behind a proxy, your public API URL. |
WA_SERVER_INTERNAL_URL | string | http://wa-server:3001 | No | Internal Docker URL the Next.js server-side code uses to reach the WA Server directly (for QR code streaming). |
PostgreSQL (Docker Service)
These variables configure the PostgreSQL container in the Docker Compose stack.
| Variable | Type | Default | Required | Description |
|---|---|---|---|---|
POSTGRES_USER | string | wasphere | No | PostgreSQL superuser name. Must match the username in DATABASE_URL. |
POSTGRES_PASSWORD | string | changeme | Yes | PostgreSQL superuser password. Use a strong password in production. Must match the password in DATABASE_URL. |
POSTGRES_DB | string | wasphere | No | Database name. Must match the database in DATABASE_URL. |
The default POSTGRES_PASSWORD=changeme is intentionally insecure. Replace it before going to production. After changing it, update DATABASE_URL to match and recreate the postgres container: docker compose up -d --force-recreate postgres.
Example .env for Production
This matches the variables consumed by docker-compose.yml. Generate every secret separately with openssl rand -hex 32 (use -hex 16 for the database password).
# ── Database ─────────────────────────────────────────────
POSTGRES_USER=wasphere
POSTGRES_PASSWORD=Sup3rS3cur3DB!
POSTGRES_DB=wasphere
# ── Secrets (generate each separately) ───────────────────
JWT_SECRET=a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
ENCRYPTION_KEY=f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3b2a1f6e5
WA_TOKEN=9a8b7c6d5e4f9a8b7c6d5e4f9a8b7c6d5e4f9a8b7c6d5e4f9a8b7c6d5e4f9a8b
WEBHOOK_SIGNING_SECRET=0f1e2d3c4b5a0f1e2d3c4b5a0f1e2d3c4b5a0f1e2d3c4b5a0f1e2d3c4b5a0f1e
INTERNAL_WEBHOOK_SECRET=5a4b3c2d1e0f5a4b3c2d1e0f5a4b3c2d1e0f5a4b3c2d1e0f5a4b3c2d1e0f5a4b
# ── URL (for CORS) ───────────────────────────────────────
DASHBOARD_UI_URL=https://app.example.com
DASHBOARD_UI_URL in the Docker .env is wired into the services as the appropriate CORS_ORIGIN / DASHBOARD_API_URL values by docker-compose.yml. The ENCRYPTION_KEY must be exactly 64 hex characters — it encrypts your stored WA Server token, and changing it makes existing encrypted values unreadable.
Rotating Secrets
JWT_SECRET — Rotating this immediately invalidates all active dashboard sessions. Everyone signed in will be logged out. To rotate:
- Generate a new value:
openssl rand -hex 32 - Update
.env - Restart the Dashboard API:
docker compose restart dashboard-api
WA_TOKEN — Must be updated in .env and both the Dashboard API and WA Server containers restarted simultaneously to avoid a broken state:
# Update .env, then:
docker compose restart dashboard-api wa-server
WEBHOOK_SIGNING_SECRET — This is the single global secret used to sign every webhook payload. Rotating it means every receiver must be updated with the new secret at the same time, or signature verification will start failing. Plan the cutover with your integrations.
Installation
Install WaSphere with the 4-service Docker Compose stack — requirements, the real .env, the docker compose up flow, and update/backup/teardown commands.
Inbox
The realtime two-pane WhatsApp Inbox in the WaSphere dashboard — live SSE updates, media, polls, reactions, tags, notes, search, and multi-session.