--- # SPDX-License-Identifier: AGPL-3.0-or-later # Logical backup cron + cross-region Spaces sync. The actual scripts # live under deploy/postgres/ and deploy/spaces/ so they can be # read/edited without booting Ansible. - name: Backup scripts — install copy: src: "{{ playbook_dir }}/../{{ item.src }}" dest: "{{ item.dest }}" mode: "0755" loop: - { src: postgres/backup-daily.sh, dest: /usr/local/bin/shithub-backup-daily } - { src: spaces/sync-cross-region.sh, dest: /usr/local/bin/shithub-spaces-sync } # Restore drill needs run.sh + smoke-queries.sql to live next to each # other (run.sh reads the .sql via $(dirname "$0")). Put both in a # share dir; the cron job invokes the absolute path. - name: Restore drill — share dir file: path: /usr/local/share/shithub/restore-drill state: directory mode: "0755" - name: Restore drill — install copy: src: "{{ playbook_dir }}/../restore-drill/{{ item.src }}" dest: "/usr/local/share/shithub/restore-drill/{{ item.src }}" mode: "{{ item.mode }}" loop: - { src: run.sh, mode: "0755" } - { src: smoke-queries.sql, mode: "0644" } # Single rclone config shared by every script that talks to Spaces: # - root-owned for the daily/cross-region cron jobs (running as root) # - postgres-readable (group 0640) for archive_command, which Postgres # invokes as the postgres user. The previous /root/.config/rclone/ # path was unreachable to postgres because /root is mode 0700; # moving to /etc/ with explicit group sidesteps the traversal block. - name: rclone config — Spaces credentials, shared with postgres template: src: rclone.conf.j2 dest: /etc/rclone-shithub.conf owner: root group: postgres mode: "0640" - name: cron — daily logical backup cron: name: shithub-backup-daily job: /usr/local/bin/shithub-backup-daily >> /var/log/shithub-backup.log 2>&1 minute: "17" hour: "3" - name: cron — hourly cross-region sync cron: name: shithub-spaces-sync job: /usr/local/bin/shithub-spaces-sync >> /var/log/shithub-spaces-sync.log 2>&1 minute: "23" # Weekly restore drill. The runbook still calls for a *manual* drill # every quarter (the operator inspects the result), but exercising # the recovery path weekly catches backup-pipeline regressions # (corrupt dumps, missing schema migrations) within days instead of # months. The script logs to /var/log/shithub/restore-drill.log so # the operator can `tail` it whenever. - name: cron — weekly restore drill cron: name: shithub-restore-drill job: /usr/local/share/shithub/restore-drill/run.sh weekday: "0" hour: "4" minute: "30"