# Database Backup and Restore

This guide covers database backups for DMARQ deployments using SQLite or PostgreSQL. Back up the database before upgrades, before changing migrations, and on a regular schedule that matches how much DMARC history you can afford to lose.

## What To Back Up

Back up these items together:

- The DMARQ database: SQLite file or PostgreSQL database.
- The deployment configuration needed to reconnect the app to that database.
- The secret store or secret references used by the deployment. Do not copy raw secrets into backup notes, issue comments, or chat logs.

The database contains domains, parsed reports, report records, settings, mail source configuration, Gmail ingest state, and import history. It does not replace your deployment secrets, so keep secret backups in your password manager or secret-management system.

## Backup Cadence

Recommended minimums:

- Before every upgrade or migration.
- Daily for active production instances.
- Weekly for low-volume personal instances.
- After adding important domains or mail sources.

Keep at least one recent backup off the server that runs DMARQ. Periodically test restoring into a temporary database so backups are proven, not only present.

## SQLite Backups

SQLite is easiest to back up when the app is stopped. The `.backup` command is safer than copying a live database file because it asks SQLite to create a consistent copy.

### Docker Compose SQLite

```bash
mkdir -p backups
backup_file="backups/dmarq-$(date +%Y%m%d-%H%M%S).db"

docker compose stop backend
sqlite3 data/dmarq.db ".backup $backup_file"
sqlite3 "$backup_file" "PRAGMA integrity_check;"
docker compose start backend
```

Restore a SQLite backup:

```bash
docker compose stop backend
cp data/dmarq.db "data/dmarq-before-restore-$(date +%Y%m%d-%H%M%S).db"
cp backups/dmarq-backup.db data/dmarq.db
docker compose start backend
docker compose logs --tail=100 backend
```

### Manual SQLite

```bash
sudo systemctl stop dmarq
mkdir -p /var/backups/dmarq
backup_file="/var/backups/dmarq/dmarq-$(date +%Y%m%d-%H%M%S).db"

sqlite3 /path/to/dmarq/data/dmarq.db ".backup $backup_file"
sqlite3 "$backup_file" "PRAGMA integrity_check;"
sudo systemctl start dmarq
```

Restore a manual SQLite backup:

```bash
sudo systemctl stop dmarq
cp /path/to/dmarq/data/dmarq.db "/path/to/dmarq/data/dmarq-before-restore-$(date +%Y%m%d-%H%M%S).db"
cp /var/backups/dmarq/dmarq-backup.db /path/to/dmarq/data/dmarq.db
sudo systemctl start dmarq
sudo journalctl -u dmarq -n 100
```

## PostgreSQL Backups

Use PostgreSQL custom-format dumps for normal operations. They restore cleanly with `pg_restore` and are easier to validate than plain SQL files.

### Docker Compose PostgreSQL

```bash
mkdir -p backups
backup_file="backups/dmarq-$(date +%Y%m%d-%H%M%S).dump"

docker compose exec -T db pg_dump \
  -U "${DB_USER:-dmarq}" \
  -d "${DB_NAME:-dmarq}" \
  --format=custom \
  > "$backup_file"

pg_restore --list "$backup_file" >/dev/null
```

Restore a Docker Compose PostgreSQL backup:

```bash
docker compose stop backend

cat backups/dmarq-backup.dump | docker compose exec -T db pg_restore \
  -U "${DB_USER:-dmarq}" \
  -d "${DB_NAME:-dmarq}" \
  --clean \
  --if-exists \
  --no-owner

docker compose start backend
docker compose logs --tail=100 backend
```

### Manual PostgreSQL

If `DATABASE_URL` is available to your shell:

```bash
mkdir -p /var/backups/dmarq
backup_file="/var/backups/dmarq/dmarq-$(date +%Y%m%d-%H%M%S).dump"

pg_dump --dbname "$DATABASE_URL" --format=custom > "$backup_file"
pg_restore --list "$backup_file" >/dev/null
```

Restore a manual PostgreSQL backup:

```bash
sudo systemctl stop dmarq

pg_restore \
  --dbname "$DATABASE_URL" \
  --clean \
  --if-exists \
  --no-owner \
  /var/backups/dmarq/dmarq-backup.dump

sudo systemctl start dmarq
sudo journalctl -u dmarq -n 100
```

If you do not use `DATABASE_URL`, pass the database name, host, user, and port to `pg_dump` and `pg_restore` with the standard PostgreSQL flags.

## Before Upgrades

Use this checklist before upgrading DMARQ:

1. Create a fresh database backup.
2. Verify the backup can be listed or passes SQLite integrity checks.
3. Record the current DMARQ version and image tag.
4. Apply the upgrade and let migrations run.
5. Confirm the app starts, the dashboard loads, and recent reports are still visible.

## Restore Verification

After any restore, check:

- The app starts without database errors.
- Domain list and dashboard totals are present.
- Mail source import history is visible.
- Recent uploaded or imported reports appear in the UI.
- Background polling logs do not show repeated database failures.

For PostgreSQL production deployments with strict recovery requirements, also consider managed database snapshots or WAL archiving in addition to `pg_dump`.
