Changed both GitHub Actions and Forgejo workflows to only build and push Docker images to Docker Hub when a vX.X.X tag is pushed. Tests still run on all pushes to main and PRs. |
||
|---|---|---|
| .forgejo | ||
| .github/workflows | ||
| app | ||
| dev | ||
| hooks | ||
| screenshots | ||
| .dockerignore | ||
| .gitignore | ||
| .tool-versions | ||
| API_DOCUMENTATION.md | ||
| CHANGELOG.md | ||
| DEVELOPMENT.md | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| entrypoint.sh | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
| TODO.md | ||
| TROUBLESHOOTING.md | ||
baktainer
A fully featured backup/restoration system for Docker containers.
Features
- Database Support: MySQL, PostgreSQL, MongoDB, SQLite, and Redis databases
- Volume Backups: Backup Docker volumes and bind mounts alongside databases
- Authentication: Local user auth and OIDC/SSO support with role-based access
- Scheduled Backups: Run on a schedule using cron expressions
- Container Discovery: Define which databases to backup using docker labels
- Health Monitoring: Web dashboard and REST API for monitoring backup status
- Notifications: Multi-channel notifications (Slack, Discord, Teams, Email, Webhooks)
- Backup Rotation: Automatic cleanup based on age, count, or disk space
- Encryption: AES-256-GCM encryption for backup files
- Compression: Gzip compression to reduce backup file sizes
- Hooks: Pre/post backup scripts for custom workflows (S3, Restic, etc.)
- Performance Monitoring: Real-time metrics and performance alerts
- Persistent Storage: SQLite database for backup history and audit trails
- Auto-Import: Automatically imports existing backups on first start
- Label Validation: Schema-based validation with helpful error messages
- SSL/TLS Support: Secure Docker API connections
- High Performance: Multi-threaded backups with dynamic scaling
Installation
⚠️ Security Notice: Baktainer requires Docker socket access which grants significant privileges. Please review SECURITY.md for important security considerations and recommended mitigations.
services:
baktainer:
image: jamez001/baktainer:latest
container_name: baktainer
restart: unless-stopped
ports:
- "8080:8080" # Health check dashboard
volumes:
- ./backups:/backups
- ./data:/data # Persist backup history database
- /var/run/docker.sock:/var/run/docker.sock
environment:
- BT_CRON="0 0 * * *" # Backup every day at midnight
- BT_DOCKER_URL=unix:///var/run/docker.sock
- BT_THREADS=4
- BT_LOG_LEVEL=info
- BT_HEALTH_SERVER_ENABLED=true # Enable health check server
- BT_COMPRESS=true # Enable compression
- BT_ROTATION_ENABLED=true # Enable backup rotation
- BT_RETENTION_DAYS=30 # Keep backups for 30 days
# SSL Configuration (if using remote Docker API)
#- BT_SSL=true
#- BT_CA=/path/to/ca.pem
#- BT_CERT=/path/to/cert.pem
#- BT_KEY=/path/to/key.pem
# Notification Configuration
#- BT_NOTIFICATION_CHANNELS=slack,log
#- BT_SLACK_WEBHOOK_URL=https://hooks.slack.com/...
#- BT_NOTIFY_FAILURES=true
# Encryption Configuration
#- BT_ENCRYPTION_ENABLED=true
#- BT_ENCRYPTION_KEY=your-hex-key
For enhanced security, consider using a Docker socket proxy. See SECURITY.md for detailed security recommendations.
Environment Variables
Core Configuration
| Variable | Description | Default |
|---|---|---|
| BT_CRON | Cron expression for scheduling backups | 0 0 * * * |
| BT_THREADS | Number of threads to use for backups | 4 |
| BT_LOG_LEVEL | Log level (debug, info, warn, error) | info |
| BT_DOCKER_URL | Docker API URL | unix:///var/run/docker.sock |
| BT_BACKUP_DIR | Directory to store backups | /backups |
Backup Options
| Variable | Description | Default |
|---|---|---|
| BT_COMPRESS | Enable gzip compression for backups | true |
| BT_ROTATION_ENABLED | Enable automatic backup rotation | true |
| BT_RETENTION_DAYS | Days to keep backups (0 = unlimited) | 30 |
| BT_RETENTION_COUNT | Max backups per container (0 = unlimited) | 0 |
| BT_MIN_FREE_SPACE_GB | Minimum free space in GB | 10 |
| BT_BACKUP_TIMEOUT | Overall backup timeout in seconds | 1800 |
PostgreSQL-Specific Options
| Variable | Description | Default |
|---|---|---|
| BT_PG_LOCK_TIMEOUT | Lock wait timeout for pg_dump (e.g., '60s') | 60s |
| BT_PG_STATEMENT_TIMEOUT | Statement timeout for pg_dump (0 = disabled) | 0 |
| BT_PG_VERBOSE | Enable verbose output for debugging | false |
Health Monitoring
| Variable | Description | Default |
|---|---|---|
| BT_HEALTH_SERVER_ENABLED | Enable health check server | false |
| BT_HEALTH_PORT | Port for health check server | 8080 |
| BT_HEALTH_BIND | Bind address for health server | 0.0.0.0 |
SSL/TLS Configuration
| Variable | Description | Default |
|---|---|---|
| BT_SSL | Enable SSL for Docker connection | false |
| BT_CA | Path to CA certificate or certificate data | none |
| BT_CERT | Path to client certificate or certificate data | none |
| BT_KEY | Path to client key or key data | none |
Encryption
| Variable | Description | Default |
|---|---|---|
| BT_ENCRYPTION_ENABLED | Enable AES-256-GCM encryption | false |
| BT_ENCRYPTION_KEY | Encryption key (hex or base64) | none |
| BT_ENCRYPTION_KEY_FILE | Path to encryption key file | none |
| BT_ENCRYPTION_PASSPHRASE | Passphrase for key derivation | none |
Notifications
| Variable | Description | Default |
|---|---|---|
| BT_NOTIFICATION_CHANNELS | Comma-separated list of channels | log |
| BT_NOTIFY_SUCCESS | Notify on successful backups | false |
| BT_NOTIFY_FAILURES | Notify on backup failures | true |
| BT_NOTIFY_WARNINGS | Notify on warnings | true |
| BT_NOTIFY_HEALTH | Notify on health issues | true |
| BT_SLACK_WEBHOOK_URL | Slack webhook URL | none |
| BT_DISCORD_WEBHOOK_URL | Discord webhook URL | none |
| BT_TEAMS_WEBHOOK_URL | Microsoft Teams webhook URL | none |
| BT_WEBHOOK_URL | Generic webhook URL | none |
Authentication
| Variable | Description | Default |
|---|---|---|
| BT_AUTH_ENABLED | Enable authentication for dashboard | true |
| BT_AUTH_SECRET | Secret key for session signing (auto-generated if not set) | auto |
| BT_DB_PATH | Path to SQLite database | /data/baktainer.db |
| BT_SESSION_TIMEOUT | Session timeout in seconds | 86400 (24h) |
| BT_PASSWORD_MIN_LENGTH | Minimum password length | 12 |
| BT_MAX_LOGIN_ATTEMPTS | Max failed logins before lockout | 5 |
| BT_LOCKOUT_DURATION | Lockout duration in seconds | 900 (15min) |
OIDC/SSO (Optional)
| Variable | Description | Default |
|---|---|---|
| BT_OIDC_ENABLED | Enable OIDC authentication | false |
| BT_OIDC_ISSUER | OIDC issuer URL | none |
| BT_OIDC_CLIENT_ID | OIDC client ID | none |
| BT_OIDC_CLIENT_SECRET | OIDC client secret | none |
| BT_OIDC_REDIRECT_URI | Callback URL for OIDC | none |
| BT_OIDC_ADMIN_GROUP | OIDC group that grants admin role | none |
Hooks
| Variable | Description | Default |
|---|---|---|
| BT_HOOKS_ENABLED | Enable pre/post backup hooks | true |
| BT_HOOKS_DIR | Directory containing hook scripts | /hooks |
Usage
Basic Backup Operation
Add labels to your docker containers to specify which databases to backup.
services:
db:
image: postgres:17
container_name: my-db
restart: unless-stopped
volumes:
- db:/var/lib/postgresql/data
environment:
POSTGRES_DB: "${DB_BASE:-database}"
POSTGRES_USER: "${DB_USER:-user}"
POSTGRES_PASSWORD: "${DB_PASSWORD:-StrongPassword}"
labels:
- baktainer.backup=true
- baktainer.db.engine=postgres
- baktainer.db.name=my-db
- baktainer.db.user=user
- baktainer.db.password=StrongPassword
- baktainer.name="MyApp"
Dry-Run Mode (Configuration Validation)
Before running actual backups, use dry-run mode to validate your configuration:
# Run dry-run mode to validate configuration
docker exec baktainer ruby app.rb --dry-run
# Or when starting a new container
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
jamez001/baktainer:latest \
ruby app.rb --dry-run
Dry-run mode will:
- Discover all containers with backup labels
- Validate label configuration for each container
- Check if containers are running
- Verify backup command availability (mysqldump, pg_dump, etc.)
- Simulate backup paths without creating files
- Report any configuration issues found
Example output:
============================================================
DRY-RUN MODE REPORT
============================================================
Discovered 3 containers for backup:
✓ mysql-prod: mysql backup
→ Would backup 'production_db' to: /backups/2025-01-12/mysql-prod-1736652000.sql
✓ postgres-app: postgres backup
→ Would backup 'app_db' to: /backups/2025-01-12/postgres-app-1736652000.sql
✗ redis-cache: redis backup
→ Issues found:
• Missing database user (baktainer.db.user label)
• Backup command 'redis-cli' not found in container
------------------------------------------------------------
Configuration validation: 2 passed, 1 failed
============================================================
Command-Line Options
# Show help
docker exec baktainer ruby app.rb --help
# Run backup immediately (bypass cron schedule)
docker exec baktainer ruby app.rb --now
# Validate configuration without performing backups
docker exec baktainer ruby app.rb --dry-run
# Import old .meta backup files into the database
docker exec baktainer ruby app.rb --import-backups [DIR]
Troubleshooting
Matrix/Synapse Database Backups Hanging
Large Matrix/Synapse databases may hang during backup due to:
- Long-running transactions blocking pg_dump
- Large database size exceeding timeout limits
- Active connections preventing table locks
Solutions:
- Increase the backup timeout:
BT_BACKUP_TIMEOUT=3600(1 hour) - Enable verbose logging:
BT_PG_VERBOSE=trueandBT_LOG_LEVEL=debug - Adjust lock timeout:
BT_PG_LOCK_TIMEOUT=120s(wait longer for locks) - Run backup during low-activity periods
- Monitor progress in logs - backups log every 100MB written
General Backup Issues
- Check container logs:
docker logs baktainer - Verify Docker socket permissions
- Test with dry-run:
docker exec baktainer ruby app.rb --dry-run - Check disk space in backup directory
- Ensure database credentials are correct
Docker Labels for Container Configuration
Required Labels
| Label | Description | Required For |
|---|---|---|
| baktainer.backup | Set to true to enable backup for this container |
All |
| baktainer.db.engine | Database engine: mysql, postgres, mongodb, sqlite, redis |
All |
| baktainer.db.name | Name of the database to backup (or database number 0-15 for Redis) | All except Redis |
| baktainer.db.user | Username for the database | MySQL, PostgreSQL, MongoDB, Redis (ACL) |
| baktainer.db.password | Password for the database | MySQL, PostgreSQL, MongoDB, Redis |
Optional Labels
| Label | Description | Default |
|---|---|---|
| baktainer.name | Application name for backup files | Database name |
| baktainer.compress | Enable compression for this container (true/false) |
BT_COMPRESS value |
| baktainer.encrypt | Enable encryption for this container (true/false) |
BT_ENCRYPTION_ENABLED value |
| baktainer.backup.priority | Backup priority: low, normal, high, critical |
normal |
| baktainer.backup.retention.days | Days to keep backups for this container | BT_RETENTION_DAYS value |
| baktainer.backup.retention.count | Max backups to keep for this container | BT_RETENTION_COUNT value |
Backup Files
The backup files will be stored in the directory specified by the BT_BACKUP_DIR environment variable. The files will be named according to the following format:
/backups/<date>/<db_name>-<timestamp>.sql.gz
Where <date> is the date of the backup ('YY-MM-DD' format) <db_name> is the name provided by baktainer.name, or the name of the database, <timestamp> is the unix timestamp of the backup.
By default, backups are compressed with gzip. To disable compression, set BT_COMPRESS=false or add baktainer.compress=false label to specific containers.
Health Monitoring & Dashboard
Baktainer includes a comprehensive health monitoring system with a web dashboard and REST API.
Accessing the Dashboard
When BT_HEALTH_SERVER_ENABLED=true, visit http://localhost:8080 for:
- Real-time backup status and metrics
- Container discovery and configuration
- Performance monitoring with auto-refresh
- System health checks and alerts
Health Check Endpoints
| Endpoint | Description |
|---|---|
GET / |
Interactive monitoring dashboard |
GET /health |
Health check (200 = healthy, 503 = unhealthy) |
GET /status |
Detailed system status and metrics |
GET /backups |
Backup history and statistics |
GET /containers |
Discovered containers with backup labels |
GET /config |
Configuration (credentials sanitized) |
GET /metrics |
Prometheus-format metrics |
Prometheus Integration
Use the /metrics endpoint to integrate with monitoring systems:
# Prometheus scrape config
scrape_configs:
- job_name: 'baktainer'
static_configs:
- targets: ['baktainer:8080']
metrics_path: '/metrics'
scrape_interval: 30s
Notifications
Configure multi-channel notifications for backup events:
Supported Channels
- Slack: Set
BT_SLACK_WEBHOOK_URL - Discord: Set
BT_DISCORD_WEBHOOK_URL - Microsoft Teams: Set
BT_TEAMS_WEBHOOK_URL - Generic Webhook: Set
BT_WEBHOOK_URL - Logs: Always available
Example Configuration
environment:
- BT_NOTIFICATION_CHANNELS=slack,log
- BT_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
- BT_NOTIFY_FAILURES=true
- BT_NOTIFY_SUCCESS=false
- BT_NOTIFY_WARNINGS=true
Backup Encryption
Secure your backups with AES-256-GCM encryption:
environment:
- BT_ENCRYPTION_ENABLED=true
- BT_ENCRYPTION_KEY=your-256-bit-hex-key
# Or use a key file:
# - BT_ENCRYPTION_KEY_FILE=/path/to/keyfile
# Or derive from passphrase:
# - BT_ENCRYPTION_PASSPHRASE=your-secure-passphrase
Encrypted files use .enc extension and include authentication data for integrity verification.
Backup Rotation & Cleanup
Automatic backup cleanup keeps your storage manageable:
Configuration Options
environment:
- BT_ROTATION_ENABLED=true # Enable automatic cleanup
- BT_RETENTION_DAYS=30 # Keep backups for 30 days
- BT_RETENTION_COUNT=0 # Max backups per container (0 = unlimited)
- BT_MIN_FREE_SPACE_GB=10 # Trigger cleanup when free space < 10GB
Per-Container Overrides
labels:
- baktainer.backup.retention.days=7 # Keep this container's backups for 7 days
- baktainer.backup.retention.count=5 # Keep max 5 backups for this container
Cleanup Behavior
- Time-based: Remove backups older than specified days
- Count-based: Keep only N most recent backups per container
- Space-based: Automatic cleanup when disk space is low
- Smart cleanup: Removes empty date directories after cleanup
Authentication
Baktainer includes a built-in authentication system to secure the dashboard and API.
First-Time Setup
On first start, you'll be redirected to a setup wizard to create the initial admin user. Access the dashboard at http://localhost:8080 and follow the prompts.
Local Authentication
Users are stored in the SQLite database with passwords hashed using Argon2id.
environment:
- BT_AUTH_ENABLED=true
- BT_PASSWORD_MIN_LENGTH=12
- BT_MAX_LOGIN_ATTEMPTS=5
- BT_LOCKOUT_DURATION=900
OIDC/SSO Integration
For enterprise environments, configure OIDC authentication:
environment:
- BT_OIDC_ENABLED=true
- BT_OIDC_ISSUER=https://your-idp.com
- BT_OIDC_CLIENT_ID=baktainer
- BT_OIDC_CLIENT_SECRET=your-secret
- BT_OIDC_REDIRECT_URI=http://localhost:8080/auth/callback
- BT_OIDC_ADMIN_GROUP=baktainer-admins
User Roles
| Role | Permissions |
|---|---|
admin |
Full access: manage users, delete backups, change settings |
operator |
Run backups, restore, view all data |
viewer |
Read-only access to dashboard and backup history |
User Management API
Admins can manage users through the REST API:
| Endpoint | Method | Description |
|---|---|---|
/api/users |
GET | List all users |
/api/users |
POST | Create a new user |
/api/users/:id |
GET | Get user details |
/api/users/:id |
PUT | Update user |
/api/users/:id |
DELETE | Delete user |
Creating a New User
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-H "Cookie: baktainer_session=YOUR_SESSION_TOKEN" \
-d '{
"username": "newuser",
"email": "user@example.com",
"password": "securepassword123",
"role": "operator"
}'
Listing Users
curl http://localhost:8080/api/users \
-H "Cookie: baktainer_session=YOUR_SESSION_TOKEN"
Updating a User
curl -X PUT http://localhost:8080/api/users/2 \
-H "Content-Type: application/json" \
-H "Cookie: baktainer_session=YOUR_SESSION_TOKEN" \
-d '{"role": "admin"}'
Deleting a User
curl -X DELETE http://localhost:8080/api/users/2 \
-H "Cookie: baktainer_session=YOUR_SESSION_TOKEN"
Note: The last admin user cannot be deleted. Admins cannot delete their own account.
Disabling Authentication
For development or internal networks:
environment:
- BT_AUTH_ENABLED=false
Volume Backups
Baktainer can backup Docker volumes and bind mounts, either standalone or alongside database backups.
Standalone Volume Backup
For containers that only need volume backups (no database):
services:
my-app:
image: my-app:latest
volumes:
- uploads:/app/uploads
- ./config:/app/config
labels:
- baktainer.backup=true
- baktainer.db.engine=volume
- baktainer.volumes.backup=true
- baktainer.name=my-app
Combined Mode (Database + Volumes)
Backup both the database and volumes for the same container:
services:
wordpress:
image: wordpress:latest
volumes:
- wp-content:/var/www/html/wp-content
labels:
- baktainer.backup=true
- baktainer.db.engine=mysql
- baktainer.db.name=wordpress
- baktainer.db.user=wp_user
- baktainer.db.password=secret
- baktainer.volumes.backup=true # Also backup volumes
How It Works
- Volumes and bind mounts are auto-detected from the container's Docker configuration
- Creates tar archives of volume contents using
docker cp - Supports compression (
.tar.gz) and encryption (.tar.gz.enc) tmpfsmounts are automatically skipped (ephemeral)
Redis Backups
Baktainer supports backing up Redis databases using RDB snapshots.
Basic Redis Backup
services:
redis:
image: redis:7
labels:
- baktainer.backup=true
- baktainer.db.engine=redis
- baktainer.name=my-redis
Redis with Password Authentication
services:
redis:
image: redis:7
command: redis-server --requirepass mysecretpassword
labels:
- baktainer.backup=true
- baktainer.db.engine=redis
- baktainer.db.password=mysecretpassword
- baktainer.name=my-redis
Redis with ACL Authentication (Redis 6+)
services:
redis:
image: redis:7
labels:
- baktainer.backup=true
- baktainer.db.engine=redis
- baktainer.db.user=myuser
- baktainer.db.password=mysecretpassword
- baktainer.name=my-redis
Redis with Specific Database Number
Redis supports 16 databases numbered 0-15 (default is 0):
labels:
- baktainer.backup=true
- baktainer.db.engine=redis
- baktainer.db.name=3
- baktainer.name=my-redis
How It Works
- Uses
redis-cli --rdbto stream an RDB snapshot - Supports both legacy password auth and ACL-based auth (Redis 6+)
- Backup files are binary RDB format (can be restored with
redis-cli --rdb) - Compatible with Redis 5.x, 6.x, and 7.x
Hooks
Run custom scripts before and after backups for workflows like offsite sync.
Hook Scripts
Place executable scripts in the hooks directory (default: /hooks):
/hooks/
├── pre-backup.sh # Runs before each backup
└── post-backup.sh # Runs after each backup
Environment Variables
Hooks receive context via environment variables:
| Variable | Description |
|---|---|
BAKTAINER_CONTAINER_NAME |
Name of the container being backed up |
BAKTAINER_BACKUP_FILE |
Full path to the backup file |
BAKTAINER_BACKUP_SIZE |
Size of backup in bytes |
BAKTAINER_BACKUP_STATUS |
success or failed |
BAKTAINER_ENGINE |
Database engine (mysql, postgres, etc.) |
BAKTAINER_TIMESTAMP |
Unix timestamp of backup |
Example: Sync to S3
#!/bin/bash
# /hooks/post-backup.sh
if [ "$BAKTAINER_BACKUP_STATUS" = "success" ]; then
aws s3 cp "$BAKTAINER_BACKUP_FILE" "s3://my-bucket/backups/"
fi
Example: Restic Backup
#!/bin/bash
# /hooks/post-backup.sh
if [ "$BAKTAINER_BACKUP_STATUS" = "success" ]; then
restic -r s3:s3.amazonaws.com/my-bucket backup "$BAKTAINER_BACKUP_FILE"
fi
Docker Compose Configuration
services:
baktainer:
image: jamez001/baktainer:latest
volumes:
- ./hooks:/hooks
environment:
- BT_HOOKS_ENABLED=true
- BT_HOOKS_DIR=/hooks
Importing Existing Backups
If you have existing backups from older versions of Baktainer (with .meta files), you can import them into the database to view them in the health dashboard and track history.
Import Command
# Import from default backup directory (/backups)
docker exec baktainer ruby app.rb --import-backups
# Import from a specific directory
docker exec baktainer ruby app.rb --import-backups /path/to/backups
# Short form
docker exec baktainer ruby app.rb -i /backups
What Gets Imported
The import scans for .meta files (JSON metadata files created alongside backup files) and imports:
- Container name
- Backup timestamp
- File size
- Backup file path
- Compression status
Example Output
{"severity":"INFO","message":"Importing backup metadata from: /backups"}
{"severity":"INFO","message":"Imported 42 backup records from meta files"}
{"severity":"INFO","message":"Successfully imported 42 backup records"}
Notes
- The import is idempotent - running it multiple times won't create duplicate records
- Corrupted or invalid
.metafiles are skipped with a warning - After import, backup history appears in the health dashboard at
/backups - The database is stored at
/data/baktainer.db(ensure/datais persisted with a volume)
Persisting the Database
To retain imported data and backup history across container restarts, mount the data directory:
services:
baktainer:
image: jamez001/baktainer:latest
volumes:
- ./backups:/backups
- ./data:/data # Persist backup history database
- /var/run/docker.sock:/var/run/docker.sock
Upgrading from v0.1.x
Breaking Changes in v0.2.0
- New volume mount required:
/datadirectory for persistent storage - Environment variable renamed:
BT_AUTH_DB_PATH→BT_DB_PATH - Database file renamed:
baktainer_auth.db→baktainer.db
Migration Steps
-
Update docker-compose.yml:
volumes: - ./backups:/backups - ./data:/data # ADD THIS LINE - /var/run/docker.sock:/var/run/docker.sock -
Rename environment variable (if customized):
# Old - BT_AUTH_DB_PATH=/custom/path/db.sqlite # New - BT_DB_PATH=/custom/path/db.sqlite -
Existing backups: On first start, Baktainer automatically imports existing backup files from your backup directory. No manual action required.
-
Existing database (if upgrading from auth preview):
mv ./data/baktainer_auth.db ./data/baktainer.db
Testing
The project includes comprehensive test coverage with both unit and integration tests.
Running Tests
# Run all tests
cd app && bundle exec rspec
# Run tests with coverage report
cd app && COVERAGE=true bundle exec rspec
# Run only unit tests
cd app && bundle exec rspec spec/unit/
# Run only integration tests (requires Docker)
cd app && bundle exec rspec spec/integration/
Test Coverage
- Line Coverage: 94.94% (150/158 lines)
- Branch Coverage: 71.11% (32/45 branches)
- Tests cover all database engines, container discovery, error handling, and backup workflows
- Integration tests validate full backup operations with real Docker containers
Test Commands
# Quick unit tests
bin/test
# All tests with coverage
bin/test --all --coverage
# Integration tests with setup/cleanup
bin/test --integration --setup --cleanup
Development Roadmap
✅ Completed Features
- Database Support: MySQL, PostgreSQL, MongoDB, SQLite, and Redis backups
- Volume Backups: Docker volumes and bind mount backups
- Authentication: Local users and OIDC/SSO integration
- Scheduling: Cron-based backup scheduling
- Container Discovery: Docker label-based configuration
- Docker Integration: Support for socket, TCP, SSL/TLS connections
- Compression: Gzip compression for backup files
- Health Monitoring: Web dashboard and REST API monitoring
- Notifications: Multi-channel notifications (Slack, Discord, Teams, Webhooks)
- Backup Rotation: Automatic cleanup based on age, count, and disk space
- Encryption: AES-256-GCM encryption for backup files
- Performance Monitoring: Real-time metrics and alerts
- Hooks: Pre/post backup scripts for custom workflows
- Persistent Storage: SQLite database for backup history
- Auto-Import: Automatic import of existing backups on first start
- Label Validation: Schema-based validation with helpful error messages
- High Performance: Multi-threaded backups with dynamic scaling
- Comprehensive Testing: 878 tests with high coverage
Development Environment
For developers and contributors, Baktainer includes a complete development environment with sample databases:
Quick Setup
# Set up development environment with sample databases
./dev/setup.sh
# Test dry-run mode with sample data
docker compose -f docker-compose.dev.yml exec baktainer-dev ruby app.rb --dry-run
# View health dashboard
open http://localhost:8080
What's Included
- Sample Databases: MySQL, PostgreSQL, and SQLite with realistic test data
- Health Dashboard: Real-time monitoring and metrics at http://localhost:8080
- Automated Testing: Containers configured for testing various scenarios
- Debug Logging: Full visibility into backup processes
- Error Testing: Intentionally misconfigured containers for testing error handling
Development Services
| Database | Port | Credentials | Purpose |
|---|---|---|---|
| MySQL | 3306 | dev_user/dev_password |
Primary MySQL testing |
| PostgreSQL | 5432 | dev_user/dev_password |
PostgreSQL backup testing |
| SQLite | - | File-based | SQLite backup testing |
| MySQL Secondary | 3307 | secondary_user/secondary_pass |
Multi-container testing |
Quick Commands
# Test dry-run validation
docker compose -f docker-compose.dev.yml exec baktainer-dev ruby app.rb --dry-run
# Run immediate backup
docker compose -f docker-compose.dev.yml exec baktainer-dev ruby app.rb --now
# View backup files
ls -la dev-backups/
# Clean up environment
./dev/teardown.sh
For detailed development instructions, see DEVELOPMENT.md.
🔄 In Progress
- Backup streaming for large databases
- Advanced retry strategies with exponential backoff
📋 Future Enhancements
- Configurable timeout limits for each backup
- Database-specific optimization settings
- Backup verification and integrity checking
- Multi-region backup replication
- Advanced alerting rules and thresholds
- Backup scheduling per container
