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¶
- Stop the app to prevent writes during restore:
docker compose stop api worker
- Replace the database file:
cp ./data/ddns_backup_20240115.db ./data/ddns.db
- Start the app:
docker compose start api worker
- 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.