OpenWA Data Volume — What's in There and How to Back It Up
Where the Data Lives
Docker named volume managed in docker-compose.yml:
volumes:
openwa-data:
driver: local
With docker-compose.dev.yml, the volume is mounted at /app/data inside the container. On the host, Docker manages the actual filesystem path.
To find the host path:
docker volume inspect openwa_data --format '{{.Mountpoint}}'
The Sessions Directory
~/projects/OpenWA/data/sessions/
This is the most important directory in the entire stack.
Each authenticated WhatsApp session has a subdirectory here. Inside it:
auth.json — the WhatsApp Web authentication session. Contains the phone number, signed device identity, session tokens. This is what keeps the session alive without rescanning the QR.message-capability.json — features the connected WhatsApp version supportssender-jid-map.json — maps phone numbers to WhatsApp JIDsWithout auth.json, the session is dead. You must scan the QR code again. For personal use with one or two sessions this is an inconvenience. For a business running dozens of customer sessions, losing sessions means losing conversations.
The SQLite Database
~/projects/OpenWA/data/openwa.sqlite
Everything except session auth state lives here:
The audit log is the first thing to check when debugging. It records every API request: method, path, API key ID (not the key itself), source IP, response status, and timestamp.
DATABASE_SYNCHRONIZE=false in production means the schema is managed by TypeORM migrations, not auto-sync. Run migrations after updates:
docker compose exec openwa-api npx typeorm migration:run
If you skip migrations after a version update, the app boots but some columns or tables are missing, causing silent failures or 500 errors on specific endpoints.
The API Key File
The API key is stored in the Docker named volume, not on the host filesystem. To retrieve it:
Step 1 — Find the container name
docker ps --format '{{.Names}}'
Step 2 — Read the key
sudo docker exec cat /app/data/.api-key
The key is written once at first boot and stored as a plain text file at /app/data/.api-key inside the container. If you set API_MASTER_KEY in .env before first boot, that value is used. Otherwise a random one is generated.
Always store this key in a password manager, not just in the volume. You need it to call the API, configure n8n credentials, and access swagger docs.
Media Directory
~/projects/OpenWA/data/media/
Inbound media (photos, videos, documents sent by contacts) and outbound media sent via URL are cached here. The naming is hash-based, not original filename.
Storage behaviour:
/media/{hash}This directory can grow large with active usage. Back it up along with everything else.
Backup Strategy
Full Backup Script:
#!/bin/bash
BACKUP_DIR="$HOME/backups/openwa"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
docker compose -f docker-compose.dev.yml exec -T openwa-api tar czf /tmp/openwa-backup.tar.gz \
/app/data/openwa.sqlite \
/app/data/sessions \
/app/data/media \
/app/data/.api-key \
/app/data/plugins 2>/dev/null
docker compose -f docker-compose.dev.yml cp openwa-api:/tmp/openwa-backup.tar.gz "$BACKUP_DIR/openwa-${DATE}.tar.gz"
echo "Backup saved: $BACKUP_DIR/openwa-${DATE}.tar.gz"
Key inclusions: openwa.sqlite (API keys, sessions metadata, audit logs), sessions/ (authentication state — irreplaceable), media/ (inbound/outbound files), .api-key (master key), plugins/ (if used).
Exclude from backup: .cache/, puppeteer/, .local/ — these are regenerated.
Retention
Rotate old backups:
find ~/backups/openwa -name "openwa-*.tar.gz" -mtime +7 -delete
Keep 7 days of daily backups. For anything mission-critical, also push weekly backups to cloud storage.
Restore
docker compose -f docker-compose.dev.yml stop
docker compose -f docker-compose.dev.yml run --rm -v $(pwd)/data:/restore openwa-api \
sh -c "cd /app/data && tar xzf /restore/openwa-backup.tar.gz --strip-components=3"
docker compose -f docker-compose.dev.yml up -d
Replace openwa-backup.tar.gz with the actual backup file. The --strip-components=3 removes the app/data prefix from the archive paths so files land in the right place.
What Happens If You Lose the Sessions Directory
If sessions/ is gone but openwa.sqlite and .api-key are intact:
If openwa.sqlite is gone but sessions/ is intact:
If everything is gone: full re-setup from scratch.
Series: ← OpenWA Docker Setup | Next: Connecting n8n to OpenWA →
Related Posts
Built something similar or want to talk through the architecture? Get in touch.