WWaSphere Docs
Getting Started

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

ResourceMinimumRecommended
CPU1 vCPU2 vCPU
RAM1 GB2 GB
Disk10 GB20 GB SSD
Docker Engine24.0+latest stable
Docker Composev2.20+latest stable

Verify your Docker installation:

docker compose version
# Docker Compose version v2.27.0

If 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:

ToolVersion
Node.js20 or newer
pnpm9 or newer
PostgreSQL14 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

On this page