baktainer/CLAUDE.md
James Paterni d14b8a2e76
Some checks are pending
Test and Build Docker Image / test (push) Waiting to run
Test and Build Docker Image / build (push) Blocked by required conditions
Implement comprehensive security fixes and enhancements
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>
2025-07-14 10:19:18 -04:00

6.2 KiB

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

# 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

cd app
bundle install              # Install dependencies
bundle update              # Update dependencies
bundle exec <command>      # Run commands with bundled gems

Testing Commands

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

# 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:

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:

docker build -t jamez001/baktainer:latest .
docker push jamez001/baktainer:latest

Common Development Tasks

Testing Database Backups

# 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