Installation
Install WaSphere with the 4-service Docker Compose stack — requirements, the real .env, the docker compose up flow, and update/backup/teardown commands.
Installation
WaSphere ships as a single Docker Compose stack with four services: PostgreSQL, the WA Server, the Dashboard API, and the Dashboard UI. There is one docker-compose.yml and one .env at the repository root. Database migrations run automatically on startup — there is no manual migration step.
This page covers the requirements, the real environment variables, the full docker compose up -d flow, and the commands for updating, backing up, and tearing down the stack.
Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2 vCPU |
| RAM | 1 GB | 2 GB |
| Disk | 10 GB | 20 GB SSD |
| Docker Engine | 24.0+ | latest stable |
| Docker Compose | v2.20+ | latest stable |
Verify your Docker installation:
docker compose version
# Docker Compose version v2.27.0If Docker is not installed, follow the official instructions at docs.docker.com.
If you prefer to run the Node processes directly (for development or a non-Docker host), you need:
| Tool | Version |
|---|---|
| Node.js | 20 or newer |
| pnpm | 9 or newer |
| PostgreSQL | 14 or newer |
You still use Docker for the database in dev — see Local Development below.
RAM grows with the number of active WhatsApp sessions. Each session holds a WebSocket connection and a local message cache — budget roughly 100–150 MB per session above the base footprint.
1. Clone the repository
git clone https://github.com/wasphere/wasphere.git
cd wasphere
2. Create your .env
cp .env.example .env
There is a single .env file at the repository root. Open it and set the values below. Generate every secret with openssl rand -hex 32 — never reuse one value for two secrets.
# ── PostgreSQL ───────────────────────────────────────────
POSTGRES_USER=wasphere
POSTGRES_PASSWORD=$(openssl rand -hex 32) # strong, unique
POSTGRES_DB=wasphere
# ── Secrets (generate each separately) ───────────────────
JWT_SECRET=$(openssl rand -hex 32) # signs dashboard auth tokens
ENCRYPTION_KEY=$(openssl rand -hex 32) # encrypts stored credentials at rest
WA_TOKEN=$(openssl rand -hex 32) # Dashboard API → WA Server auth
WEBHOOK_SIGNING_SECRET=$(openssl rand -hex 32) # default HMAC-SHA256 webhook signing key
INTERNAL_WEBHOOK_SECRET=$(openssl rand -hex 32) # WA Server → Dashboard API internal events
# ── Dashboard UI ─────────────────────────────────────────
DASHBOARD_UI_URL=http://localhost:3004 # public URL of the dashboard
WA_TOKEN is the shared secret the Dashboard API sends to the WA Server to authenticate internal calls. Generate it independently from JWT_SECRET and ENCRYPTION_KEY — reusing a value across secrets weakens every guarantee that depends on it.
The .env file holds every secret for your deployment. It is gitignored by default — verify it never gets committed before any git add.
A convenient way to generate all secrets at once:
for k in JWT_SECRET ENCRYPTION_KEY WA_TOKEN WEBHOOK_SIGNING_SECRET INTERNAL_WEBHOOK_SECRET POSTGRES_PASSWORD; do
echo "$k=$(openssl rand -hex 32)"
done
Paste the output into .env, then set POSTGRES_USER, POSTGRES_DB, and DASHBOARD_UI_URL.
3. Start the stack
docker compose up -d
The first run pulls images and builds the stack (1–3 minutes). Migrations run automatically when the Dashboard API container starts — you do not run Prisma by hand.
Follow the logs while it comes up:
docker compose logs -f
Press Ctrl+C to stop following logs; the containers keep running.
Check that all four services are up:
docker compose ps
4. Register the first admin account
Open http://localhost:3004 in your browser. On first launch the dashboard shows a registration screen — the first account you create becomes the admin. Sign in, then head to the Quick Start to connect a WhatsApp session and send your first message.
The four services
The root docker-compose.yml defines exactly four services. There is no bundled reverse proxy and no Redis — see Reverse proxy & TLS for how to front the stack in production.
postgres — PostgreSQL
Stores all persistent data: accounts, session metadata, message history, API keys, webhook configuration, and the audit log.
- Port: 5432 (Docker network)
- Configured by
POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DB - Data persists in a Docker-managed volume
wa-server — WhatsApp Server
NestJS application that manages WhatsApp connections via Baileys. Each session is a separate connection inside this process. Authenticates inbound requests with the WA_TOKEN shared secret.
- Port: 3001
- Session credentials persist in a mounted volume
Do not expose port 3001 to the internet. The WA Server trusts the WA_TOKEN shared secret — all external traffic must go through the Dashboard API.
dashboard-api — Dashboard API
NestJS REST API that your applications and the Dashboard UI talk to. Handles authentication (JWT + scoped API keys), workspace and session orchestration, message dispatch, and signed webhook fan-out. Runs database migrations automatically on startup.
- Port: 3000
dashboard-ui — Dashboard UI
Next.js 15 application providing the web management interface. This is the URL you open in the browser.
- Port: 3004
- Public URL configured by
DASHBOARD_UI_URL
Reverse proxy & TLS
WaSphere does not bundle a reverse proxy or terminate TLS. In production you front the stack with your own proxy — nginx, Caddy, or Traefik — terminating TLS there and forwarding to:
- the Dashboard UI on port 3004
- the Dashboard API on port 3000
A minimal Caddy example:
app.your-domain.com {
reverse_proxy localhost:3004
}
api.your-domain.com {
reverse_proxy localhost:3000
}
Point DASHBOARD_UI_URL at the public HTTPS URL your proxy serves.
For Dokploy deployments the repository includes a docker-compose.prod.yml tuned for that platform. Use it in place of the default compose file: docker compose -f docker-compose.prod.yml up -d.
Updating WaSphere
# Pull the latest images and recreate changed containers
docker compose pull && docker compose up -d
Migrations run automatically on startup, so there is no separate migrate step after an update.
Always read the release notes before updating. Breaking changes to the .env schema or database are documented in the repository CHANGELOG.md.
Backing up
All durable state lives in PostgreSQL and the WhatsApp session volume. Back up the database with pg_dump:
docker compose exec -T postgres \
pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > wasphere-backup-$(date +%F).sql
Restore into a fresh database:
cat wasphere-backup-2026-06-01.sql | \
docker compose exec -T postgres psql -U "$POSTGRES_USER" "$POSTGRES_DB"
Also back up the session volume so connected WhatsApp numbers survive a rebuild. See Backup & Restore for the full procedure.
Stopping & tearing down
# Stop and remove the containers (data volumes are kept)
docker compose down
# Also remove all data volumes — DESTRUCTIVE: deletes the database and sessions
docker compose down -v
Local development without Docker
For active development, run only PostgreSQL in Docker and the apps directly with pnpm:
# Start PostgreSQL only
docker compose -f docker-compose.dev.yml up -d
# Install workspace dependencies and run all apps with hot reload
pnpm install
pnpm dev
This requires Node.js 20+, pnpm 9+, and the .env configured as above (point DASHBOARD_UI_URL at http://localhost:3004).
Running the apps directly with pnpm dev is for development only. Use the Docker Compose stack for anything publicly accessible.
Next steps
- Quick Start — connect a session and send your first message
- Configuration — full environment variable reference
- Backup & Restore — protect your data