A CLI tool for backing up databases to cloud storage.
Project description
Database Backup Tool
A command-line tool for backing up MySQL databases to local storage or AWS S3.
Quick start
- Install
pip install database-backup
# upgrade
pip install --upgrade database-backup
- Initialize storage configuration
# Interactive init (sets up storage/global settings)
db-backup init
- Add a database connection
# Add your first database connection
db-backup add --name production --host 127.0.0.1 --user root
- Run backup
db-backup backup --connection production --local # store on filesystem
db-backup backup --connection production --s3 # store on S3
Features
- Multiple database connections: Manage multiple database connections with separate JSON storage.
- Back up all MySQL databases, excluding system databases.
- Store backups in a local directory or an AWS S3 bucket.
- Create a separate folder for each database.
- Timestamped backups for easy identification.
- Automatic cleanup of old backups based on a retention policy.
- Configuration via
.envfile (storage/global settings) andconnections.json(database connections). - Command-line interface for easy operation.
- Cron setup for automatic backups.
Requirements
-
Python 3.10+
-
mysql-connector-python -
boto3 -
python-dotenv -
click -
paramiko(for SSH tunnel support) -
MySQL client tools (provides
mysqldump)On macOS (Homebrew):
brew install mysql-client # Typical binary path: /opt/homebrew/opt/mysql-client/bin/mysqldump (Apple Silicon)
On Debian/Ubuntu:
sudo apt-get update sudo apt-get install mysql-client # Typical binary path: /usr/bin/mysqldump
On Red Hat/CentOS/Fedora:
sudo dnf install mysql # OR sudo dnf install @mysql # Typical binary path: /usr/bin/mysqldump
On Arch/Manjaro:
sudo pacman -Syu sudo pacman -S mysql # Typical binary path: /usr/bin/mysqldump
Installation
From PyPI (recommended):
pip install database-backup
From source (optional):
git clone https://github.com/magicstack-llp/db-backup.git
cd db-backup
pip install -r requirements.txt
Configuration
The tool uses two separate configuration files:
-
.envfile: Stores storage and global settings (S3 credentials, backup directory, retention count, etc.)- Default location:
~/.config/database-backup/.env(or${XDG_CONFIG_HOME}/database-backup/.env) - Override with
--configorDATABASE_BACKUP_CONFIGenv var
- Default location:
-
connections.jsonfile: Stores database connection details (host, port, user, password, etc.)- Default location:
~/.config/database-backup/connections.json - Managed via CLI commands:
add,remove,list
- Default location:
Storage Configuration (.env)
Example .env (storage/global settings only):
BACKUP_DRIVER=local # local, s3
BACKUP_DIR=/Users/<USER>/backups/databases
RETENTION_COUNT=5
S3_BUCKET=mybucket
S3_PATH=backups
AWS_ACCESS_KEY_ID=XXXXXXX
AWS_SECRET_ACCESS_KEY=YYYYYYY
Connection Management
Database connections are stored separately in JSON format. Use these commands:
db-backup add: Add a new database connectiondb-backup remove: Remove a database connectiondb-backup list: List all database connections
Example connections.json:
{
"production": {
"host": "127.0.0.1",
"port": 3306,
"user": "root",
"password": "password",
"mysqldump_path": "/opt/homebrew/opt/mysql-client/bin/mysqldump",
"excluded_databases": ["db_1", "db_2"],
"storage_driver": "local",
"path": "/backups/production"
},
"staging": {
"host": "192.168.1.100",
"port": 3306,
"user": "backup_user",
"password": "secure_password",
"mysqldump_path": "/usr/bin/mysqldump",
"excluded_databases": [],
"storage_driver": "s3",
"s3_bucket": "my-backup-bucket",
"path": "staging"
},
"remote_ssh": {
"host": "127.0.0.1",
"port": 3306,
"user": "root",
"password": "password",
"ssh_host": "db.example.com",
"ssh_port": 22,
"ssh_user": "backup_user",
"ssh_key_path": "/home/user/.ssh/id_rsa",
"storage_driver": "local",
"path": "/backups/remote"
},
"bastion_ssh": {
"host": "127.0.0.1",
"port": 3306,
"user": "root",
"password": "password",
"ssh_host": "internal-db.example.com",
"ssh_port": 22,
"ssh_user": "backup_user",
"ssh_key_path": "/home/user/.ssh/id_rsa",
"bastion_host": "bastion.example.com",
"bastion_port": 22,
"bastion_user": "bastion_user",
"bastion_key_path": "/home/user/.ssh/bastion_key",
"storage_driver": "s3",
"s3_bucket": "my-backup-bucket",
"path": "bastion"
}
}
Connection Management Commands
Add a connection
db-backup add --name production --host 127.0.0.1 --port 3306 --user root --password mypass
Or interactively:
db-backup add
Options:
--name: Connection name (required)--host: MySQL server host (default: localhost)--port: MySQL server port (default: 3306)--user: MySQL username (default: root)--password: MySQL password (will prompt if not provided)--mysqldump: Path to mysqldump binary--excluded: Comma-separated list of databases to exclude--storage-driver: Preferred storage driver for this connection (local/s3)--path: Storage path - backup directory for local storage or S3 path prefix (overrides .env)--s3-bucket: Preferred S3 bucket for this connection (overrides .env)--ssh-host: SSH hostname for tunnel (if database is behind SSH)--ssh-port: SSH port (default: 22)--ssh-user: SSH username for tunnel--ssh-key-path: Path to SSH private key file--bastion-host: Bastion host for double-hop SSH (optional)--bastion-port: Bastion SSH port (default: 22)--bastion-user: Bastion SSH username (optional, uses ssh-user if not provided)--bastion-key-path: Bastion SSH key path (optional, uses ssh-key-path if not provided)
Remove a connection
db-backup remove --name production
List connections
db-backup list
Cron setup
You can set up cron jobs interactively:
db-backup cron
- You can enter either:
- A full cron expression (5 fields), e.g.
0 3,15 * * * - Or a comma-separated list of 24h times, e.g.
03:00,15:00
- A full cron expression (5 fields), e.g.
- Default schedule:
0 3,15 * * *(daily at 03:00 and 15:00) - You'll be prompted to select a connection and storage type
- The CLI writes a managed block to your user crontab between
# BEGIN db-backup (managed)and# END db-backup (managed). - It will pass
--config ~/.config/database-backup/.envby default (or whatever you provide with--config).
Helpful: You can use a cron expression generator like it-tools crontab generator to craft schedules.
Usage
Basic backup
# Backup using a specific connection
db-backup backup --connection production --local
# If only one connection exists, it will be used automatically
db-backup backup --local
# If multiple connections exist, you'll be prompted to select one
db-backup backup --local
Backup options
--connection NAME: Specify which connection to use (required if multiple connections exist)--local: Store backups locally--s3: Store backups in S3--retention N: Number of backups to retain (overrides .env)--backup-dir PATH: Local backup directory (overrides .env)--mysqldump PATH: Path to mysqldump binary (overrides connection setting)--compress/--no-compress: Compress backups with gzip (default: compress)--config FILE: Override .env config file path
Examples
# Local backup with specific connection
db-backup backup --connection production --local
# S3 backup
db-backup backup --connection staging --s3
# Override retention count
db-backup backup --connection production --local --retention 10
# Custom backup directory
db-backup backup --connection production --local --backup-dir /custom/path
Architecture
The database backup tool is built using a Clean Architecture approach, which separates the code into four layers:
- Domain: Contains the core business logic and entities of the application.
- Data: Contains the data access layer, which is responsible for interacting with the database and storage.
- App: Contains the application logic, which orchestrates the backup process.
- Interface: Contains the user interface, which is responsible for handling user input and displaying output.
This separation of concerns makes the application more modular, testable, and maintainable.
Configuration Reference
.env File (Storage/Global Settings)
All storage and global settings are read from your .env file unless overridden by CLI flags. Defaults are shown where applicable.
- BACKUP_DRIVER: Where to store backups. One of:
local,s3- Example:
local - Note: You can also pass
--localor--s3on the CLI.
- Example:
- BACKUP_DIR: Base directory for local backups (used when BACKUP_DRIVER=local or with --local).
- Example:
/Users/alex/backups/databases
- Example:
- S3_BUCKET: S3 bucket name (used when BACKUP_DRIVER=s3 or with --s3).
- Example:
my-bucket
- Example:
- S3_PATH: Prefix/path inside the bucket to store backups (folders are created per database).
- Example:
backups
- Example:
- AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY: AWS credentials to access the bucket.
- Example:
AWS_ACCESS_KEY_ID=AKIA.../AWS_SECRET_ACCESS_KEY=... - Tip: If using instance/profile or environment credentials, these can be left empty; boto3 will try the default credential chain.
- Example:
- RETENTION_COUNT: Number of most recent backups to keep per database. Older ones are removed automatically.
- Default:
5 - Example:
10
- Default:
- DATABASE_BACKUP_CONFIG: Optional env var to point the CLI to a different .env file.
- Example:
/etc/database-backup/.env
- Example:
connections.json (Database Connections)
Database connections are stored in JSON format. Each connection includes:
- host: MySQL server host
- Example:
127.0.0.1
- Example:
- port: MySQL server port
- Default:
3306
- Default:
- user: MySQL username with privileges to dump all databases
- Example:
root
- Example:
- password: Password for the MySQL user
- Example:
changeme
- Example:
- mysqldump_path: Full path or command name to mysqldump (optional)
- Example (macOS/Homebrew on Apple Silicon):
/opt/homebrew/opt/mysql-client/bin/mysqldump - If not set, the tool tries to resolve mysqldump from PATH
- Example (macOS/Homebrew on Apple Silicon):
- excluded_databases: List of additional databases to skip (optional)
- Example:
["db_1", "db_2"] - Note: System DBs are always excluded:
mysql,information_schema,performance_schema,sys
- Example:
- storage_driver: Preferred storage driver for this connection (optional)
- Values:
localors3 - If not set, uses CLI flag (
--local/--s3) or falls back toBACKUP_DRIVERfrom .env
- Values:
- path: Storage path - backup directory for local storage or S3 path prefix (optional)
- For local storage: Example
/backups/production - For S3 storage: Example
production/backups - Priority: CLI
--backup-dir(for local) > connectionpath>.envBACKUP_DIRorS3_PATH
- For local storage: Example
- s3_bucket: Preferred S3 bucket for this connection (optional)
- Example:
my-backup-bucket - Used when
storage_driveriss3 - Priority: connection
s3_bucket>.envS3_BUCKET
- Example:
- ssh_host: SSH hostname for tunnel (optional)
- Example:
db.example.com - Required if database is behind SSH
- Example:
- ssh_port: SSH port (optional, default: 22)
- Example:
22
- Example:
- ssh_user: SSH username for tunnel (optional)
- Example:
backup_user - Required if
ssh_hostis set
- Example:
- ssh_key_path: Path to SSH private key file (optional)
- Example:
/home/user/.ssh/id_rsa - Required if
ssh_hostis set - Supports RSA, ECDSA, Ed25519, and DSS keys
- Example:
- bastion_host: Bastion host for double-hop SSH (optional)
- Example:
bastion.example.com - Used when database requires SSH through a bastion host
- Example:
- bastion_port: Bastion SSH port (optional, default: 22)
- Example:
22
- Example:
- bastion_user: Bastion SSH username (optional)
- Example:
bastion_user - Defaults to
ssh_userif not provided
- Example:
- bastion_key_path: Bastion SSH key path (optional)
- Example:
/home/user/.ssh/bastion_key - Defaults to
ssh_key_pathif not provided
- Example:
Examples
Connection Management
# Add a production database connection with local storage preference
db-backup add --name production --host db.example.com --user backup_user --password secure_pass \
--storage-driver local --path /backups/production
# Add a staging connection with S3 storage preference
db-backup add --name staging --host staging.db.example.com --user backup_user --password secure_pass \
--storage-driver s3 --s3-bucket my-backup-bucket --path staging
# Add a connection without storage preferences (will use .env or CLI flags)
db-backup add --name dev --host localhost --user root --password devpass
# Add a connection with simple SSH tunnel
db-backup add --name remote --host 127.0.0.1 --port 3306 --user root --password pass \
--ssh-host db.example.com --ssh-user backup_user --ssh-key-path ~/.ssh/id_rsa
# Add a connection with bastion host (double-hop SSH)
db-backup add --name bastion --host 127.0.0.1 --port 3306 --user root --password pass \
--ssh-host internal-db.example.com --ssh-user backup_user --ssh-key-path ~/.ssh/id_rsa \
--bastion-host bastion.example.com --bastion-user bastion_user --bastion-key-path ~/.ssh/bastion_key
# List all connections (shows storage preferences)
db-backup list
# Remove a connection
db-backup remove --name dev
Running Backups
# Backup using connection's preferred storage (if set)
db-backup backup --connection production
# Backup production database to local storage (overrides connection preference)
db-backup backup --connection production --local
# Backup staging database to S3 (overrides connection preference)
db-backup backup --connection staging --s3
# Backup with custom retention
db-backup backup --connection production --retention 10
# Backup with custom backup directory (overrides connection preference)
db-backup backup --connection production --local --backup-dir /custom/backup/path
# Backup with custom mysqldump path
db-backup backup --connection production --mysqldump /custom/path/mysqldump
SSH Tunnel Support
The tool supports connecting to MySQL databases through SSH tunnels, including:
Simple SSH Tunnel
For databases accessible via a single SSH hop:
db-backup add --name remote --host 127.0.0.1 --port 3306 --user root --password pass \
--ssh-host db.example.com --ssh-user backup_user --ssh-key-path ~/.ssh/id_rsa
In this configuration:
--hostand--portrefer to the MySQL server as seen from the SSH host (typically127.0.0.1:3306)--ssh-hostis the SSH server that can reach the MySQL server--ssh-userand--ssh-key-pathare used to authenticate to the SSH server
SSH with Bastion Host
For databases requiring a double-hop SSH connection (through a bastion host):
db-backup add --name bastion --host 127.0.0.1 --port 3306 --user root --password pass \
--ssh-host internal-db.example.com --ssh-user backup_user --ssh-key-path ~/.ssh/id_rsa \
--bastion-host bastion.example.com --bastion-user bastion_user --bastion-key-path ~/.ssh/bastion_key
In this configuration:
- First SSH connection is made to the bastion host
- Second SSH connection is made through the bastion to the target SSH host
- MySQL connection is then tunneled through both SSH connections
SSH Key Requirements
- SSH keys must be in a format supported by paramiko (RSA, ECDSA, Ed25519, or DSS)
- Key files should have appropriate permissions (typically
600) - The SSH user must have access to the MySQL server on the remote host
How It Works
- When a backup is initiated with SSH configuration, the tool establishes an SSH tunnel
- A local port is opened that forwards to the remote MySQL server
- All MySQL connections (both for listing databases and running mysqldump) use the local tunnel port
- The tunnel is automatically cleaned up after the backup completes
Upcoming Features
- Web UI Mangement Server
- Multiple connections with SQLite
- Postgres Support
- Mongodb Support
- Independent Docker Container
- Backup history and management
- Restore Database MySQL, Postgres, MongoDB CLI and UI
- Multiple compression
- Multifile database backup
- Exclude tables
- Database Size Viewer
Building Standalone Executables
This project can be built into a single standalone executable for cross-platform distribution using PyInstaller.
Prerequisites
- Python 3.10+
- uv package manager (install with:
curl -LsSf https://astral.sh/uv/install.sh | sh) - PyInstaller (will be installed automatically by build scripts via uv)
Quick Build (Current Platform)
To build an executable for your current platform:
# Make sure uv is installed (if not already)
# curl -LsSf https://astral.sh/uv/install.sh | sh
# Build the executable (uv will handle dependencies)
./build.sh
The executable will be created in the dist/ directory:
- Linux/macOS:
dist/db-backup - Windows:
dist/db-backup.exe
Cross-Platform Builds
Using GitHub Actions (Recommended)
The project includes a GitHub Actions workflow (.github/workflows/build.yml) that automatically builds executables for Linux, Windows, and macOS when you create a release tag:
git tag v0.3.0
git push origin v0.3.0
This will create executables for all platforms and attach them to the GitHub release.
Manual Cross-Platform Builds
Linux (using Docker):
docker run --rm -v $(pwd):/src -w /src python:3.11-slim bash -c \
'curl -LsSf https://astral.sh/uv/install.sh | sh && source ~/.cargo/env && uv sync && uv pip install -r requirements-build.txt && uv run pyinstaller db-backup.spec --clean'
Windows:
uv sync
uv pip install -r requirements-build.txt
uv run pyinstaller db-backup.spec --clean
macOS:
uv sync
uv pip install -r requirements-build.txt
uv run pyinstaller db-backup.spec --clean
Using the Executable
Once built, the executable is completely standalone and includes all Python dependencies. You can:
- Copy it anywhere: The executable is self-contained and doesn't require Python to be installed
- Run it directly:
./db-backup --help(Linux/macOS) ordb-backup.exe --help(Windows) - Distribute it: Share the executable with others without requiring them to install Python or dependencies
Note: The executable still requires:
- MySQL client tools (
mysqldump) to be installed on the system - Appropriate system permissions for file operations
- Network access for S3 backups (if using S3 storage)
Build Configuration
The build configuration is defined in db-backup.spec. Key features:
- Single-file executable (all dependencies bundled)
- Console application (for CLI usage)
- Includes all required Python packages (boto3, click, mysql-connector, paramiko, etc.)
- UPX compression enabled (if available) to reduce file size
Troubleshooting
If the executable fails to run:
- Check that all required system dependencies are installed (especially
mysqldump) - Verify the executable has execute permissions:
chmod +x dist/db-backup - Run with verbose output to see errors:
./dist/db-backup --help - Check that the build completed successfully without errors
Contributing
Contributions are welcome! Please feel free to submit a pull request or open an issue if you have any suggestions or feedback.
License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file database_backup-0.3.1.tar.gz.
File metadata
- Download URL: database_backup-0.3.1.tar.gz
- Upload date:
- Size: 24.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47a68ad8482cd23e25ca4ab7480f876e09e6a3de7df0fd54e949683051b5d46f
|
|
| MD5 |
df43df5306ccb7390dc6b2c70e9fa978
|
|
| BLAKE2b-256 |
4d2b1fc516ba48c4ae882b23ba01689869d5a380de9ac5733243c05d0dc0fc0a
|
Provenance
The following attestation bundles were made for database_backup-0.3.1.tar.gz:
Publisher:
publish.yml on magicstack-llp/db-backup
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
database_backup-0.3.1.tar.gz -
Subject digest:
47a68ad8482cd23e25ca4ab7480f876e09e6a3de7df0fd54e949683051b5d46f - Sigstore transparency entry: 708526766
- Sigstore integration time:
-
Permalink:
magicstack-llp/db-backup@fbb06d53ac68321e09971e934268e5ad00c58cc5 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/magicstack-llp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fbb06d53ac68321e09971e934268e5ad00c58cc5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file database_backup-0.3.1-py3-none-any.whl.
File metadata
- Download URL: database_backup-0.3.1-py3-none-any.whl
- Upload date:
- Size: 26.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c285d76cb58785a35a05d561e3ed90d7f1e7fe20d2c9250e835b1213f7302aaf
|
|
| MD5 |
90129a47496777e14404efa669b6642e
|
|
| BLAKE2b-256 |
da18d003788c0e536f41625361d78f909a0f7b12a607701f0a07ef0c7882758a
|
Provenance
The following attestation bundles were made for database_backup-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on magicstack-llp/db-backup
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
database_backup-0.3.1-py3-none-any.whl -
Subject digest:
c285d76cb58785a35a05d561e3ed90d7f1e7fe20d2c9250e835b1213f7302aaf - Sigstore transparency entry: 708526767
- Sigstore integration time:
-
Permalink:
magicstack-llp/db-backup@fbb06d53ac68321e09971e934268e5ad00c58cc5 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/magicstack-llp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fbb06d53ac68321e09971e934268e5ad00c58cc5 -
Trigger Event:
push
-
Statement type: