Skip to content

Backup & Restore

Dreadnought's entire application state lives in a single SQLite file. Backing up and restoring is as simple as copying that one file.


What's in the Database

The database (ddns.db) contains:

Table Contents
users Admin account (email, password hash)
domains Registered Cloudflare zones (name, Zone ID)
tracked_records DNS records being managed
settings Runtime settings (poll interval, last IP, etc.)
audit_log Full sync history

Not in the database: - Your Cloudflare API token (stored in .env / environment variables) - The SECRET_KEY (stored in .env)

So a complete backup requires: 1. The ddns.db file 2. Your .env file


Database Location

Deployment Database path
Docker Compose ./data/ddns.db (relative to docker-compose.yml)
Coolify Docker-managed volume (use docker cp to extract)
Systemd (bare metal) /var/lib/dreadnought/ddns.db

Manual Backup

Docker Compose

# Simple copy (app can stay running — SQLite supports concurrent reads)
cp ./data/ddns.db ./data/ddns_backup_$(date +%Y%m%d_%H%M%S).db

Coolify / Named Volume

# Find the container name
docker ps | grep dreadnought-api

# Copy the database out of the container
docker cp <container-name>:/data/ddns.db ./ddns_backup_$(date +%Y%m%d_%H%M%S).db

Systemd (bare metal)

cp /var/lib/dreadnought/ddns.db \
   /var/backups/ddns_$(date +%Y%m%d_%H%M%S).db

Automated Backups with Cron

Daily backup (Docker Compose)

crontab -e

Add:

# Backup Dreadnought database every day at 2 AM
0 2 * * * cp /path/to/Dreadnought-DDNS/data/ddns.db /path/to/backups/ddns_$(date +\%Y\%m\%d).db

Replace /path/to/Dreadnought-DDNS with your actual project path.

With automatic pruning (keep last 30 days)

crontab -e

Add:

# Backup and prune old backups (keep 30 days)
0 2 * * * cp /path/to/data/ddns.db /path/to/backups/ddns_$(date +\%Y\%m\%d).db && find /path/to/backups -name "ddns_*.db" -mtime +30 -delete

Systemd timer (alternative to cron)

Create /etc/systemd/system/dreadnought-backup.service:

[Unit]
Description=Dreadnought DDNS Database Backup

[Service]
Type=oneshot
ExecStart=/bin/bash -c 'cp /path/to/data/ddns.db /path/to/backups/ddns_$(date +%%Y%%m%%d_%%H%%M%%S).db'

Create /etc/systemd/system/dreadnought-backup.timer:

[Unit]
Description=Daily Dreadnought DDNS Backup

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Enable:

sudo systemctl daemon-reload
sudo systemctl enable --now dreadnought-backup.timer

Backing Up to a Remote Location

rsync to another server

rsync -avz ./data/ddns.db user@backup-server:/backups/dreadnought/

To Backblaze B2 / S3 (using rclone)

# Install rclone and configure your storage
rclone copy ./data/ddns.db b2:your-bucket/dreadnought/

# Scheduled via cron:
0 3 * * * rclone copy /path/to/data/ddns.db b2:your-bucket/dreadnought/ddns_$(date +\%Y\%m\%d).db

Restoring from Backup

Docker Compose

  1. Stop the app to prevent writes during restore:
docker compose stop api worker
  1. Replace the database file:
cp ./data/ddns_backup_20240115.db ./data/ddns.db
  1. Start the app:
docker compose start api worker
  1. Verify the restore:
# Check logs for startup errors
docker compose logs api --tail 20

# Verify data looks correct by logging into the dashboard

Systemd (bare metal)

sudo systemctl stop dreadnought-api dreadnought-worker

sudo cp /var/backups/ddns_20240115.db /var/lib/dreadnought/ddns.db
sudo chown dreadnought:dreadnought /var/lib/dreadnought/ddns.db

sudo systemctl start dreadnought-api dreadnought-worker
sudo systemctl status dreadnought-api

Migrating to a New Server

Use this process to move Dreadnought to a different machine.

On the old server

# 1. Back up the database
cp ./data/ddns.db ./ddns_migration.db

# 2. Copy your .env file somewhere safe
cp .env .env_backup

On the new server

# 1. Clone the repository
git clone https://github.com/dreadnought-0/Dreadnought-DDNS.git
cd Dreadnought-DDNS

# 2. Restore your .env
cp /path/to/.env_backup .env

# 3. Create the data directory
mkdir -p ./data
chmod 777 ./data

# 4. Copy the database from the old server
scp old-server:/path/to/ddns_migration.db ./data/ddns.db

# 5. Start the app
docker compose up -d

# 6. Verify everything is working
docker compose ps
docker compose logs -f

All your domains, records, settings, and audit log will be intact.


Verifying a Backup

To verify a backup without restoring it:

# Check that the file is a valid SQLite database
sqlite3 ./ddns_backup.db "PRAGMA integrity_check;"
# Expected output: ok

# Check record counts
sqlite3 ./ddns_backup.db "SELECT COUNT(*) FROM domains; SELECT COUNT(*) FROM tracked_records;"

# View last 5 audit log entries
sqlite3 ./ddns_backup.db "SELECT ts, action FROM audit_log ORDER BY ts DESC LIMIT 5;"

Install sqlite3 if needed: sudo apt install sqlite3


What's Not Backed Up (And Why It Doesn't Matter)

The Docker images: Can be rebuilt from source with docker compose build. No data loss.

Container logs: Ephemeral — cleared when containers are rebuilt. Important events are also in the audit log table.

node_modules / Python venv: Installed from requirements.txt and package.json. Rebuild recreates them.