dbtote

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: MIT

README

dbtote

A cross-platform CLI tool for backing up and restoring databases, with compression, encryption at rest, and pluggable storage backends.

Full design: docs/SPEC.md.

Status

Phase 3: MySQL and PostgreSQL full backup/restore, local storage, gzip compression, age encryption, OS-keyring credentials, YAML config file with targets, test-connection, list, and CI/CD (gated releases, Docker image, keyless artifact signing, PR coverage comments).

Install

No tagged releases yet — versioned binaries land in Phase 3 once goreleaser is wired up. Until then, build from source:

git clone https://github.com/nweber23/dbtote.git
cd dbtote
go build -o bin/dbtote ./cmd/dbtote

Requires the mysqldump/mysql client binaries on PATH for MySQL targets, and pg_dump/pg_restore for PostgreSQL targets.

Quick start

  1. Store the database password once:

    dbtote secret set --target prod-mysql
    
  2. Run a backup:

    dbtote backup --target prod-mysql --host db.internal --user backup_svc --database app_production --output /var/backups/dbtote
    
  3. Encrypt backups at rest with age:

    age-keygen -o identity.txt   # prints the matching public key
    dbtote backup --target prod-mysql --host db.internal --user backup_svc --database app_production \
      --output /var/backups/dbtote --encrypt --recipient age1...
    
  4. Restore:

    dbtote restore --target prod-mysql --from /var/backups/dbtote/prod-mysql_full_....sql.gz.age \
      --host db.internal --user backup_svc --database app_production --decrypt-key identity.txt --yes
    

Config file

Instead of passing --host/--user/--database/etc. on every command, define targets once in a YAML config file. CLI flags always override the config for that run.

  1. Write a starter config:

    dbtote config init
    

    Prompts for a local storage path and writes $XDG_CONFIG_HOME/dbtote/config.yaml (or --config <path>).

  2. Add a target under targets:, e.g.:

    targets:
      prod-mysql:
        engine: mysql
        host: db1.internal
        port: 3306
        user: backup_svc
        database: app_production
        storage: local-main
    
  3. Validate the config — checks storage references, age recipient keys, cron expressions, and that every target's credential resolves (password_env or OS keyring), without connecting to any database:

    dbtote config validate
    
  4. Check connectivity and credentials for a specific target:

    dbtote test-connection --target prod-mysql
    
  5. List known backups:

    dbtote list
    dbtote list --target prod-mysql --since 24h
    dbtote list --json
    

With a config file in place, dbtote backup --target prod-mysql and dbtote restore --target prod-mysql --from <file> --yes resolve engine, host, port, user, database, storage, and encryption recipients from the target's config entry — pass any of --host/--user/--database/etc. explicitly to override just that field for one run.

PostgreSQL

Postgres is supported the same way MySQL is — set engine: postgres on a target. Requires the pg_dump and pg_restore client binaries on PATH.

Releasing

Pushing a v* tag triggers .github/workflows/release.yml: it gates on the full CI suite, then runs goreleaser to cross-compile binaries for linux/darwin/windows (amd64 + arm64, minus windows/arm64), checksum them, and publish a GitHub Release with an auto-generated changelog. Every release artifact is signed keylessly with cosign (Sigstore's OIDC-based flow — no signing key to manage), and a multi-arch Docker image is published to ghcr.io/nweber23/dbtote:

docker run --rm ghcr.io/nweber23/dbtote:latest backup --target prod-mysql --host db.internal --user backup_svc --database app_production --output /backups

Homebrew isn't set up yet — it needs a separate nweber23/homebrew-dbtote tap repository and a HOMEBREW_TAP_GITHUB_TOKEN secret, neither of which exist yet (link here once they do).

Development

make build   # compile ./cmd/dbtote
make test    # unit tests
make test-integration   # requires Docker; spins up real MySQL via testcontainers
make lint    # golangci-lint

Directories

Path Synopsis
cmd
dbtote command
internal
cli

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL