# Backups & Restoration [← Back to Index](../CLAUDE.md) --- ## Overview Tududi automatically creates SQLite database file backups before migrations and on startup to protect your data. These backups ensure you have a recovery point if a migration fails or if you need to restore to a previous state. --- ## Automatic SQLite File Backups ### When Backups Are Created SQLite database file backups are **automatically created** in these scenarios: 1. **Before migrations** - Every time the app starts and finds an existing database 2. **On startup** - Before running any database operations (Docker/production) 3. **Manual trigger** - Via the backup script **Location:** `/backend/cmd/start.sh` (lines 9-78) ### Backup File Location - **Development:** `/backend/db/db-backup-YYYYMMDDHHMMSS.sqlite3` - **Docker/Production:** `/app/backend/db/db-backup-YYYYMMDDHHMMSS.sqlite3` (mounted volume) ### Backup Retention Policy The system automatically manages backup retention with these rules: | Timeframe | Retention Policy | |-----------|------------------| | **Today** | Keep up to 4 most recent backups | | **Past 7 days** | Keep 1 backup per day (most recent) | | **Older than 7 days** | Automatically deleted | **Example:** ``` db-backup-20260315083000.sqlite3 ← Today (backup #1) db-backup-20260315070000.sqlite3 ← Today (backup #2) db-backup-20260314193000.sqlite3 ← Yesterday (only 1 kept) db-backup-20260313100000.sqlite3 ← 2 days ago (only 1 kept) db-backup-20260308120000.sqlite3 ← Automatically deleted (>7 days) ``` ### How Automatic Backups Work When the app starts (via `npm start` or Docker): 1. Check if `DB_FILE` exists 2. If exists, call `backup_db()` function 3. Clean old backups based on retention policy 4. Create timestamped copy: `cp $DB_FILE $backup_file` 5. Run migrations: `npx sequelize-cli db:migrate` 6. Start application **Critical:** Backups are created **before** migrations run, ensuring you have a recovery point if a migration fails. --- ## Restoring from SQLite File Backup ### Quick Restore (Development) ```bash # 1. Stop the application npm stop # or Ctrl+C # 2. List available backups ls -lh backend/db/db-backup-*.sqlite3 # 3. Identify the backup to restore (e.g., db-backup-20260314193000.sqlite3) # 4. Backup current state (optional but recommended) cp backend/db/development.sqlite3 backend/db/development.sqlite3.before-restore # 5. Restore the backup cp backend/db/db-backup-20260314193000.sqlite3 backend/db/development.sqlite3 # 6. Restart the application npm start ``` ### Restore in Docker ```bash # 1. Stop the container docker-compose down # 2. Access the host volume (find your volume location) docker volume inspect tududi_db_data # 3. Navigate to the mount point and list backups cd /var/lib/docker/volumes/tududi_db_data/_data ls -lh db-backup-*.sqlite3 # 4. Backup current state cp production.sqlite3 production.sqlite3.before-restore # 5. Restore from backup cp db-backup-20260314193000.sqlite3 production.sqlite3 # 6. Restart the container docker-compose up -d ``` ### Emergency Restore (Production) If a migration fails and the app won't start: ```bash # The start script creates a backup BEFORE migrations # So the most recent backup is from before the failed migration cd backend/db # Find the most recent backup (will be from just before failure) ls -lt db-backup-*.sqlite3 | head -1 # Restore it cp db-backup-20260315083000.sqlite3 production.sqlite3 # Try starting again npm start ``` --- ## Best Practices ### 1. Before Major Changes Create a manual backup before: - Upgrading Tududi to a new version - Running manual migrations - Bulk data operations - Testing new features ```bash # Quick manual backup (development) cp backend/db/development.sqlite3 backend/db/manual-backup-$(date +%Y%m%d%H%M%S).sqlite3 ``` ### 2. External Backups For production: - Copy `/backend/db/*.sqlite3` to external storage weekly - Test restore procedures periodically ### 3. Docker Volume Backups Backup the entire Docker volume: ```bash # Backup Docker volume docker run --rm \ -v tududi_db_data:/data \ -v $(pwd):/backup \ alpine tar czf /backup/tududi-db-backup-$(date +%Y%m%d).tar.gz -C /data . # Restore Docker volume docker run --rm \ -v tududi_db_data:/data \ -v $(pwd):/backup \ alpine tar xzf /backup/tududi-db-backup-20260314.tar.gz -C /data ``` ### 4. Migration Rollback Strategy If a migration fails: 1. **Don't panic** - automatic backup was created 2. Stop the application 3. Restore the most recent automatic backup (created before migration) 4. Investigate the migration issue 5. Fix the migration or rollback: `npm run migration:undo` ### 5. Test Restore Procedures Periodically test that backups can be restored: ```bash # Test restore in a safe environment cp backend/db/db-backup-20260314193000.sqlite3 backend/db/test-restore.sqlite3 # Verify the backup file is readable sqlite3 backend/db/test-restore.sqlite3 "SELECT COUNT(*) FROM Tasks;" ``` --- ## Backup Commands Reference ```bash # Manual backup (development) cp backend/db/development.sqlite3 backend/db/manual-backup-$(date +%Y%m%d%H%M%S).sqlite3 # Manual backup (production) cp backend/db/production.sqlite3 backend/db/manual-backup-$(date +%Y%m%d%H%M%S).sqlite3 # List all backups ls -lh backend/db/db-backup-*.sqlite3 # Restore specific backup cp backend/db/db-backup-20260314193000.sqlite3 backend/db/development.sqlite3 # Verify backup file integrity sqlite3 backend/db/db-backup-20260314193000.sqlite3 "PRAGMA integrity_check;" ``` --- ## Troubleshooting ### Backup File Not Found **Problem:** Can't find automatic backup after startup failure **Solution:** Check if database existed before startup. Backups are only created for existing databases. ```bash # New installations won't have backups yet # First run creates database, second run creates first backup ``` ### Restore Fails with "Database is locked" **Problem:** SQLite database is locked during restore **Solution:** Ensure the application is fully stopped ```bash # Kill all node processes pkill -f "node.*tududi" # Verify no processes are using the database lsof backend/db/development.sqlite3 # Then attempt restore ``` ### Large Backup Files **Problem:** Backup files consuming too much space **Solution:** Automatic cleanup runs on every startup. For manual cleanup: ```bash # Delete backups older than 7 days manually find backend/db -name "db-backup-*.sqlite3" -mtime +7 -delete # Or keep only last 10 backups ls -t backend/db/db-backup-*.sqlite3 | tail -n +11 | xargs rm ``` --- ## Implementation Details ### Backup Script Location The automatic backup script is located at `/backend/cmd/start.sh` (lines 9-78). **Key functions:** - `backup_db()` - Creates timestamped SQLite file copy - Automatic cleanup based on retention policy - Runs before every migration --- ## Related Documentation - [Database & Migrations](database.md) - Schema changes and migrations - [Development Workflow](development-workflow.md) - Database management commands - [Architecture](architecture.md) - Data model relationships --- [← Back to Index](../CLAUDE.md)