release: v1.0.6 optional local backup retention

Add optional KEEP_LOCAL_BACKUP environment variable to control local backup retention.

Default behavior remains unchanged: backup files are deleted locally after
successful upload, keeping deployments safe on Railway and other PaaS
platforms with ephemeral storage.

When KEEP_LOCAL_BACKUP=true is set, backups are preserved locally, which is
useful for CLI usage, local machines, VPS, or NAS workflows.

Documentation and CLI output were updated for clarity.
No breaking changes.
This commit is contained in:
KakiFilem Team 2026-02-03 14:22:23 +08:00
parent a226ebbc53
commit 3f9ac9f4e5
4 changed files with 32 additions and 12 deletions

View File

@ -24,6 +24,7 @@ Designed specifically as a **Railway deployment template**, with built-in suppor
- 🐳 **Docker Ready** — portable, lightweight container - 🐳 **Docker Ready** — portable, lightweight container
- 🚀 **Railway Template First** — no fork required for normal usage - 🚀 **Railway Template First** — no fork required for normal usage
- 🪣 **S3-Compatible Storage** — works with R2, AWS S3, Wasabi, B2, MinIO - 🪣 **S3-Compatible Storage** — works with R2, AWS S3, Wasabi, B2, MinIO
- 💾 **Optional Local Retention** — keep backups locally for CLI, VPS, or NAS usage
--- ---
@ -32,7 +33,9 @@ Designed specifically as a **Railway deployment template**, with built-in suppor
1. Click the **Deploy on Railway** button below 1. Click the **Deploy on Railway** button below
2. Railway will create a new project using the latest version of this repository 2. Railway will create a new project using the latest version of this repository
3. Add the required environment variables in the Railway dashboard 3. Add the required environment variables in the Railway dashboard
4. (Optional) Configure a cron job for your desired backup schedule 4. (Optional) Configure a cron job for your desired backup schedule
> Railway uses ephemeral storage. Local backup files are deleted by default after upload.
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/postgres-to-r2-backup?referralCode=nIQTyp&utm_medium=integration&utm_source=template&utm_campaign=generic) [![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/postgres-to-r2-backup?referralCode=nIQTyp&utm_medium=integration&utm_source=template&utm_campaign=generic)
@ -48,6 +51,7 @@ USE_PUBLIC_URL=false # Set true to use DATABASE_PUBLIC_URL
DUMP_FORMAT=dump # sql | plain | dump | custom | tar DUMP_FORMAT=dump # sql | plain | dump | custom | tar
FILENAME_PREFIX=backup # Backup filename prefix FILENAME_PREFIX=backup # Backup filename prefix
MAX_BACKUPS=7 # Number of backups to retain MAX_BACKUPS=7 # Number of backups to retain
KEEP_LOCAL_BACKUP=false # Keep backup file locally after upload (not recommended on PaaS)
R2_ENDPOINT= # S3 endpoint URL R2_ENDPOINT= # S3 endpoint URL
R2_BUCKET_NAME= # Bucket name R2_BUCKET_NAME= # Bucket name
@ -166,13 +170,13 @@ If you downloaded a prebuilt Docker image archive (`.tar` or `.tar.gz`), you can
```bash ```bash
# Extract the archive (if compressed) # Extract the archive (if compressed)
tar -xzf postgres-to-r2-backup_v1.0.4.tar.gz tar -xzf postgres-to-r2-backup_v1.0.6.tar.gz
# Load the image into Docker # Load the image into Docker
docker load -i postgres-to-r2-backup_v1.0.4.tar docker load -i postgres-to-r2-backup_v1.0.6.tar
# Run the container # Run the container
docker run --env-file .env postgres-to-r2-backup:v1.0.4 docker run --env-file .env postgres-to-r2-backup:v1.0.6
``` ```
> Prebuilt images are architecture-specific (amd64 / arm64). > Prebuilt images are architecture-specific (amd64 / arm64).
@ -225,6 +229,17 @@ When running via the CLI, environment variables are resolved in the following or
This allows different folders to maintain separate backup configurations. This allows different folders to maintain separate backup configurations.
### Local Backup Behavior (CLI)
By default, pg-r2-backup deletes the local backup file after a successful upload.
To keep a local copy (recommended for local machines, VPS, or NAS):
KEEP_LOCAL_BACKUP=true
> Not recommended on PaaS platforms (Railway, Fly.io, Render, Heroku, etc.)
> due to ephemeral filesystems.
### Scheduling Backups (CLI) ### Scheduling Backups (CLI)
The CLI does not run a background scheduler. Use your operating system or platform scheduler instead. The CLI does not run a background scheduler. Use your operating system or platform scheduler instead.

View File

@ -22,6 +22,7 @@ R2_SECRET_KEY = os.environ.get("R2_SECRET_KEY")
R2_BUCKET_NAME = os.environ.get("R2_BUCKET_NAME") R2_BUCKET_NAME = os.environ.get("R2_BUCKET_NAME")
R2_ENDPOINT = os.environ.get("R2_ENDPOINT") R2_ENDPOINT = os.environ.get("R2_ENDPOINT")
MAX_BACKUPS = int(os.environ.get("MAX_BACKUPS", 7)) MAX_BACKUPS = int(os.environ.get("MAX_BACKUPS", 7))
KEEP_LOCAL_BACKUP = os.environ.get("KEEP_LOCAL_BACKUP", "false").lower() == "true"
BACKUP_PREFIX = os.environ.get("BACKUP_PREFIX", "") BACKUP_PREFIX = os.environ.get("BACKUP_PREFIX", "")
FILENAME_PREFIX = os.environ.get("FILENAME_PREFIX", "backup") FILENAME_PREFIX = os.environ.get("FILENAME_PREFIX", "backup")
DUMP_FORMAT = os.environ.get("DUMP_FORMAT", "dump") DUMP_FORMAT = os.environ.get("DUMP_FORMAT", "dump")
@ -173,7 +174,11 @@ def run_backup():
log(f"[ERROR] R2 operation failed: {e}") log(f"[ERROR] R2 operation failed: {e}")
finally: finally:
if os.path.exists(compressed_file): if os.path.exists(compressed_file):
os.remove(compressed_file) if KEEP_LOCAL_BACKUP:
log("[INFO] Keeping local backup (KEEP_LOCAL_BACKUP=true)")
else:
os.remove(compressed_file)
log("[INFO] Local backup deleted")
if __name__ == "__main__": if __name__ == "__main__":
log("[INFO] Starting backup scheduler...") log("[INFO] Starting backup scheduler...")

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "pg-r2-backup" name = "pg-r2-backup"
version = "1.0.5" version = "1.0.6"
description = "PostgreSQL backup tool for Cloudflare R2 (S3 Compatible)" description = "PostgreSQL backup tool for Cloudflare R2 (S3 Compatible)"
readme = "README.md" readme = "README.md"
requires-python = ">=3.9" requires-python = ">=3.9"
@ -13,7 +13,7 @@ authors = [
{ name = "Aman" } { name = "Aman" }
] ]
license = { text = "MIT" } license = "MIT"
dependencies = [ dependencies = [
"boto3", "boto3",

View File

@ -1,5 +1,5 @@
boto3==1.42.40 boto3==1.42.40
psycopg2-binary==2.9.10 psycopg2-binary==2.9.10
python-dotenv==1.2.1 python-dotenv==1.2.1
py7zr==1.1.0 py7zr==1.1.0
schedule==1.2.2 schedule==1.2.2