--- - name: Install backup software and configure backup to Synology NAS hosts: all become: false vars_files: - vault.yml vars: backup_dir: "/home" nas_target_base: "/volume1/Backup" cron_time: "0 17 * * 0" # This represents every Sunday at 17:00 hostname: "{{ ansible_hostname }}" cron_name: "Wake NAS and Backup to Synology NAS" ssh_key_paths: - "/home/alex/.ssh/id_ed25519.pub" - "/home/alex/.ssh/id_rsa.pub" - "/home/alex/.ssh/id_ecdsa.pub" - "/home/alex/.ssh/id_dsa.pub" tasks: - name: Update apt cache apt: update_cache: yes become: yes - name: Ensure rsync is installed apt: name: rsync state: present become: yes - name: Ensure etherwake is installed apt: name: etherwake state: present become: yes - name: Find network interface with 192.168.1.x IP address shell: ip -o -4 addr list | grep '192.168.1.' | awk '{print $2}' register: network_interface - name: Set network_interface fact set_fact: network_interface: "{{ network_interface.stdout }}" - name: Find existing SSH public key stat: path: "{{ item }}" with_items: "{{ ssh_key_paths }}" register: ssh_key_check - name: Set SSH key path set_fact: ssh_key_path: "{{ ssh_key_check.results | selectattr('stat.exists', 'equalto', true) | map(attribute='item') | first }}" when: ssh_key_check.results | selectattr('stat.exists', 'equalto', true) | length > 0 - name: Debug SSH key path debug: msg: "SSH key path: {{ ssh_key_path }}" - name: Read the SSH public key slurp: src: "{{ ssh_key_path }}" register: ssh_pub_key when: ssh_key_path is defined - name: Ensure .ssh directory exists on the NAS command: "ssh alex@alex-ds414.localdomain 'mkdir -p ~/.ssh && chmod 700 ~/.ssh'" ignore_errors: yes - name: Add the SSH public key to the NAS authorized_keys command: "ssh alex@alex-ds414.localdomain 'echo {{ ssh_pub_key.content | b64decode }} >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'" when: ssh_key_path is defined - name: Show debug info for rsync_user and rsync_password debug: msg: "rsync_user: {{ rsync_user }}, rsync_password: {{ rsync_password }}" - name: Wake up the NAS command: sudo etherwake -i {{ network_interface }} 00:11:32:43:FA:11 async: 0 poll: 0 become: yes - name: Wait for 1 minute to allow NAS to start up initially wait_for: timeout: 60 - name: Check if NAS is reachable via SSH command: "ssh -o BatchMode=yes -o ConnectTimeout=5 alex@alex-ds414.localdomain echo 'SSH connection successful'" register: nas_ping_result ignore_errors: yes - name: Fail if the NAS is not reachable via SSH fail: msg: "NAS is not reachable via SSH. Exiting." when: nas_ping_result.rc != 0 - name: Perform the test rsync command: rsync -av --dry-run --delete {{ backup_dir }}/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/ register: rsync_test ignore_errors: yes failed_when: rsync_test.rc not in [0, 23] - name: Fail if the rsync test fails for reasons other than permission issues fail: msg: "rsync test failed for reasons other than permission issues. Exiting." when: rsync_test.rc not in [0, 23] - name: Perform the backup using rsync command: rsync -av --delete {{ backup_dir }}/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/ when: rsync_test.rc in [0, 23] ignore_errors: yes failed_when: rsync_test.rc not in [0, 23] - name: Check if cron job exists cron: name: "{{ cron_name }}" state: present register: cron_present ignore_errors: yes - name: Add cron job for backup if not present cron: name: "{{ cron_name }}" minute: "{{ cron_time.split()[0] }}" hour: "{{ cron_time.split()[1] }}" day: "{{ cron_time.split()[2] }}" month: "{{ cron_time.split()[3] }}" weekday: "{{ cron_time.split()[4] }}" job: "sudo etherwake -i {{ network_interface }} 00:11:32:43:FA:11 && sleep 300 && rsync -av --delete /home/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/" when: rsync_test.rc in [0, 23] and (cron_present is not defined or cron_present is failed) become: yes