# Backup and Restore Comprehensive backup and restore for data safety and disaster recovery. ## Quick Start ### Create a Backup ```bash # Default directory (./backups) mix concord.backup create # Custom directory mix concord.backup create --path /mnt/backups ``` ### List Backups ```bash mix concord.backup list ``` ### Restore from Backup ```bash # Interactive (asks for confirmation) mix concord.backup restore ./backups/concord_backup_20251023T143052.backup # Force (skip confirmation) mix concord.backup restore ./backups/concord_backup_20251023T143052.backup --force ``` ### Verify Integrity ```bash mix concord.backup verify ./backups/concord_backup_20251023T143052.backup ``` ### Cleanup Old Backups ```bash # Keep only 5 most recent mix concord.backup cleanup --keep-count 5 # Keep backups from last 7 days mix concord.backup cleanup --keep-days 7 ``` ## Programmatic API ```elixir # Create backup {:ok, backup_path} = Concord.Backup.create(path: "/mnt/backups") # List backups {:ok, backups} = Concord.Backup.list("/mnt/backups") Enum.each(backups, fn backup -> IO.puts("#{backup.path} - #{backup.entry_count} entries") end) # Restore :ok = Concord.Backup.restore("/mnt/backups/concord_backup_20251023.backup") # Verify case Concord.Backup.verify("/path/to/backup.backup") do {:ok, :valid} -> IO.puts("Backup is valid") {:ok, :invalid} -> IO.puts("Backup is corrupted") {:error, reason} -> IO.puts("Error: #{inspect(reason)}") end # Cleanup {:ok, deleted_count} = Concord.Backup.cleanup( path: "/mnt/backups", keep_count: 10, keep_days: 30 ) ``` ## Backup Format Backups are compressed Erlang term files (`.backup`) containing: - **Metadata**: Timestamp, cluster info, entry count, checksum - **Snapshot Data**: Full copy of all key-value pairs - **Integrity Check**: SHA-256 checksum for verification Features: - Compressed storage for efficient disk usage - Atomic snapshots via Ra consensus - Compatible across cluster nodes ## Automated Backups ### Cron-based ```bash # Backup every hour 0 * * * * cd /app && mix concord.backup create --path /mnt/backups # Cleanup old backups daily 0 2 * * * cd /app && mix concord.backup cleanup --keep-count 24 --keep-days 7 ``` ### In-App Scheduler ```elixir defmodule MyApp.BackupScheduler do use GenServer def start_link(_opts) do GenServer.start_link(__MODULE__, %{}, name: __MODULE__) end def init(state) do schedule_backup() {:ok, state} end def handle_info(:backup, state) do case Concord.Backup.create(path: "/mnt/backups") do {:ok, path} -> Logger.info("Backup created: #{path}") Concord.Backup.cleanup(path: "/mnt/backups", keep_count: 24) {:error, reason} -> Logger.error("Backup failed: #{inspect(reason)}") end schedule_backup() {:noreply, state} end defp schedule_backup do Process.send_after(self(), :backup, :timer.hours(1)) end end ``` ## Disaster Recovery ```bash # 1. Stop the application (if running) # 2. Restore from backup mix concord.backup restore /mnt/backups/latest.backup --force # 3. Verify data mix concord.cluster status # 4. Start the application mix run --no-halt ``` ## Best Practices 1. **Regular Backups** — Schedule automated backups hourly or daily 2. **Off-site Storage** — Copy backups to remote storage (S3, GCS, etc.) 3. **Test Restores** — Periodically test backup restoration 4. **Retention Policy** — Keep multiple backup versions 5. **Monitor** — Set up alerts for backup failures 6. **Verify** — Always verify backups after creation