Skip to content

BfM is a comprehensive database migration system that supports multiple backends (PostgreSQL, GreptimeDB, Etcd) with HTTP and Protobuf APIs.

License

Notifications You must be signed in to change notification settings

toolsascode/bfm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

drawing

Backend For Migrations (BfM)

Go Reference Release CLI Release Docker codecov

BfM is a comprehensive database migration system that supports multiple backends (PostgreSQL, GreptimeDB, Etcd) with HTTP and Protobuf APIs.

Features

  • Multi-backend support: PostgreSQL, GreptimeDB, Etcd
  • HTTP REST API with authentication
  • Protobuf/gRPC API (requires code generation)
  • Migration state tracking in PostgreSQL/MySQL
  • Support for fixed and dynamic schemas
  • Embedded SQL scripts in Go files
  • Dry-run mode for testing
  • Idempotent migrations

Screenshots

Login Dashboard
Migration List Migration Details

Configuration

Environment Variables

Server Configuration

  • BFM_HTTP_PORT - HTTP server port (default: 7070)
  • BFM_GRPC_PORT - gRPC server port (default: 9090)
  • BFM_API_TOKEN - API token for authentication (required)

State Database Configuration

  • BFM_STATE_BACKEND - State database type: "postgresql" or "mysql" (default: "postgresql")
  • BFM_STATE_DB_HOST - State database host (default: "localhost")
  • BFM_STATE_DB_PORT - State database port (default: "5432")
  • BFM_STATE_DB_USERNAME - State database username (default: "postgres")
  • BFM_STATE_DB_PASSWORD - State database password (required)
  • BFM_STATE_DB_NAME - State database name (default: "migration_state")
  • BFM_STATE_SCHEMA - State database schema (default: "public")

Connection Configuration

For each connection (e.g., "core", "guard", "logs"), set:

  • {CONNECTION}_BACKEND - Backend type: "postgresql", "greptimedb", or "etcd"
  • {CONNECTION}_DB_HOST - Database host
  • {CONNECTION}_DB_PORT - Database port
  • {CONNECTION}_DB_USERNAME - Database username
  • {CONNECTION}_DB_PASSWORD - Database password
  • {CONNECTION}_DB_NAME - Database name
  • {CONNECTION}_SCHEMA - Schema name (optional, for fixed schemas)

Example:

CORE_BACKEND=postgresql
CORE_DB_HOST=localhost
CORE_DB_PORT=5432
CORE_DB_USERNAME=dashcloud
CORE_DB_PASSWORD=password
CORE_DB_NAME=dashcloud
CORE_SCHEMA=core

Development

For development environment setup, local development, and hot-reload configuration, see docs/DEVELOPMENT.md.

Production Deployment

Using Docker Image

BfM provides a production-ready Docker image that includes:

  • BfM API Server (HTTP on port 7070, gRPC on port 9090)
  • BfM Worker (optional, enabled via BFM_QUEUE_ENABLED=true)
  • BfM CLI tool (available inside container)
  • FfM Frontend (served via the API server)

Registry

Install from the command line

docker pull ghcr.io/toolsascode/bfm:latest

Building the Production Image

Build the standalone production Docker image:

# Using Makefile
make prod-build

# Or manually
docker build -t bfm-production:latest -f docker/Dockerfile .

Running with Docker Compose (Recommended)

The easiest way to run BfM in production is using the standalone Docker Compose configuration:

  1. Create environment file:
# Copy and edit environment variables
cp .env.example .env
  1. Configure environment variables:

Set the following required variables in your .env file:

# API Authentication
BFM_API_TOKEN=your-secure-random-token-here

# State Database
BFM_STATE_DB_PASSWORD=your-secure-password
BFM_STATE_DB_USERNAME=postgres

# Backend Connections (configure as needed)
CORE_DB_HOST=your-postgres-host
CORE_DB_PASSWORD=your-password
CORE_DB_NAME=your-database

# Optional: Queue Configuration
BFM_QUEUE_ENABLED=false  # Set to true to enable worker
  1. Start the service:
# Using Makefile
make standalone-up

