Skip to main content

DuplicAid

PyPI version Tests Python versions Code style: black Ruff

DuplicAid is a CLI tool for managing PostgreSQL backups using SQL dumps. It provides a unified interface for creating, listing, and restoring backups from PostgreSQL instances running in Docker containers.

The tool supports both local and remote execution modes.

⚠️ The package depends on tiredofit/docker-db-backup:4.1.21 for backup operations.

Features

  • SQL Dumps: Create and restore database backups using pg_dump/pg_restore
  • S3 Integration: Store and retrieve backups from S3-compatible storage
  • Dual Execution Modes: Manage backups locally or on remote servers via SSH

Installation

Install duplicaid using uv:

# Install from PyPI
uv add duplicaid

# Or install from source
git clone <repository-url>
cd duplicaid
uv sync --extra dev

Configuration

Duplicaid stores configuration in .duplicaid.yml in your current working directory by default. You can specify a different location using the --config flag.

Execution Modes

Remote Mode (default):

  • Manages PostgreSQL containers on a remote server via SSH
  • Requires SSH key authentication
  • All Docker commands executed on remote server

Local Mode:

  • Manages PostgreSQL containers on the local machine
  • No SSH connection required
  • Docker commands executed locally

Setup

Initialize configuration interactively:

duplicaid config init

Configuration Options

  • Execution Mode: remote or local
  • Remote Server (remote mode only): SSH connection details (host, user, port, key path)
  • Container Names: PostgreSQL and backup container names
  • PostgreSQL Credentials: Database user and password
  • Paths: Docker Compose file location

Example Configurations

Remote Mode:

execution_mode: remote
remote:
  host: your-server.example.com
  user: root
  port: 22
  ssh_key_path: /home/user/.ssh/id_rsa
containers:
  postgres: postgres
  backup: db-backup
postgres:
  user: postgres
  password: your_secure_password
  host: postgres
s3:
  endpoint: https://s3.amazonaws.com
  bucket: my-backups
  path: postgres/backups
  # access_key and secret_key can be set here or via env vars:
  # AWS_ACCESS_KEY_ID / S3_ACCESS_KEY
  # AWS_SECRET_ACCESS_KEY / S3_SECRET_KEY
paths:
  docker_compose: /home/user/postgres/docker-compose.yml
databases:
  - myapp
  - analytics

Local Mode:

execution_mode: local
containers:
  postgres: postgres
  backup: db-backup
postgres:
  user: postgres
  password: your_secure_password
  host: postgres
s3:
  endpoint: http://localhost:9000
  bucket: my-backups
  path: postgres/backups
paths:
  docker_compose: /home/user/postgres/docker-compose.yml

S3 Credentials:

S3 credentials can be configured in two ways:

  1. In config file (less secure):

    s3:
      access_key: YOUR_ACCESS_KEY
      secret_key: YOUR_SECRET_KEY
    
  2. Via environment variables (recommended):

    export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY
    export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
    # or
    export S3_ACCESS_KEY=YOUR_ACCESS_KEY
    export S3_SECRET_KEY=YOUR_SECRET_KEY
    

Quick Start

  1. Initialize Configuration:

    duplicaid config init
    
  2. Check Status:

    duplicaid status
    
  3. Create a Backup:

    duplicaid backup create
    
  4. List Backups:

    duplicaid list backups
    
  5. Restore a Backup:

    duplicaid restore mydb backup_file.sql.bz2
    

Backup Operations

Creating Backups

  • Storage: S3-compatible storage (compressed with bzip2)
  • Scope: All configured databases backed up automatically
  • Format: pgsql_hostname_database_YYYYMMDD-HHMMSS.sql.bz2

Listing Backups

Backups can be listed from:

  • S3-compatible storage (if configured)
  • Local backup directory (fallback)

Restoring Backups

  • Source: Automatically downloads from S3 if not found locally
  • Scope: Database-specific restoration
  • Compatibility: Works across PostgreSQL versions

