Skip to content

Daily MySQL backup to Google Drive#850

Open
edwh wants to merge 1 commit into
developfrom
feature/gdrive-db-backup
Open

Daily MySQL backup to Google Drive#850
edwh wants to merge 1 commit into
developfrom
feature/gdrive-db-backup

Conversation

@edwh
Copy link
Copy Markdown
Collaborator

@edwh edwh commented May 13, 2026

Summary

Implements automated daily MySQL backups uploaded to Google Drive via rclone. Backups run daily at 2am UTC and only the last 7 backups are retained.

Implementation Details

  • db-backup.sh: New script that:

    • Reads database and backup credentials from init process environ (same pattern as queue-watchdog.sh)
    • Uses mysqldump with --single-transaction and --quick for consistent InnoDB snapshots
    • Compresses output with gzip
    • Uploads to Google Drive using rclone
    • Automatically deletes backups older than 7 days
    • Logs all operations to /var/log/db-backup.log
    • Silent/no-op if GDRIVE_BACKUP_FOLDER_ID is not set (safe for dev environments)
  • Dockerfile.fly changes:

    • Added default-mysql-client (for mysqldump)
    • Added rclone via official install script
    • Copy db-backup.sh to /usr/local/bin with executable permissions
    • Added daily cron entry: 0 2 * * * /usr/local/bin/db-backup.sh (2am UTC)
  • .fly/scripts/startup.sh changes:

    • Added startup registration pattern (mirrors queue-watchdog approach) to ensure db-backup persists through container restarts before full deployments

Required Fly.io Secrets

The following secrets must be set in the Fly.io application for backups to work:

flyctl secrets set RCLONE_CONFIG_GDRIVE_TYPE=drive
flyctl secrets set RCLONE_CONFIG_GDRIVE_SCOPE=drive.file
flyctl secrets set 'RCLONE_CONFIG_GDRIVE_SERVICE_ACCOUNT_CREDENTIALS={...full service account JSON...}'
flyctl secrets set GDRIVE_BACKUP_FOLDER_ID=<Google Drive folder ID>

Getting Service Account Credentials

  1. Create a service account in Google Cloud Console
  2. Generate a JSON key for the service account
  3. Share the target Google Drive folder with the service account email
  4. Use the full JSON key as RCLONE_CONFIG_GDRIVE_SERVICE_ACCOUNT_CREDENTIALS

Notes on Fly.io Secrets

  • RCLONE_CONFIG_GDRIVE_SERVICE_ACCOUNT_CREDENTIALS must be the complete JSON key file (multi-line JSON is supported)
  • The service account needs drive.file scope to access shared folders
  • If GDRIVE_BACKUP_FOLDER_ID is not set, the backup job silently exits (no errors in production if misconfigured)

Test Plan

  • PR approval and merge to develop
  • Verify Dockerfile.fly builds successfully with rclone and mysql-client
  • Deploy to Fly.io with secrets configured
  • Check that /var/log/db-backup.log shows successful backup at 2am UTC the following day
  • Verify backup files appear in Google Drive folder
  • After 8 days, verify only 7 most recent backups remain

🤖 Generated with Claude Code

- Add db-backup.sh script that dumps database with mysqldump, compresses with gzip, and uploads to Google Drive using rclone
- Script reads DB_* and GDRIVE_* env vars from init process (cron doesn't inherit container env vars)
- Automatically rotates backups, keeping only the last 7 daily backups on Google Drive
- Silent/no-op if GDRIVE_BACKUP_FOLDER_ID not set (for dev environments)
- Install default-mysql-client and rclone in production image
- Schedule daily backup at 2am UTC via cron in Dockerfile.fly
- Add startup.sh registration pattern to ensure backup job persists across container restarts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant