Backup & Restore Guide

Configure scheduled backups and restore Weavestream on a fresh Docker host.

This guide explains how to protect a Weavestream deployment and restore it after a host failure.

Weavestream's persistent data lives in three places:

Location Contents Required for restore
$DATA_DIR/postgres Live PostgreSQL data directory Yes, or use a logical dump from $DATA_DIR/backup
$DATA_DIR/files Uploads, attachments, logos, thumbnails, export PDFs Yes
$DATA_DIR/backup Scheduled pg_dump --format=custom files and manifests Yes, if using in-app backups
$DATA_DIR/redis Sessions, queues, cache No, normally replayable

1. Confirm Your Data Directory

By default, compose.yml stores data in ./data next to the compose file. If you set DATA_DIR in .env, use that path instead.

cd /opt/weavestream
grep '^DATA_DIR=' .env || echo "DATA_DIR=./data"

For the rest of this guide:

COMPOSE_DIR=/opt/weavestream
DATA_DIR=$COMPOSE_DIR/data

If your .env uses a custom DATA_DIR, replace the value above.

2. Configure Scheduled Database Exports

  1. Sign in as a SUPER_ADMIN or a user with BACKUP_MANAGE.
  2. Go to Admin → Backups.
  3. Click New schedule.
  4. Choose a preset or enter a five-field cron expression.
  5. Set the timezone, for example Etc/UTC or America/New_York.
  6. Set retention:
    • Keep last keeps the N most-recent successful runs regardless of date bucket. Default: 3.
    • Daily keeps one run per distinct day.
    • Weekly keeps one run per ISO week.
    • Monthly keeps one run per calendar month.
  7. Optional: add notification email addresses.
  8. Save the schedule.

Click Run now once and wait for a successful run. A successful run creates:

$DATA_DIR/backup/weavestream-postgres-<timestamp>.dump
$DATA_DIR/backup/weavestream-postgres-<timestamp>.manifest.json

The manifest includes the dump filename, SHA-256 checksum, Weavestream version, Prisma migration hash, database hostname, and active password-encryption key id.

3. Back Up Files and Dumps Off-Host

The in-app backup only exports PostgreSQL. You must also copy uploaded files.

Minimum off-host backup set:

$DATA_DIR/backup/
$DATA_DIR/files/
.env

Recommended nightly sync:

#!/bin/bash
set -euo pipefail

COMPOSE_DIR=/opt/weavestream
DATA_DIR="$COMPOSE_DIR/data"
DEST=/mnt/backups/weavestream
DATE=$(date +%F)

mkdir -p "$DEST/postgres-dumps" "$DEST/files-$DATE" "$DEST/secrets"

# Database dumps produced by Admin -> Backups.
rsync -a "$DATA_DIR/backup/" "$DEST/postgres-dumps/"

# Uploaded files and generated file artifacts.
rsync -a "$DATA_DIR/files/" "$DEST/files-$DATE/"

# Secrets required to decrypt vaulted data after restore.
cp "$COMPOSE_DIR/.env" "$DEST/secrets/.env"

# Example file snapshot rotation. The database dumps are pruned by
# Weavestream retention, so this only rotates file snapshots.
find "$DEST" -maxdepth 1 -type d -name 'files-*' -mtime +30 -exec rm -rf {} +

For production, run the script from cron or a systemd timer and replicate DEST to a different machine, NAS, or encrypted object storage.

Example with restic:

restic -r s3:https://s3.amazonaws.com/example-weavestream-backups backup \
  "$DATA_DIR/backup" \
  "$DATA_DIR/files" \
  "$COMPOSE_DIR/.env"

4. Optional Manual Database Dump

You can also create a one-off logical dump from the Docker host:

cd /opt/weavestream
docker compose exec -T postgres \
  pg_dump -U "$POSTGRES_USER" --format=custom --no-owner --no-acl "$POSTGRES_DB" \
  > "weavestream-postgres-manual-$(date -u +%Y-%m-%dT%H-%M-%SZ).dump"

This is useful before upgrades or maintenance. It does not replace $DATA_DIR/files or .env.

5. Restore on a New Docker Host

Use this when the original Docker host is gone and you have:

  • A Weavestream .dump file from $DATA_DIR/backup.
  • A matching $DATA_DIR/files backup.
  • The original .env.

Prepare the New Host

mkdir -p /opt/weavestream
cd /opt/weavestream

curl -O https://raw.githubusercontent.com/Weavestream/Weavestream/main/compose.yml
cp /backup/weavestream/secrets/.env .env

mkdir -p data
rsync -a /backup/weavestream/files-2026-05-01/ data/files/

If your original .env set DATA_DIR, recreate that directory and restore files there instead.

Start PostgreSQL Only

docker compose up -d postgres
docker compose ps postgres

Wait until the container is healthy.

Restore the Database Dump

Replace the dump path with the file you want to restore:

docker compose exec -T postgres sh -lc \
  'pg_restore --clean --if-exists --no-owner --no-acl \
     -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
  < /backup/weavestream/postgres-dumps/weavestream-postgres-2026-05-01T03-00-00Z.dump

If the database already contains partial data and the restore fails, recreate it and retry:

docker compose exec -T postgres sh -lc \
  'dropdb -U "$POSTGRES_USER" --if-exists "$POSTGRES_DB" &&
   createdb -U "$POSTGRES_USER" "$POSTGRES_DB"'

Then run the pg_restore command again.

Start the Full Stack

docker compose up -d
docker compose ps

The api container runs prisma migrate deploy on boot. If the restored dump already includes all migrations, this is a no-op.

6. Restore Uploaded Files Later

If you restored the database first and need to restore files afterward:

cd /opt/weavestream
docker compose stop api worker
rsync -a /backup/weavestream/files-2026-05-01/ data/files/
docker compose start api worker

7. Verify the Restore

After the stack starts:

  1. Sign in with an existing admin account.
  2. Open a saved password and confirm it decrypts. This proves the restored .env has the correct PASSWORD_ENCRYPTION_KEY.
  3. Open an uploaded image or attachment. This proves $DATA_DIR/files is restored.
  4. Go to Admin → Backups and confirm history is visible.
  5. Click Run now and confirm a new dump is written to $DATA_DIR/backup.

8. Troubleshooting

pg_restore: error: input file appears to be a text format dump

The restore command above expects Weavestream's in-app custom-format dump. If you have a .sql or .sql.gz dump, restore it with psql instead:

gunzip -c backup.sql.gz | docker compose exec -T postgres \
  psql -U "$POSTGRES_USER" "$POSTGRES_DB"

Passwords or Secrets Do Not Decrypt

The database restored, but .env does not match the original deployment. Restore the original values for:

PASSWORD_ENCRYPTION_KEY
PASSWORD_PREVIOUS_KEYS
MFA_ENCRYPTION_KEY
INTEGRATION_SECRET_KEY
SMTP_SECRET_KEY

If these keys are lost, encrypted vault values cannot be recovered from the database dump.

Attachments Are Missing

The database references files that are not present under $DATA_DIR/files. Restore the file backup again and confirm ownership/permissions allow the api container to read the directory.

Backup Runs Keep Only One Dump Per Day

Increase Keep last in the backup schedule. Daily / weekly / monthly retention is bucketed, so multiple manual runs in the same day count as one daily slot unless protected by Keep last.

Checklist

  • At least one scheduled backup exists under Admin → Backups.
  • A manual Run now backup has succeeded.
  • $DATA_DIR/backup is copied off-host.
  • $DATA_DIR/files is copied off-host.
  • .env is stored securely outside the Docker host.
  • Off-host backups are encrypted.
  • A restore has been tested on a clean host.