| 1 | #!/usr/bin/env bash |
| 2 | # SPDX-License-Identifier: AGPL-3.0-or-later |
| 3 | # |
| 4 | # Cross-region copy from the primary Spaces bucket (NYC3) to the |
| 5 | # DR bucket (SFO3). Run on a schedule from the backup host (the one |
| 6 | # that already has rclone configured), NOT from the app server — |
| 7 | # we don't want a runaway sync to evict app pages from cache. |
| 8 | # |
| 9 | # rclone copy is incremental (size + mtime), so this is cheap on |
| 10 | # steady-state and only moves new objects. |
| 11 | # |
| 12 | # --s3-no-check-bucket: skip the GetBucketLocation pre-check that |
| 13 | # requires a permission our scoped-RW Spaces keys don't grant. The |
| 14 | # actual copy works fine on a key with bucket-level readwrite. |
| 15 | |
| 16 | set -euo pipefail |
| 17 | |
| 18 | PRIMARY="${SHITHUB_BACKUP_BUCKET:-spaces-prod:shithub-backups}" |
| 19 | DR="${SHITHUB_DR_BUCKET:-spaces-dr:shithub-backups-dr}" |
| 20 | WAL_PRIMARY="${SHITHUB_WAL_BUCKET:-spaces-prod:shithub-wal}" |
| 21 | WAL_DR="${SHITHUB_WAL_DR_BUCKET:-spaces-dr:shithub-wal-dr}" |
| 22 | |
| 23 | LOG="/var/log/shithub/spaces-sync.log" |
| 24 | mkdir -p "$(dirname "$LOG")" |
| 25 | |
| 26 | ts() { date -u +%Y-%m-%dT%H:%M:%SZ; } |
| 27 | |
| 28 | { |
| 29 | echo "[$(ts)] sync start" |
| 30 | |
| 31 | rclone --config /etc/rclone-shithub.conf --s3-no-check-bucket \ |
| 32 | copy --transfers 8 --checkers 16 --fast-list \ |
| 33 | "$PRIMARY" "$DR" |
| 34 | |
| 35 | rclone --config /etc/rclone-shithub.conf --s3-no-check-bucket \ |
| 36 | copy --transfers 8 --checkers 16 --fast-list \ |
| 37 | "$WAL_PRIMARY" "$WAL_DR" |
| 38 | |
| 39 | echo "[$(ts)] sync end" |
| 40 | } >> "$LOG" 2>&1 |