Files
bab-backend-ansible/playbooks/backup_supabase_prod.yml
2026-04-14 20:23:26 -04:00

109 lines
3.7 KiB
YAML

---
- name: Dump Supabase prod database to local temp file
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Read Supabase prod secrets from Vault
ansible.builtin.set_fact:
_supabase_prod: "{{ lookup('community.hashi_vault.hashi_vault',
'secret=oys/prod/supabase url=' + vault_addr + ' engine_mount_point=kv') }}"
no_log: true
- name: Set backup filename
ansible.builtin.set_fact:
_backup_filename: >-
{{ 'oysqn-prod-' + now(fmt='%Y-%m') + '-monthly.sql.gz'
if now(fmt='%-d') == '1'
else 'oysqn-prod-' + now(fmt='%Y%m%d-%H%M%S') + '.sql.gz' }}
- name: Create local temporary directory
ansible.builtin.tempfile:
state: directory
suffix: .backup
register: _tmpdir
- name: Dump and compress database
ansible.builtin.shell:
cmd: "set -o pipefail && pg_dump '{{ _supabase_prod.postgres_url }}' | gzip > '{{ _tmpdir.path }}/{{ _backup_filename }}'"
executable: /bin/bash
changed_when: true
no_log: true
- name: Store backup on bab1 and enforce retention
hosts: bab1.mgmt.toal.ca
gather_facts: false
tasks:
- name: Ensure backup directory exists
ansible.builtin.file:
path: "{{ backup_base_dir }}"
state: directory
mode: '0750'
- name: Copy backup file to bab1
ansible.builtin.copy:
src: "{{ hostvars['localhost']['_tmpdir']['path'] }}/{{ hostvars['localhost']['_backup_filename'] }}"
dest: "{{ backup_base_dir }}/{{ hostvars['localhost']['_backup_filename'] }}"
mode: '0640'
- name: Find regular backup files older than retention period
ansible.builtin.find:
paths: "{{ backup_base_dir }}"
patterns: "oysqn-prod-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]*.sql.gz"
age: "{{ backup_retain_regular_days }}d"
age_stamp: mtime
register: _regular_old
- name: Delete regular backups beyond age limit
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ _regular_old.files }}"
- name: Find all regular backup files
ansible.builtin.find:
paths: "{{ backup_base_dir }}"
patterns: "oysqn-prod-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9]*.sql.gz"
register: _regular_all
- name: Delete oldest regular backups beyond count limit
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ (_regular_all.files | sort(attribute='mtime'))[: [(_regular_all.files | length - backup_retain_regular_count), 0] | max | int] }}"
- name: Find monthly backup files older than retention period
ansible.builtin.find:
paths: "{{ backup_base_dir }}"
patterns: "oysqn-prod-[0-9][0-9][0-9][0-9]-[0-9][0-9]-monthly.sql.gz"
age: "{{ backup_retain_monthly_days }}d"
age_stamp: mtime
register: _monthly_old
- name: Delete monthly backups beyond age limit
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ _monthly_old.files }}"
- name: Find all monthly backup files
ansible.builtin.find:
paths: "{{ backup_base_dir }}"
patterns: "oysqn-prod-[0-9][0-9][0-9][0-9]-[0-9][0-9]-monthly.sql.gz"
register: _monthly_all
- name: Delete oldest monthly backups beyond count limit
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ (_monthly_all.files | sort(attribute='mtime'))[: [(_monthly_all.files | length - backup_retain_monthly_count), 0] | max | int] }}"
- name: Remove local temporary directory
ansible.builtin.file:
path: "{{ hostvars['localhost']['_tmpdir']['path'] }}"
state: absent
delegate_to: localhost