CRITICAL Security Fixes: - Add command injection protection with whitelist validation - Implement robust SSL/TLS certificate handling and validation - Add backup verification with SHA256 checksums and content validation - Implement atomic backup operations with proper cleanup - Create comprehensive security documentation Security Improvements: - Enhanced backup_command.rb with command sanitization and whitelisting - Added SSL certificate expiration checks and key matching validation - Implemented atomic file operations to prevent backup corruption - Added backup metadata storage for integrity tracking - Created SECURITY.md with Docker socket security guidance Testing Updates: - Added comprehensive security tests for command injection prevention - Updated SSL tests with proper certificate validation - Enhanced PostgreSQL alias method test coverage (100% coverage achieved) - Maintained 94.94% overall line coverage Documentation Updates: - Updated README.md with security warnings and test coverage information - Updated TODO.md marking all critical security items as completed - Enhanced TESTING.md and CLAUDE.md with current coverage metrics - Added comprehensive SECURITY.md with deployment best practices 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
208 lines
No EOL
6.2 KiB
Markdown
208 lines
No EOL
6.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
Baktainer is a Ruby-based Docker container database backup utility that automatically discovers and backs up databases using Docker labels. It supports MySQL, MariaDB, PostgreSQL, and SQLite databases.
|
|
|
|
## Development Commands
|
|
|
|
### Build and Run
|
|
```bash
|
|
# Build Docker image locally
|
|
docker build -t baktainer:local .
|
|
|
|
# Run with docker-compose
|
|
docker-compose up -d
|
|
|
|
# Run directly with Ruby (for development)
|
|
cd app && bundle install
|
|
bundle exec ruby app.rb
|
|
|
|
# Run backup immediately (bypasses cron schedule)
|
|
cd app && bundle exec ruby app.rb --now
|
|
```
|
|
|
|
### Dependency Management
|
|
```bash
|
|
cd app
|
|
bundle install # Install dependencies
|
|
bundle update # Update dependencies
|
|
bundle exec <command> # Run commands with bundled gems
|
|
```
|
|
|
|
### Testing Commands
|
|
```bash
|
|
cd app
|
|
|
|
# Quick unit tests
|
|
bin/test
|
|
bundle exec rspec spec/unit/
|
|
|
|
# All tests with coverage
|
|
bin/test --all --coverage
|
|
COVERAGE=true bundle exec rspec
|
|
|
|
# Integration tests (requires Docker)
|
|
bin/test --integration --setup --cleanup
|
|
bundle exec rspec spec/integration/
|
|
|
|
# Using Rake tasks
|
|
rake spec # Unit tests
|
|
rake integration # Integration tests
|
|
rake test_full # Full suite with setup/cleanup
|
|
rake coverage # Tests with coverage
|
|
rake coverage_report # Open coverage report
|
|
```
|
|
|
|
### Test Coverage
|
|
Current test coverage: **94.94% line coverage** (150/158 lines), **71.11% branch coverage** (32/45 branches)
|
|
- 66 test examples covering all major functionality
|
|
- Unit tests for all database engines, container discovery, and backup workflows
|
|
- Integration tests with mocked Docker API calls
|
|
- Coverage report available at `coverage/index.html` after running tests with `COVERAGE=true`
|
|
|
|
### Docker Commands
|
|
```bash
|
|
# View logs
|
|
docker logs baktainer
|
|
|
|
# Restart container
|
|
docker restart baktainer
|
|
|
|
# Check running containers with baktainer labels
|
|
docker ps --filter "label=baktainer.backup=true"
|
|
```
|
|
|
|
## Architecture Overview
|
|
|
|
### Core Components
|
|
|
|
1. **Runner (`app/lib/baktainer.rb`)**
|
|
- Main orchestrator class `Baktainer::Runner`
|
|
- Manages Docker connection (socket/TCP/SSL)
|
|
- Implements cron-based scheduling using `cron_calc` gem
|
|
- Uses thread pool for concurrent backups
|
|
|
|
2. **Container Discovery (`app/lib/baktainer/container.rb`)**
|
|
- `Baktainer::Containers.find_all` discovers containers with `baktainer.backup=true` label
|
|
- Parses Docker labels to extract database configuration
|
|
- Creates appropriate backup command objects
|
|
|
|
3. **Database Backup Implementations**
|
|
- `app/lib/baktainer/mysql.rb` - MySQL/MariaDB backups using `mysqldump`
|
|
- `app/lib/baktainer/postgres.rb` - PostgreSQL backups using `pg_dump`
|
|
- `app/lib/baktainer/sqlite.rb` - SQLite backups using file copy
|
|
- Each implements a common interface with `#backup` method
|
|
|
|
4. **Backup Command (`app/lib/baktainer/backup_command.rb`)**
|
|
- Abstract base class for database-specific backup implementations
|
|
- Handles file organization: `/backups/<date>/<name>-<timestamp>.sql`
|
|
- Manages Docker exec operations
|
|
|
|
### Threading Model
|
|
- Uses `concurrent-ruby` gem with `FixedThreadPool`
|
|
- Default 4 threads (configurable via `BT_THREADS`)
|
|
- Each backup runs in separate thread
|
|
- Thread-safe logging via custom Logger wrapper
|
|
|
|
### Docker Integration
|
|
- Connects via Docker socket (`/var/run/docker.sock`) or TCP
|
|
- Supports SSL/TLS for remote Docker API
|
|
- Uses `docker-api` gem for container operations
|
|
- Executes backup commands inside containers via `docker exec`
|
|
|
|
## Environment Variables
|
|
|
|
Required configuration through environment variables:
|
|
|
|
- `BT_DOCKER_URL` - Docker API endpoint (default: `unix:///var/run/docker.sock`)
|
|
- `BT_CRON` - Cron expression for backup schedule (default: `0 0 * * *`)
|
|
- `BT_THREADS` - Thread pool size (default: 4)
|
|
- `BT_LOG_LEVEL` - Logging level: debug/info/warn/error (default: info)
|
|
- `BT_BACKUP_DIR` - Backup storage directory (default: `/backups`)
|
|
- `BT_SSL` - Enable SSL for Docker API (default: false)
|
|
- `BT_CA` - CA certificate for SSL
|
|
- `BT_CERT` - Client certificate for SSL
|
|
- `BT_KEY` - Client key for SSL
|
|
|
|
## Docker Label Configuration
|
|
|
|
Containers must have these labels for backup:
|
|
|
|
```yaml
|
|
labels:
|
|
- baktainer.backup=true # Required: Enable backup
|
|
- baktainer.db.engine=<engine> # Required: mysql/postgres/sqlite
|
|
- baktainer.db.name=<database> # Required: Database name
|
|
- baktainer.db.user=<username> # Required for MySQL/PostgreSQL
|
|
- baktainer.db.password=<pass> # Required for MySQL/PostgreSQL
|
|
- baktainer.name=<app_name> # Optional: Custom backup filename
|
|
```
|
|
|
|
## File Organization
|
|
|
|
Backups are stored as:
|
|
```
|
|
/backups/
|
|
├── YYYY-MM-DD/
|
|
│ ├── <name>-<unix_timestamp>.sql
|
|
│ └── <name>-<unix_timestamp>.sql
|
|
```
|
|
|
|
## Adding New Database Support
|
|
|
|
1. Create new file in `app/lib/baktainer/<database>.rb`
|
|
2. Inherit from `Baktainer::BackupCommand`
|
|
3. Implement `#backup` method
|
|
4. Add engine mapping in `container.rb`
|
|
5. Update README.md with new engine documentation
|
|
|
|
## Deployment
|
|
|
|
GitHub Actions automatically builds and pushes to Docker Hub on:
|
|
- Push to `main` branch → `jamez001/baktainer:latest`
|
|
- Tag push `v*.*.*` → `jamez001/baktainer:<version>`
|
|
|
|
Manual deployment:
|
|
```bash
|
|
docker build -t jamez001/baktainer:latest .
|
|
docker push jamez001/baktainer:latest
|
|
```
|
|
|
|
## Common Development Tasks
|
|
|
|
### Testing Database Backups
|
|
```bash
|
|
# Create test container with labels
|
|
docker run -d \
|
|
--name test-postgres \
|
|
-e POSTGRES_PASSWORD=testpass \
|
|
-l baktainer.backup=true \
|
|
-l baktainer.db.engine=postgres \
|
|
-l baktainer.db.name=testdb \
|
|
-l baktainer.db.user=postgres \
|
|
-l baktainer.db.password=testpass \
|
|
postgres:17
|
|
|
|
# Run backup immediately
|
|
cd app && bundle exec ruby app.rb --now
|
|
|
|
# Check backup file
|
|
ls -la backups/$(date +%Y-%m-%d)/
|
|
```
|
|
|
|
### Debugging
|
|
- Set `BT_LOG_LEVEL=debug` for verbose logging
|
|
- Check container logs: `docker logs baktainer`
|
|
- Verify Docker socket permissions
|
|
- Test Docker connection: `docker ps` from inside container
|
|
|
|
## Code Conventions
|
|
|
|
- Ruby 3.3 with frozen string literals
|
|
- Module namespacing under `Baktainer`
|
|
- Logger instance available as `LOGGER`
|
|
- Error handling with logged stack traces in debug mode
|
|
- No test framework currently implemented |