# Or manually
docker compose -p bfm-standalone -f deploy/docker-compose.standalone.yml up -d --build
  1. Verify the service:
# Check health
curl http://localhost:7070/health

# Check service status
make standalone-ps
# or
docker compose -p bfm-standalone -f deploy/docker-compose.standalone.yml ps
  1. View logs:
# Using Makefile
make standalone-logs

# Or manually
docker compose -p bfm-standalone -f deploy/docker-compose.standalone.yml logs -f
  1. Stop the service:
# Using Makefile
make standalone-down

# Or manually
docker compose -p bfm-standalone -f deploy/docker-compose.standalone.yml down

Running with Docker Run

For more control, you can run the container directly:

docker run -d \
  --name bfm-production \
  -p 7070:7070 \
  -p 9090:9090 \
  -e BFM_API_TOKEN=your-secure-token \
  -e BFM_STATE_DB_HOST=postgres \
  -e BFM_STATE_DB_PASSWORD=your-password \
  -e CORE_DB_HOST=your-postgres-host \
  -e CORE_DB_PASSWORD=your-password \
  -v /path/to/your/sfm:/app/sfm:ro \
  bfm-production:latest

Accessing the Services

Once running, you can access:

Using the CLI Inside Container

The BfM CLI is available inside the production container:

# Execute CLI commands
docker exec bfm-standalone /app/bin/bfm-cli --help
docker exec bfm-standalone /app/bin/bfm-cli version

# Build migration files from SFM directory
docker exec bfm-standalone /app/bin/bfm-cli build /app/sfm --verbose

BfM CLI Tool

The BfM CLI is a command-line tool for generating migration .go files from SQL/JSON scripts.

How to install?

Go Install

go install github.com/toolsascode/bfm@latest

Via Github

curl -fLSs https://raw.githubusercontent.com/toolsascode/bfm/main/scripts/install.sh | bash

Or

curl -fLSs https://raw.githubusercontent.com/toolsascode/bfm/main/scripts/install.sh | sudo bash

Homebrew

brew install toolsascode/tap/bfm

Scoop

  1. Run PowerShell as an Administrator and:
  2. To add this bucket, run scoop bucket add bfm-scoop https://github.com/toolsascode/scoop-bucket.
  3. To install, do scoop install bfm.

Building the CLI

# Using Makefile
make build-cli

# Or manually
cd api && go build -o ../bfm-cli ./cmd/cli

CLI Commands

Version:

./bfm-cli version

Build Migration Files:

Generate .go files from migration scripts in the SFM directory:

# Basic usage
./bfm-cli build examples/sfm

# With verbose output
./bfm-cli build examples/sfm --verbose

# Dry run (show what would be generated)
./bfm-cli build examples/sfm --dry-run

# Custom output directory
./bfm-cli build examples/sfm --output /path/to/output

# Custom path
./bfm-cli build /path/to/sfm --verbose

SFM Directory Structure

The CLI expects migration scripts in the following structure:

{sfm_path}/
  {backend}/                    # The first folder after SfM is considered the backend.
    {connection}/               # The last folder will be considered a connection.
      {version}_{name}.up.sql
      {version}_{name}.down.sql
      # OR for etcd
      {version}_{name}.up.json
      {version}_{name}.down.json

Example:

examples/sfm/
  postgresql/
    core/
      20250101120000_create_users.up.sql
      20250101120000_create_users.down.sql
  greptimedb/
    logs/
      20250101120000_create_metrics.up.sql
      20250101120000_create_metrics.down.sql
  etcd/
    metadata/
      20250101120000_init_config.up.json
      20250101120000_init_config.down.json

The CLI will generate corresponding .go files that embed the SQL/JSON and register migrations in the global registry.

Using CLI in Production

In production environments, you can:

  1. Build migrations as part of CI/CD:
# In your build pipeline
./bfm-cli build /path/to/migrations --output /path/to/generated
go build -o bfm-server ./cmd/server
  1. Use in Docker builds:
# Copy migration scripts
COPY migrations/sfm /app/sfm

# Generate .go files
RUN /app/bin/bfm-cli build /app/sfm

