4.8 KiB
Postgres-to-R2 Backup
A lightweight automation service that creates scheduled PostgreSQL backups and securely uploads them to Cloudflare R2 object storage.
Designed specifically as a Railway deployment template, with built-in support for Docker and cron scheduling.
✨ Features
- 📦 Automated Backups — scheduled daily or hourly PostgreSQL backups
- 🔐 Optional Encryption — gzip compression or 7z encryption with password
- ☁️ Cloudflare R2 Integration — seamless S3-compatible uploads
- 🧹 Retention Policy — automatically delete old backups
- 🔗 Flexible Database URLs — supports private and public PostgreSQL URLs
- ⚡ Optimized Performance — parallel pg_dump and multipart R2 uploads
- 🐳 Docker Ready — portable, lightweight container
- 🚀 Railway Template First — no fork required for normal usage
🚀 Deployment on Railway (Recommended)
- Click the Deploy on Railway button below
- Railway will create a new project using the latest version of this repository
- Add the required environment variables in the Railway dashboard
- (Optional) Configure a cron job for your desired backup schedule
🔧 Environment Variables
DATABASE_URL= # PostgreSQL database URL (private)
DATABASE_PUBLIC_URL= # Public PostgreSQL URL (optional)
USE_PUBLIC_URL=false # Set true to use DATABASE_PUBLIC_URL
DUMP_FORMAT=dump # sql | plain | dump | custom | tar
FILENAME_PREFIX=backup # Backup filename prefix
MAX_BACKUPS=7 # Number of backups to retain
R2_ACCESS_KEY= # Cloudflare R2 access key
R2_SECRET_KEY= # Cloudflare R2 secret key
R2_BUCKET_NAME= # R2 bucket name
R2_ENDPOINT= # R2 endpoint URL
BACKUP_PASSWORD= # Optional: enables 7z encryption
BACKUP_TIME=00:00 # Daily backup time (UTC, HH:MM)
⏰ Railway Cron Jobs
You can configure the backup schedule using Railway Cron Jobs:
- Open your Railway project
- Go to Deployments → Cron
- Add a cron job targeting this service
Common Cron Expressions
| Schedule | Cron Expression | Description |
|---|---|---|
| Hourly | 0 * * * * |
Every hour |
| Daily | 0 0 * * * |
Once per day (UTC midnight) |
| Twice Daily | 0 */12 * * * |
Every 12 hours |
| Weekly | 0 0 * * 0 |
Every Sunday |
| Monthly | 0 0 1 * * |
First day of the month |
Tips
- All cron times are UTC
- Use https://crontab.guru to validate expressions
- Adjust
MAX_BACKUPSto match your schedule
🖥️ Running Locally or on Other Platforms
It can run on any platform that supports:
- Python 3.9+
pg_dump(PostgreSQL client tools)- Environment variables
- Long-running background processes or cron
Supported Environments
- Local machine (Linux / macOS / Windows*)
- VPS (Netcup, Hetzner, DigitalOcean, etc.)
- Docker containers
- Other PaaS providers (Heroku, Fly.io, Render, etc.)
Windows is supported when
pg_dumpis installed and available in PATH.
Local Requirements
- Python 3.9+
- PostgreSQL client tools (
pg_dump) - pip
Run Manually (Local)
pip install -r requirements.txt
python main.py
Run with Docker (Optional)
docker build -t postgres-to-r2-backup .
docker run --env-file .env postgres-to-r2-backup
> Ensure the container is allowed to run continuously when not using an external cron scheduler.
All scheduling uses UTC by default to ensure consistent behavior across platforms.
🔐 Security
-
Do not expose PostgreSQL directly to the public internet.
If your database is not on a private network, use a secure tunnel instead. -
Recommended: Cloudflare Tunnel
When using a public database URL, it is strongly recommended to connect via a secure tunnel such as Cloudflare Tunnel rather than opening database ports. -
Protect credentials
Store all secrets (database URLs, R2 keys, encryption passwords) using environment variables.
Never commit.envfiles to version control. -
Encrypted backups (optional)
SetBACKUP_PASSWORDto enable encrypted backups using 7z before uploading to Cloudflare R2. -
Least privilege access
Use a PostgreSQL user with read-only access where possible, and restrict R2 credentials to the required bucket only.
🛠 Development & Contributions
Fork this repository only if you plan to:
- Modify the backup logic
- Add features or integrations
- Submit pull requests
- Run locally for development
📜 License
This project is open source under the MIT License.
You are free to use, modify, and distribute it with attribution.