A modern REST API for PostgreSQL database backups to S3
1.5K
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.
Clone the repository
git clone https://github.com/danielgtmn/docker-pg-backup.git
cd docker-pg-backup
Configure environment
cp env.example .env
# Edit .env with your storage configuration
Start the API server
docker-compose up -d
Access the API
This project uses GitHub Actions for automated CI/CD. Docker images are automatically built and published to the GitHub Container Registry (ghcr.io).
v* tags creates versioned releases# 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>
Images are built for both linux/amd64 and linux/arm64 architectures.
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
This API supports various S3-compatible storage services:
S3_ENDPOINT= # (optional, uses AWS default)
S3_BUCKET=my-bucket
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
S3_ENDPOINT=https://minio.example.com:9000
S3_BUCKET=my-bucket
AWS_ACCESS_KEY_ID=minio-user
AWS_SECRET_ACCESS_KEY=minio-password
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
S3_ENDPOINT=https://us-east-1.linodeobjects.comS3_ENDPOINT=https://s3.wasabisys.comS3_ENDPOINT=https://s3.us-west-002.backblazeb2.comThis API uses semantic versioning for all endpoints to ensure backward compatibility and smooth upgrades.
v1 (stable)/v{number}/api/{endpoint}/api/* routes are automatically redirected to /v1/api/*| Version | Status | Release Date | Deprecation Date | Sunset Date |
|---|---|---|---|---|
v1 | Current | 2024-01-01 | - | - |
Note: All API endpoints require authentication via API key in the
Authorizationheader.
# 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
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/configVisit http://localhost:3000/docs for the complete interactive Swagger documentation with:
If you're currently using the legacy /api/* endpoints:
/v1/api/*) for better performanceBefore (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://..."}'
X-API-Version, X-Deprecation-Warning)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/jsonRequired 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"
}
}
GET /v1/api/backups?limit=10&prefix=my-backups
GET /api/backups?limit=10&prefix=my-backups
GET /v1/api/health
GET /api/health
GET /v1/api/config
Authorization: Bearer your-api-key-here
GET /api/config
Authorization: Bearer your-api-key-here
# 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
# 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
# Install dependencies
pnpm install
# Development mode with hot reload
pnpm dev
# Build for production
pnpm build
# Run tests
pnpm test
# Lint code
pnpm lint
When running, visit http://localhost:3000/docs for interactive API documentation with:
| Storage | Configuration | Verification | Notes |
|---|---|---|---|
| AWS S3 | S3_BUCKET, AWS_ACCESS_KEY_ID | ✅ HeadObject | Most common choice |
| Google Cloud Storage | GCS_BUCKET, GOOGLE_APPLICATION_CREDENTIALS | ✅ File exists | Requires service account |
| Azure Blob Storage | AZURE_ACCOUNT, AZURE_CONTAINER | ✅ Blob exists | Requires storage account |
| Local Filesystem | BACKUP_DIR | ✅ File exists | For development/testing |
The API returns structured error responses:
{
"success": false,
"error": "Validation failed",
"details": ["databaseUrl is required"]
}
Common HTTP status codes:
200 - Success400 - Bad Request (validation errors)500 - Internal Server Error/v1/api/health (versioned) or /api/health (legacy, auto-redirects)MIT License - see LICENSE file for details.
Content type
Image
Digest
sha256:712432efe…
Size
156 MB
Last updated
about 1 year ago
docker pull danielgtmn/docker-pg-backup