# Build server with generated migrations
RUN go build -o bfm-server ./cmd/server
  1. Validate migrations before deployment:
# Dry run to check for errors
./bfm-cli build /path/to/migrations --dry-run --verbose

Production Best Practices

  1. Security:

    • Use strong, randomly generated API tokens
    • Store credentials in secret management systems (e.g., HashiCorp Vault, AWS Secrets Manager)
    • Enable TLS/HTTPS via reverse proxy (nginx, Traefik)
    • Restrict network access to BfM API
  2. High Availability:

    • Run multiple BfM instances behind a load balancer
    • Use PostgreSQL replication for state database
    • Implement distributed locking to prevent concurrent migrations
    • Monitor health endpoints
  3. Monitoring:

    • Set up health check monitoring (GET /health)
    • Collect logs via centralized logging (ELK, Loki, etc.)
    • Track migration execution metrics
    • Alert on migration failures
  4. Backup:

    • Regularly backup the state database
    • Version control all migration scripts
    • Test restore procedures
  5. Migration Management:

    • Always test migrations in staging first
    • Use dry-run mode before applying migrations
    • Keep migration scripts idempotent
    • Document complex migrations

See docs/DEPLOYMENT.md for more detailed deployment instructions.

Usage

OpenAPI Specification

BfM provides a complete OpenAPI v3.2.0 specification for the HTTP API. The specification is available at:

  • YAML format: http://localhost:7070/api/v1/openapi.yaml
  • JSON format: http://localhost:7070/api/v1/openapi.json

The OpenAPI specification includes:

  • Complete API endpoint documentation
  • Request/response schemas
  • Authentication requirements
  • Example requests and responses
  • Error response formats

You can use the OpenAPI spec with tools like:

Example: View OpenAPI spec in Swagger UI

# Using Docker
docker run -p 8080:8080 -e SWAGGER_JSON=/openapi.yaml -v $(pwd)/api/internal/api/http/openapi.yaml:/openapi.yaml swaggerapi/swagger-ui

# Or use online Swagger Editor
# Paste the content from http://localhost:7070/api/v1/openapi.yaml

HTTP API

Migrate Endpoint

POST /api/v1/migrate
Authorization: Bearer {BFM_API_TOKEN}
Content-Type: application/json

{
  "target": {
    "backend": "postgresql",
    "schema": "core",
    "tables": [],
    "version": "",
    "connection": "core"
  },
  "connection": "core",
  "schema": "core",
  "environment": "",
  "dry_run": false
}

Response:

{
  "success": true,
  "applied": ["core_users_20250101120000_create_users"],
  "skipped": [],
  "errors": []
}

Note: For complete API documentation, see the OpenAPI Specification section above.

Health Check

GET /health

Migration Scripts

Migration scripts are located in sfm/{backend}/{connection}/ and follow the naming convention: {version}_{name}.up.sql and {version}_{name}.down.sql

The BfM CLI generates corresponding .go files with the format {version}_{name}.go that:

  1. Embed SQL/JSON files using //go:embed
  2. Register themselves in the global registry via init()
  3. Include both up and down migrations

Example structure:

sfm/
  postgresql/
    core/
      20250101120000_create_users.up.sql
      20250101120000_create_users.down.sql
      20250101120000_create_users.go  # Generated by CLI
  greptimedb/
    logs/
      20250101120000_create_metrics.up.sql
      20250101120000_create_metrics.down.sql
      20250101120000_create_metrics.go  # Generated by CLI
  etcd/
    metadata/
      20250101120000_init_config.up.json
      20250101120000_init_config.down.json
      20250101120000_init_config.go  # Generated by CLI

Migration from Existing System

To migrate from the existing GORM AutoMigrate system:

  1. Extract table definitions from GORM models
  2. Create SQL migration scripts following the naming convention
  3. Place scripts in appropriate sfm/{backend}/{connection}/ directory
  4. Register migrations via init() functions
  5. Run migrations via HTTP API or Protobuf API

About

BfM is a comprehensive database migration system that supports multiple backends (PostgreSQL, GreptimeDB, Etcd) with HTTP and Protobuf APIs.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •