Sign inSign up

danielgtmn/docker-pg-backup

By danielgtmn

•Updated about 1 year ago

A modern REST API for PostgreSQL database backups to S3

Image
Developer tools
0

1.5K

danielgtmn/docker-pg-backup repository overview

⁠PostgreSQL Backup API

Docker Image TypeScript Fastify

A modern REST API for PostgreSQL database backups to S3-compatible storage (AWS S3, MinIO, DigitalOcean Spaces, etc.) with API key authentication, built with TypeScript and Fastify.

⁠🚀 Features

  • REST API - Simple HTTP endpoints for backup operations
  • S3-Compatible Storage - Support for AWS S3 and S3-compatible services (MinIO, DigitalOcean Spaces, etc.)
  • API Key Authentication - Secure access with API key authentication
  • TypeScript - Full type safety and excellent developer experience
  • OpenAPI/Swagger - Auto-generated API documentation
  • Health Checks - Built-in health monitoring
  • Docker Ready - Production-ready containerization
  • Backup Verification - Automatic verification of successful uploads
  • Compressed Backups - Automatic gzip compression

⁠📋 Prerequisites

  • Docker and Docker Compose
  • Node.js 18+ (for development)
  • S3-compatible storage (AWS S3, MinIO, DigitalOcean Spaces, etc.)
  • API key for authentication
  • PostgreSQL database connection details (provided per backup request)

⁠🏃 Quick Start

  1. Clone the repository

    git clone https://github.com/danielgtmn/docker-pg-backup.git
    cd docker-pg-backup
    
  2. Configure environment

    cp env.example .env
    # Edit .env with your storage configuration
    
  3. Start the API server

    docker-compose up -d
    
  4. Access the API

⁠🚀 CI/CD & Container Registry

This project uses GitHub Actions for automated CI/CD. Docker images are automatically built and published to the GitHub Container Registry (ghcr.io).

⁠Automated Builds
  • Push to main: Triggers full CI pipeline with container build and push
  • Pull Requests: Runs tests and linting without container push
  • Version Tags: Pushing v* tags creates versioned releases
⁠Using Published Images
# Latest version from main branch
docker pull ghcr.io/danielgtmn/docker-pg-backup:latest

# Specific version
docker pull ghcr.io/danielgtmn/docker-pg-backup:v1.0.0

# Commit-based version
docker pull ghcr.io/danielgtmn/docker-pg-backup:main-<commit-sha>
⁠Multi-Platform Support

Images are built for both linux/amd64 and linux/arm64 architectures.

⁠🔧 Configuration

Create a .env file based on env.example:

# API Configuration
NODE_ENV=production
PORT=3000
HOST=0.0.0.0

# API Authentication (required)
API_KEY=your-secure-api-key-here

# PostgreSQL Connection String (optional - provided per backup request)
# DATABASE_URL=postgresql://username:password@hostname:port/database

# ================= AWS S3 Storage =================
S3_BUCKET=my-backup-bucket
S3_PREFIX=postgres-backups
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key

# ================= MinIO / Custom S3 =================
# S3_ENDPOINT=https://minio.example.com:9000
# S3_BUCKET=my-backup-bucket
# S3_PREFIX=postgres-backups
# AWS_ACCESS_KEY_ID=minio-access-key
# AWS_SECRET_ACCESS_KEY=minio-secret-key

# ================= DigitalOcean Spaces =================
# S3_ENDPOINT=https://fra1.digitaloceanspaces.com
# S3_BUCKET=my-spaces-bucket
# S3_PREFIX=postgres-backups
# AWS_REGION=fra1
# AWS_ACCESS_KEY_ID=spaces-access-key
# AWS_SECRET_ACCESS_KEY=spaces-secret-key

⁠☁️ S3-Compatible Storage Support

This API supports various S3-compatible storage services:

