|
| 1 | +# PostgreSQL DB Backup & Restore via Docker & Deno |
| 2 | + |
| 3 | +This project provides a system to automate the backup and restore of a PostgreSQL database using **Deno**, **Docker**, and **Cloudflare R2**. It supports local backups, restoring from local files, and restoring directly from Cloudflare R2. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## **Technologies Used** |
| 8 | + |
| 9 | +- **Deno**: Runtime for the scripts and automation. |
| 10 | +- **Docker**: Containerization for portable backup/restore workflows. |
| 11 | +- **PostgreSQL**: Database used for backups and restores. |
| 12 | +- **PostgreSQL 16 Client**: Installed in the container for backup and restore operations. *(Note: Update the `postgresql<x>-client` version in the Dockerfile if your database uses a different version.)* |
| 13 | +- **Cloudflare R2**: Object storage for storing backup files. |
| 14 | +- **Winston**: Logging library for structured and color-coded logs. |
| 15 | +- **pg_restore**: PostgreSQL's native tool for restoring database dumps. |
| 16 | +- **Cronie**: Lightweight cron daemon for scheduling backup and restore tasks in the container. |
| 17 | + |
| 18 | +## **Getting Started** |
| 19 | + |
| 20 | +### **Requirements** |
| 21 | + |
| 22 | +1. **Deno** installed ([Install Guide](https://deno.land/manual/getting_started/installation)). |
| 23 | +2. **Docker** installed ([Install Guide](https://docs.docker.com/get-docker/)). |
| 24 | +3. A `.env` file in the root directory containing: |
| 25 | + |
| 26 | + ```env |
| 27 | + AUTOMATIC_BACKUP=If set to `true`, it will trigger a cron job to perform a backup. |
| 28 | + BACKUP_DB_URL=your_postgresql_connection_url |
| 29 | + RESTORE_DB_URL=your_postgresql_connection_url |
| 30 | + ACCESS_KEY_ID=your_r2_access_key_id |
| 31 | + SECRET_ACCESS_KEY=your_r2_secret_access_key |
| 32 | + BACKUP_DIR=your_r2_bucket_db_backup_dir |
| 33 | + ACCOUNT_ID=your_r2_account_id |
| 34 | + BUCKET_NAME=your_r2_bucket_name |
| 35 | + ``` |
| 36 | + |
| 37 | +4. **Cloudflare R2** storage setup with appropriate access credentials. |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +## **Available Tasks** |
| 42 | + |
| 43 | +### **Backup Task** |
| 44 | + |
| 45 | +Creates a backup of the database and uploads it to Cloudflare R2. |
| 46 | + |
| 47 | +**Command:** |
| 48 | + |
| 49 | +```sh |
| 50 | +deno task run:backup |
| 51 | +``` |
| 52 | + |
| 53 | +**Process:** |
| 54 | + |
| 55 | +1. Generates a backup file in the local `db_backups/<folder>` directory. |
| 56 | +2. Uploads the backup to the specified Cloudflare R2 bucket. |
| 57 | + |
| 58 | +--- |
| 59 | + |
| 60 | +### **Restore Task** |
| 61 | + |
| 62 | +Restores the database from a local backup file. |
| 63 | + |
| 64 | +**Command:** |
| 65 | + |
| 66 | +```sh |
| 67 | +deno task run:restore |
| 68 | +``` |
| 69 | + |
| 70 | +**Process:** |
| 71 | + |
| 72 | +1. Restores the database from a specified local backup file. |
| 73 | +2. Ensure the local backup file exists in the `db_backups/<folder>` directory. |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +### **Restore From R2 Task** |
| 78 | + |
| 79 | +Restores the database by downloading a backup file from Cloudflare R2. |
| 80 | + |
| 81 | +**Command:** |
| 82 | + |
| 83 | +```sh |
| 84 | +deno task run:restore-r2 --key=backups/<folder>/backup_1732266xxxxxx.tar |
| 85 | +``` |
| 86 | + |
| 87 | +**Process:** |
| 88 | + |
| 89 | +1. Downloads the specified backup file from Cloudflare R2 to a temporary location. |
| 90 | +2. Restores the database using the downloaded file. |
| 91 | +3. Deletes the temporary file after restoring. |
| 92 | + |
| 93 | +--- |
| 94 | + |
| 95 | +### **Automate Task** |
| 96 | + |
| 97 | +Automates the backup process, including uploading to R2 and cleanup. |
| 98 | + |
| 99 | +**Command:** |
| 100 | + |
| 101 | +```sh |
| 102 | +deno task automate |
| 103 | +``` |
| 104 | + |
| 105 | +**Process:** |
| 106 | + |
| 107 | +1. Creates a backup of the database. |
| 108 | +2. Uploads the backup file to Cloudflare R2. |
| 109 | +3. Cleans up local backup files older than the retention period. |
| 110 | +4. Deletes old R2 backups based on the retention policy. |
| 111 | + |
| 112 | +--- |
| 113 | + |
| 114 | +### **Restore From R2 Task (Script)** |
| 115 | + |
| 116 | +Runs the restore process from R2 using Docker for containerized execution. |
| 117 | + |
| 118 | +**Setup:** |
| 119 | + |
| 120 | +1. Set `RESTORE_DB_URL` in the `.env` file. |
| 121 | +2. Modify the `run_restore.sh` script to include the desired R2 object key. |
| 122 | + |
| 123 | +**Command:** |
| 124 | + |
| 125 | +```sh |
| 126 | +chmod +x run_restore.sh |
| 127 | +./run_restore.sh |
| 128 | +``` |
| 129 | + |
| 130 | +**Process:** |
| 131 | + |
| 132 | +1. Builds and runs a Docker container using `Dockerfile.restore`. |
| 133 | +2. Passes environment variables and R2 object key to the container. |
| 134 | +3. Restores the database and removes the temporary container after completion. |
| 135 | + |
| 136 | +--- |
| 137 | + |
| 138 | +## **Folder Structure** |
| 139 | + |
| 140 | +```plaintext |
| 141 | +. |
| 142 | +├── .dockerignore # Specifies files and directories to ignore in Docker builds |
| 143 | +├── .env # Environment variables file |
| 144 | +├── .env.example # Example environment variables file |
| 145 | +├── .vscode/ |
| 146 | +│ └── settings.json # VS Code-specific configuration |
| 147 | +├── deno.json # Deno configuration and tasks |
| 148 | +├── deno.lock # Dependency lock file for Deno |
| 149 | +├── Dockerfile.backup # Dockerfile for the backup container |
| 150 | +├── Dockerfile.restore # Dockerfile for the restore container |
| 151 | +├── railway.toml # Railway platform configuration for deployment |
| 152 | +├── README.md # Documentation |
| 153 | +├── run_automate.sh # Script to trigger automate task |
| 154 | +├── run_restore.sh # Script to trigger restore from R2 task via Docker |
| 155 | +├── start.sh # Startup script for cron-based backups |
| 156 | +├── src/ |
| 157 | +│ ├── backup/ # Backup-related functionality |
| 158 | +│ │ ├── cleanCloudBackups.ts # Cleans up old backups from R2 |
| 159 | +│ │ ├── cleanLocalBackups.ts # Cleans up old backups locally |
| 160 | +│ │ └── createBackup.ts # Logic to create a PostgreSQL backup |
| 161 | +│ ├── restore/ # Restore-related functionality |
| 162 | +│ │ └── restoreBackup.ts # Logic to restore a PostgreSQL backup |
| 163 | +│ ├── utils/ # Utility functions and helpers |
| 164 | +│ │ ├── r2/ |
| 165 | +│ │ │ ├── cloudflareR2.ts # Cloudflare R2 integration logic |
| 166 | +│ │ │ ├── index.ts # R2 helper functions |
| 167 | +│ │ │ └── multipartUploadToR2.ts # Logic for multipart uploads to R2 |
| 168 | +│ │ ├── execCommand.ts # Helper for executing shell commands |
| 169 | +│ │ └── logger.ts # Custom logger with color-coded log levels |
| 170 | +│ ├── config.ts # Configuration file for environment variables |
| 171 | +│ ├── index.ts # Entry point for backup/restore tasks |
| 172 | +│ └── automate.ts # Automation script for scheduled backups |
| 173 | +``` |
| 174 | + |
| 175 | +--- |
| 176 | + |
| 177 | +## **Environment Variables** |
| 178 | + |
| 179 | +Ensure the following environment variables are defined in the `.env` file: |
| 180 | + |
| 181 | +```env |
| 182 | +# PostgreSQL Connection URLs |
| 183 | +BACKUP_DB_URL=your_postgresql_backup_url |
| 184 | +RESTORE_DB_URL=your_postgresql_restore_url |
| 185 | +
|
| 186 | +# Cloudflare R2 Configuration |
| 187 | +ACCESS_KEY_ID=your_r2_access_key_id |
| 188 | +SECRET_ACCESS_KEY=your_r2_secret_access_key |
| 189 | +ACCOUNT_ID=your_r2_account_id |
| 190 | +BUCKET_NAME=your_r2_bucket_name |
| 191 | +``` |
| 192 | + |
| 193 | +--- |
| 194 | + |
| 195 | +## **Cron Integration** |
| 196 | + |
| 197 | +To automate backups with cron: |
| 198 | + |
| 199 | +1. Add the `deno task automate` command to your crontab file. |
| 200 | +2. Example entry for a daily backup at midnight: |
| 201 | + |
| 202 | + ```cron |
| 203 | + 0 0 * * * deno task automate >> /var/log/db_backup.log 2>&1 |
| 204 | + ``` |
| 205 | + |
| 206 | +--- |
| 207 | + |
| 208 | +## **Additional Notes** |
| 209 | + |
| 210 | +- Automatic backup is configured in `Dockerfile.backup`. It is designed for deployment on the **Railway.app** platform via the `railway.toml` file to enable automatic PostgreSQL backups. If you are using a different platform, update the configuration to run `Dockerfile.backup` by default. |
| 211 | +- Ensure your R2 bucket permissions allow read and write operations. |
| 212 | +- Use the `run_restore.sh` script for containerized restore processes. |
| 213 | +- For schema-specific restores, customize the `restoreBackup.ts` function as needed. |
0 commit comments