Requirements

Common Requirements

  • Python 3.12+
  • Docker and Docker Compose
  • PostgreSQL container
  • tiredofit/db-backup container for backup operations

Remote Mode Additional Requirements

  • SSH access to remote server
  • SSH key authentication configured

Local Mode Additional Requirements

  • Docker daemon running locally
  • Access to local Docker socket

Development

Setup

  1. Clone and setup:

    git clone <repository-url>
    cd duplicaid
    uv sync --extra dev
    
  2. Install pre-commit hooks:

    uv run pre-commit install
    
  3. Run tests:

    uv run pytest
    

Project Structure

duplicaid/
├── pyproject.toml          # Project configuration and dependencies
├── README.md               # This file
├── src/
│   └── duplicaid/          # Main package
│       ├── __init__.py
│       ├── cli.py          # CLI interface
│       ├── config.py       # Configuration management
│       ├── backup.py       # Backup operations
│       ├── ssh.py          # SSH connectivity
│       ├── executor.py     # Command execution
│       ├── discovery.py    # Database discovery
│       └── local.py        # Local operations
└── tests/                  # Test suite
    ├── conftest.py
    ├── test_cli.py
    ├── test_config.py
    ├── test_integration.py
    └── test_local_executor.py

Testing

The test suite includes:

  • Unit tests: Test individual components
  • Integration tests: Test component interactions
  • CLI tests: Test command-line interface

Run specific test types:

# All tests
uv run pytest

# Unit tests only
uv run pytest -k "not integration"

# Integration tests only
uv run pytest -m integration

# With coverage
uv run pytest --cov=duplicaid

Development Workflow

This project uses automated releases with semantic commits.

Quick Start

# 1. Create feature branch
git checkout -b feat/new-feature

# 2. Push and create PR
git push origin feat/new-feature

# 3. Merge PR → Auto-release to PyPI

Semantic Commits

git commit -m "fix: resolve timeout"      # → patch release
git commit -m "feat: add encryption"      # → minor release
git commit -m "feat!: redesign API"       # → major release

Automation

  • PRs: Auto-test, lint, format
  • Main branch: Auto-version, auto-publish to PyPI
  • Pre-commit: Enforce quality and commit format

Building and Publishing

# Manual build (for testing)
uv build

# Automated publishing (via GitHub Actions)
# → Happens automatically on main branch pushes
# → No manual PyPI uploads needed

# Emergency manual publish (not recommended)
uv publish

Metadata

Release files for duplicaid 4.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for duplicaid 4.3.0
File Size Uploaded Provenance Actions
duplicaid-4.3.0.tar.gz 78.9 kB With provenance Details for duplicaid-4.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for duplicaid 4.3.0
File Interpreter ABI Platform Actions
duplicaid-4.3.0-py3-none-any.whl Python 3 none any Details for duplicaid-4.3.0-py3-none-any.whl

Total release size: 96.5 kB

Release files / duplicaid-4.3.0.tar.gz

Download URL duplicaid-4.3.0.tar.gz
Size 78.9 kB
Tags Source
SHA-256 checksum
How to use checksums
49a8faced7678a3b5538985ff36b6a5469bd1099892d1bda4af02c54b074fba8
BLAKE2b-256 checksum
How to use checksums
b9509c15672f47e23921e2ab6e4e447ba7dfbe535d31128546539fc913db8ecb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 23, 2025.

Transparency log

Release files / duplicaid-4.3.0-py3-none-any.whl

Download URL duplicaid-4.3.0-py3-none-any.whl
Size 17.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9a786aba1aa7b3d514704b8dedbc5511fdaaf199864ea5df0583d52033ddeeb5
BLAKE2b-256 checksum
How to use checksums
63b2411eb1a8b69f0d3501a5582ccac66d209540b234ebb4d597fde1072464d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 23, 2025.

Transparency log

Security for duplicaid 4.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for duplicaid-4.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 23, 2025.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page