⁠AWS S3 (Standard)
S3_ENDPOINT=               # (optional, uses AWS default)
S3_BUCKET=my-bucket
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
⁠MinIO (Self-hosted S3)
S3_ENDPOINT=https://minio.example.com:9000
S3_BUCKET=my-bucket
AWS_ACCESS_KEY_ID=minio-user
AWS_SECRET_ACCESS_KEY=minio-password
⁠DigitalOcean Spaces
S3_ENDPOINT=https://fra1.digitaloceanspaces.com
S3_BUCKET=my-spaces-bucket
AWS_REGION=fra1
AWS_ACCESS_KEY_ID=spaces-key
AWS_SECRET_ACCESS_KEY=spaces-secret
⁠Other S3-compatible services
  • Linode Object Storage: S3_ENDPOINT=https://us-east-1.linodeobjects.com
  • Wasabi: S3_ENDPOINT=https://s3.wasabisys.com
  • Backblaze B2: S3_ENDPOINT=https://s3.us-west-002.backblazeb2.com

⁠📡 API Versioning

This API uses semantic versioning for all endpoints to ensure backward compatibility and smooth upgrades.

⁠Version Strategy
  • Current Version: v1 (stable)
  • Version Format: /v{number}/api/{endpoint}
  • Backward Compatibility: Legacy /api/* routes are automatically redirected to /v1/api/*
  • Deprecation Policy: Older versions are supported for 12 months after new version release
⁠Supported API Versions
VersionStatusRelease DateDeprecation DateSunset Date
v1Current2024-01-01--
⁠Versioned API Endpoints

Note: All API endpoints require authentication via API key in the Authorization header.

⁠Version 1 (Current)
# Create Backup
POST /v1/api/backup
Authorization: Bearer your-api-key-here
Content-Type: application/json

{
  "databaseUrl": "postgresql://user:pass@host:5432/mydb",
  "backupName": "my-backup.sql.gz"  // optional
}

# List Backups
GET /v1/api/backups?limit=10&prefix=my-backups

# Health Check
GET /v1/api/health

# Configuration Info
GET /v1/api/config
⁠Legacy Compatibility (Automatic Redirect)

The following legacy routes are automatically redirected to versioned endpoints:

  • /api/backup → /v1/api/backup
  • /api/backups → /v1/api/backups
  • /api/health → /v1/api/health
  • /api/config → /v1/api/config
⁠📋 Interactive API Documentation

Visit http://localhost:3000/docs for the complete interactive Swagger documentation with:

  • ✅ Detailed request/response schemas
  • ✅ Schema validation details
  • ✅ Try-it-out functionality
  • ✅ Authentication setup
  • ✅ Version-specific documentation
⁠Migration Guidelines
⁠Upgrading from Legacy API

If you're currently using the legacy /api/* endpoints:

  1. No immediate action required - Legacy routes still work via automatic redirects
  2. Update your clients to use versioned endpoints (/v1/api/*) for better performance
  3. Test your integration with versioned endpoints in a staging environment
  4. Update your client code to use the new endpoints before legacy deprecation
⁠Example Migration

Before (Legacy):

curl -X POST http://localhost:3000/api/backup \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"databaseUrl": "postgresql://..."}'

After (Versioned):

curl -X POST http://localhost:3000/v1/api/backup \
  -H "Authorization: Bearer your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"databaseUrl": "postgresql://..."}'
⁠Deprecation and Sunset Policy
  1. New Version Release: When a new API version is released, the previous version enters "deprecated" status
  2. Deprecation Period: Deprecated versions are supported for 12 months with full functionality
  3. Sunset Date: After 12 months, deprecated versions are removed from the API
  4. Communication: Version changes are communicated via:
    • GitHub release notes
    • API response headers (X-API-Version, X-Deprecation-Warning)
    • Updated documentation
⁠Version Headers

API responses include version information in headers:

X-API-Version: v1
X-API-Current-Version: v1
X-API-Supported-Versions: v1

Deprecated endpoints include additional headers:

X-Deprecation-Warning: "API version v1 is deprecated. Please migrate to v2"
X-Sunset-Date: "2025-01-01T00:00:00Z"

Required headers:

  • Authorization: Bearer <your-api-key>
  • Content-Type: application/json

Required fields:

  • databaseUrl: PostgreSQL connection string (must start with postgresql://)

Optional fields:

  • backupName: Custom backup filename (defaults to timestamp)

Response:

{
  "success": true,
  "data": {
    "backupPath": "s3://my-backup-bucket/postgres-backups/20241201_120000_backup.sql.gz",
    "fileSize": 1048576,
    "duration": 2500,
    "timestamp": "2024-12-01T12:00:00.000Z"
  }
}
⁠List Backups
GET /v1/api/backups?limit=10&prefix=my-backups
⁠Legacy Endpoint (Auto-redirects to versioned)
GET /api/backups?limit=10&prefix=my-backups
⁠Health Check
GET /v1/api/health
⁠Legacy Endpoint (Auto-redirects to versioned)
GET /api/health
⁠Configuration Info
GET /v1/api/config
Authorization: Bearer your-api-key-here
⁠Legacy Endpoint (Auto-redirects to versioned)
GET /api/config
Authorization: Bearer your-api-key-here

⁠🐳 Docker Usage

⁠Development
# Build and run
docker-compose up --build

# Run in background
docker-compose up -d

# View logs
docker-compose logs -f postgres-backup-api

# Stop
docker-compose down
⁠Production
# Build for production
docker build -t postgres-backup-api .

# Run with .env file (recommended)
docker run -d \
  --name postgres-backup-api \
  --env-file .env \
  -p 3000:3000 \
  postgres-backup-api

# Or run with manual environment variables
docker run -d \
  --name postgres-backup-api \
  -p 3000:3000 \
  -e S3_BUCKET="my-bucket" \
  -e AWS_ACCESS_KEY_ID="..." \
  -e AWS_SECRET_ACCESS_KEY="..." \
  -e API_KEY="your-secure-api-key" \
  postgres-backup-api

⁠🔒 Security

  • Environment Variables - Never commit sensitive credentials
  • Non-root Container - Runs as limited user
  • CORS Configured - Properly configured cross-origin requests
  • Input Validation - Zod schema validation for all inputs
  • Error Handling - Graceful error responses without information leakage

⁠🏗️ Development

# Install dependencies
pnpm install

# Development mode with hot reload
pnpm dev

# Build for production
pnpm build

# Run tests
pnpm test

# Lint code
pnpm lint

⁠📚 API Documentation

When running, visit http://localhost:3000/docs⁠ for interactive API documentation with:

  • Request/response schemas
  • Example requests
  • Authentication details
  • Error codes

⁠🔧 Supported Storage Backends

StorageConfigurationVerificationNotes
AWS S3S3_BUCKET, AWS_ACCESS_KEY_ID✅ HeadObjectMost common choice
Google Cloud StorageGCS_BUCKET, GOOGLE_APPLICATION_CREDENTIALS✅ File existsRequires service account
Azure Blob StorageAZURE_ACCOUNT, AZURE_CONTAINER✅ Blob existsRequires storage account
Local FilesystemBACKUP_DIR✅ File existsFor development/testing

⁠🚨 Error Handling

The API returns structured error responses:

{
  "success": false,
  "error": "Validation failed",
  "details": ["databaseUrl is required"]
}

Common HTTP status codes:

  • 200 - Success
  • 400 - Bad Request (validation errors)
  • 500 - Internal Server Error

⁠📊 Monitoring

  • Health check endpoint at /v1/api/health (versioned) or /api/health (legacy, auto-redirects)
  • Detailed logging in container logs
  • Docker health checks configured
  • API metrics available in logs
  • Version information included in response headers

⁠🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if needed
  5. Submit a pull request

⁠📄 License

MIT License - see LICENSE file for details.

Tag summary

Content type

Image

Digest

sha256:712432efe…

Size

156 MB

Last updated

about 1 year ago

docker pull danielgtmn/docker-pg-backup