- name: Configure local backup for Memos from memos-box hosts: lapy gather_facts: no vars_files: - ../../infra_vars.yml - ./memos_vars.yml vars: backup_data_path: "{{ memos_data_dir }}" tasks: - name: Debug remote backup vars debug: msg: - "backup_host={{ backup_host }}" - "backup_user={{ backup_user }}" - "backup_data_path='{{ backup_data_path }}'" - "local_backup_dir={{ local_backup_dir }}" - name: Ensure local backup directory exists file: path: "{{ local_backup_dir }}" state: directory mode: '0755' - name: Ensure ~/.local/bin exists file: path: "{{ lookup('env', 'HOME') }}/.local/bin" state: directory mode: '0755' - name: Create backup script copy: dest: "{{ backup_script_path }}" mode: '0750' content: | #!/bin/bash set -euo pipefail TIMESTAMP=$(date +'%Y-%m-%d') BACKUP_DIR="{{ local_backup_dir }}/$TIMESTAMP" mkdir -p "$BACKUP_DIR" {% if backup_key_file %} SSH_CMD="ssh -i {{ backup_key_file }} -p {{ backup_port }}" {% else %} SSH_CMD="ssh -p {{ backup_port }}" {% endif %} rsync -az -e "$SSH_CMD" --rsync-path="sudo rsync" --delete {{ backup_user }}@{{ backup_host }}:{{ backup_data_path }}/ "$BACKUP_DIR/" # Rotate old backups (keep 14 days) # Calculate cutoff date (14 days ago) and delete backups older than that CUTOFF_DATE=$(date -d '14 days ago' +'%Y-%m-%d') for dir in "{{ local_backup_dir }}"/20*; do if [ -d "$dir" ]; then dir_date=$(basename "$dir") if [ "$dir_date" != "$TIMESTAMP" ] && [ "$dir_date" \< "$CUTOFF_DATE" ]; then rm -rf "$dir" fi fi done - name: Ensure cronjob for backup exists cron: name: "Memos backup" user: "{{ lookup('env', 'USER') }}" job: "{{ backup_script_path }}" minute: 15 hour: "9,12,15,18" - name: Run the backup script to make the first backup command: "{{ backup_script_path }}" - name: Verify backup was created block: - name: Get today's date command: date +'%Y-%m-%d' register: today_date changed_when: false - name: Check backup directory exists and contains files stat: path: "{{ local_backup_dir }}/{{ today_date.stdout }}" register: backup_dir_stat - name: Verify backup directory exists assert: that: - backup_dir_stat.stat.exists - backup_dir_stat.stat.isdir fail_msg: "Backup directory {{ local_backup_dir }}/{{ today_date.stdout }} was not created" success_msg: "Backup directory {{ local_backup_dir }}/{{ today_date.stdout }} exists" - name: Check if backup directory contains files find: paths: "{{ local_backup_dir }}/{{ today_date.stdout }}" recurse: yes register: backup_files - name: Verify backup directory is not empty assert: that: - backup_files.files | length > 0 fail_msg: "Backup directory {{ local_backup_dir }}/{{ today_date.stdout }} exists but is empty" success_msg: "Backup directory contains {{ backup_files.files | length }} file(s)"