🔁 Automated MariaDB database backups with S3-compatible storage integration
- 🗄️ MariaDB Backup to S3
# Using pre-built binary (check Releases page for latest version)
curl -LO https://github.com/capcom6/mariadb-backup-s3/releases/latest/download/mariadb-backup-s3_Linux_x86_64.tar.gz
tar -xzf mariadb-backup-s3_Linux_x86_64.tar.gz
chmod +x mariadb-backup-s3
./mariadb-backup-s3 --help
# Or via go install
go install github.com/capcom6/mariadb-backup-s3@latest
# Configure & run
cp .env.example .env
nano .env # Edit with your credentials
./mariadb-backup-s3- 🛡️ Full database backups using
mariabackup - 🗜️ Compression to
.tar.gzformat - 🔑 Optional encryption using AES-256-GCM
- ☁️ Multiple storage backends (S3-compatible, FTP, filesystem)
- 🔌 Pluggable storage interface for extensibility
- 🔄 Automatic backup rotation with configurable retention policies
- 📋 Backup registry for tracking and managing backups
- 🐳 Docker container support
The backup process follows these steps:
- 📂 Create temporary working directory
- 💾 Perform MariaDB backup using
mariabackup --backup - 🔧 Prepare backup for consistency using
mariabackup --prepare - 🗜️ Compress backup to
.tar.gzarchive - 🔑 Encrypt archive using AES-256-GCM
- 🚀 Upload archive to configured storage backend
- 📋 Update backup registry with new backup metadata
- 🧹 Clean up old backups based on retention policy (unless
--skip-retentionis set)
The restore process follows these steps:
- 📥 Download the backup file from the specified storage backend
- 🔑 Decrypt the backup using AES-256-GCM
- 🗜️ Decompress the
.tar.gzarchive - 🔄 Restore the database files to specified directory
The tool uses a temporary working directory to store intermediate files. By default, it uses the system's default temporary directory (e.g., /tmp). If for some reason you need to use a different directory, you can specify it via the TMPDIR environment variable.
export TMPDIR=/mnt/data/backup
./mariadb-backup-s3 backupThe tool maintains a backup registry (.backup-registry.json) in the storage backend to track all backups. This registry enables:
- Backup tracking: Each backup is recorded with metadata including ID, filename, creation time, size, SHA256 hash, encryption status, and tool version
- Retention management: The registry is used to apply retention policies and clean up old backups
- Backup listing: View all available backups with their status and metadata
The registry is automatically updated when backups are created or deleted. Each backup entry includes:
| Field | Description |
|---|---|
id |
Unique identifier (timestamp + SHA256 prefix) |
filename |
Backup filename |
created_at |
Creation timestamp |
size_bytes |
File size in bytes |
sha256 |
SHA256 hash of the backup file |
status |
Status: ready, failed, or deleted |
encrypted |
Whether the backup is encrypted |
encryption |
Encryption metadata (algorithm) |
tool |
Tool name and version |
- Go 1.23+ (for building from source)
- MariaDB server
- At least 2x the actual database size in free space (for successful backup)
- Storage backend credentials (depending on chosen storage type)
- Visit the Releases page
- Download the appropriate binary for your OS
- Make executable:
chmod +x mariadb-backup-s3 - Move to PATH:
sudo mv mariadb-backup-s3 /usr/local/bin/
go install github.com/capcom6/mariadb-backup-s3@latestdocker pull ghcr.io/capcom6/mariadb-backup-s3:latestNote The Docker image uses MariaDB's
ltsversion. For specific versions:
- Clone the repository
- Modify
Dockerfilebase image- Build custom image:
docker build -t custom-backup-image .
git clone https://github.com/capcom6/mariadb-backup-s3.git
cd mariadb-backup-s3
go build -o mariadb-backup-s3The tool supports loading configuration from multiple sources:
.envfile in the current directory- Environment variables
- Command-line flags
The priority order is: .env > Environment variables > Command-line flags
The logging system can be configured via environment variables:
LOG_LEVEL: Set log level (debug, info, warn, error, fatal). Default: infoLOG_FORMAT: Set format (human, json). Default: humanLOG_OUTPUT: Set output destination:stdout(default): Standard outputstderr: Standard error- Any file path: Write logs to the specified file
NO_COLOR: When set (any non-empty value), disables colored output for human format
mariadb-backup-s3 [global options] command [command options] [arguments...]The tool offers the following commands:
| Command | Description |
|---|---|
backup |
Perform a backup of the MariaDB database |
restore |
Restore the database files to specified directory |
retention |
Apply retention policies to backups |
registry |
Manage backup registry |
mariadb-backup-s3 backup [options]Options:
| Option | Env Var | Description | Default value |
|---|---|---|---|
| Database | |||
--db-host, --host |
MARIADB__HOST |
MariaDB hostname | localhost |
--db-port, --port |
MARIADB__PORT |
MariaDB port | 3306 |
--db-user, --user |
MARIADB__USER |
MariaDB username | root |
--db-password, --password |
MARIADB__PASSWORD |
MariaDB password | "" |
| Storage | |||
--storage, --storage-url |
STORAGE__URL |
Storage URL, see Storage Types | required |
| Encryption | |||
--encryption-key |
ENCRYPTION__KEY |
Encryption key | "" |
| mariadb-backup | |||
--db-backup-binary |
MARIADB__BACKUP_BINARY |
MariaDB backup binary path | mariadb-backup |
--db-backup-options |
MARIADB__BACKUP_OPTIONS |
MariaDB backup options | "" |
| Retention | |||
--retention-count |
RETENTION__COUNT |
Number of backups to retain, 0 = unlimited | 0 |
--max-age |
RETENTION__MAX_AGE |
Maximum age of backups to keep (e.g. 24h, 168h) | unlimited |
--keep-daily |
RETENTION__KEEP_DAILY |
Number of daily backups to keep | unlimited |
--keep-weekly |
RETENTION__KEEP_WEEKLY |
Number of weekly backups to keep | unlimited |
--keep-monthly |
RETENTION__KEEP_MONTHLY |
Number of monthly backups to keep | unlimited |
--skip-retention |
BACKUP__SKIP_RETENTION |
Skip retention policy after backup | false |
Example:
./mariadb-backup-s3 backup \
--db-host=mariadb.example.com \
--db-user=backup \
--storage-url="file:///var/backups/mariadb"mariadb-backup-s3 restore [options] [backup_name.tar.gz | --latest | --backup-id=<id>]Options:
| Option | Env Var | Description | Default value |
|---|---|---|---|
| Storage | |||
--storage, --storage-url |
STORAGE__URL |
Storage URL, see Storage Types | required |
| Encryption | |||
--encryption-key |
ENCRYPTION__KEY |
Encryption key | "" |
| Restore | |||
--target-dir |
RESTORE__TARGET_DIR |
Target directory to restore files to | required |
--latest |
Restore latest ready backup from registry | false |
|
--backup-id |
Restore backup by registry backup ID | "" |
Note Exactly one backup selector must be specified: either a filename argument,
--latest, or--backup-id.
Arguments:
| Argument | Description |
|---|---|
filename |
Backup file name |
Example:
./mariadb-backup-s3 restore \
--storage-url="file:///var/backups/mariadb" \
--target-dir=/var/lib/mariadb \
backup_name.tar.gzThe retention command applies retention policies to backups stored in the configured storage backend. This allows you to clean up old backups based on various criteria.
mariadb-backup-s3 retention [options]Options:
| Option | Env Var | Description | Default value |
|---|---|---|---|
| Storage | |||
--storage-url |
STORAGE__URL |
Storage URL, see Storage Types | required |
| Retention | |||
--retention-count |
RETENTION__COUNT |
Number of backups to retain, 0 = unlimited | 0 |
--max-age |
RETENTION__MAX_AGE |
Maximum age of backups to keep (e.g. 24h, 168h) | unlimited |
--keep-daily |
RETENTION__KEEP_DAILY |
Number of daily backups to keep | unlimited |
--keep-weekly |
RETENTION__KEEP_WEEKLY |
Number of weekly backups to keep | unlimited |
--keep-monthly |
RETENTION__KEEP_MONTHLY |
Number of monthly backups to keep | unlimited |
| Options | |||
--dry-run |
RETENTION__DRY_RUN |
Show what would be deleted without actually deleting | false |
--force |
RETENTION__FORCE |
Continue even if errors occur | false |
Retention Policy Examples:
# Keep only the 7 most recent backups
./mariadb-backup-s3 retention \
--storage-url="s3://my-bucket/backups" \
--retention-count=7
# Keep backups from the last 7 days
./mariadb-backup-s3 retention \
--storage-url="s3://my-bucket/backups" \
--max-age=168h
# Keep 1 daily backup for 7 days, 1 weekly for 4 weeks, 1 monthly for 12 months
./mariadb-backup-s3 retention \
--storage-url="s3://my-bucket/backups" \
--keep-daily=7 \
--keep-weekly=4 \
--keep-monthly=12
# Preview what would be deleted without actually deleting
./mariadb-backup-s3 retention \
--storage-url="s3://my-bucket/backups" \
--retention-count=3 \
--dry-runNote At least one retention policy must be enabled. The retention command will fail if no policies are specified.
The registry command allows you to manage and view the backup registry.
mariadb-backup-s3 registry [command] [options]Subcommands:
| Command | Alias | Description |
|---|---|---|
list |
ls |
List backups from registry |
List Command Options:
| Option | Env Var | Description | Default value |
|---|---|---|---|
--storage-url |
STORAGE__URL |
Storage URL, see Storage Types | required |
Example:
./mariadb-backup-s3 registry list \
--storage-url="s3://my-bucket/backups"Output:
The list command displays all backups in the registry with the following information:
- ID: Unique backup identifier
- Created At: Backup creation timestamp
- Status: Backup status (
ready,failed, ordeleted) - Encrypted: Whether the backup is encrypted
- Size: Backup file size in bytes
- Filename: Backup filename
For S3-compatible storage (including AWS S3, MinIO, DigitalOcean Spaces, etc.):
STORAGE__URL=s3://bucket-name/path?endpoint=https://s3.example.comRequired for S3:
AWS_ACCESS_KEY: Your access keyAWS_SECRET_KEY: Your secret keyAWS_REGION: AWS region (or any region for non-AWS S3)
Query Parameters:
endpoint: S3 endpoint URLs3-force-path-style: Set to "true" to use path-style URLspart-size: Multipart upload part size in bytes (default: 10485760 = 10 MB, minimum: 5242880 = 5 MB)
For FTP servers:
STORAGE__URL=ftp://username:password@host:port/pathRequired for FTP:
username: FTP username (defaults to "anonymous" if not provided)password: FTP password (optional for anonymous)host: FTP server hostnameport: FTP port (defaults to 21)
For local or mounted filesystem storage:
STORAGE__URL=file:///absolute/path/to/backup/directoryExamples:
- Linux/macOS:
file:///var/backups/mariadb - Windows:
file://C:/backups/mariadb - Docker volume:
file:///data/backups
The backup system supports client-side encryption using AES-256 in Galois/Counter Mode (GCM) to ensure your database backups remain confidential and secure. This method provides both confidentiality and integrity verification.
Features:
- 256-bit key strength
- Authenticated encryption with additional data (AEAD)
- Automatic nonce generation for each backup
Configuration:
# base64-encoded encryption key
ENCRYPTION__KEY=Av2cfWJ3enCHTyzPdzowfAXshvJtbEsvwgPjV46wnjc=- Never commit encryption keys to version control
- Store keys in secure environment variables or dedicated secret management systems
- Implement proper access controls for key storage
Generate secure encryption keys using cryptographically secure methods:
# Generate a 32-byte (256-bit) key for AES256-GCM
openssl rand -base64 32
# Alternative method using /dev/urandom
head -c 32 /dev/urandom | base64- systemd Service Example: examples/systemd-service
- Docker Swarm CRON Example: examples/docker-cron-backup
- Simple CRON Example: examples/simple-cron-backup
- Advanced CRON Example: examples/advanced-cron-backup
- Encryption Example: examples/encryption-example
We welcome contributions! Please follow these steps:
- 🍴 Fork the repository
- 🌿 Create a feature branch:
git checkout -b feat/amazing-feature - 💾 Commit changes:
git commit -m 'Add amazing feature' - 🚀 Push to branch:
git push origin feat/amazing-feature - 🔀 Create a Pull Request
A big thank you to everyone who has contributed to this project!
See the full CONTRIBUTORS.md file for more information.
Apache 2.0 - See LICENSE for details.
💡 Need Help? Open an issue for support.