--- - 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 become: true ansible.builtin.apt: update_cache: true - name: Ensure rsync is installed become: true ansible.builtin.apt: name: rsync state: present - name: Ensure etherwake is installed become: true ansible.builtin.apt: name: etherwake state: present - name: Find network interface with 192.168.1.x IP address register: network_interface ansible.builtin.shell: ip -o -4 addr list | grep '192.168.1.' | awk '{print $2}' - name: Set network_interface fact ansible.builtin.set_fact: network_interface: "{{ network_interface.stdout }}" - name: Find existing SSH public key with_items: "{{ ssh_key_paths }}" register: ssh_key_check ansible.builtin.stat: path: "{{ item }}" - name: Set SSH key path when: ssh_key_check.results | selectattr('stat.exists', 'equalto', true) | length > 0 ansible.builtin.set_fact: ssh_key_path: "{{ ssh_key_check.results | selectattr('stat.exists', 'equalto', true) | map(attribute='item') | first }}" - name: Debug SSH key path ansible.builtin.debug: msg: "SSH key path: {{ ssh_key_path }}" - name: Read the SSH public key register: ssh_pub_key when: ssh_key_path is defined ansible.builtin.slurp: src: "{{ ssh_key_path }}" - name: Ensure .ssh directory exists on the NAS <<<<<<< HEAD command: "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 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 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null alex@alex-ds414.localdomain 'echo {{ ssh_pub_key.content | b64decode }} >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'" ======= ignore_errors: true ansible.builtin.command: ssh alex@alex-ds414.localdomain 'mkdir -p ~/.ssh && chmod 700 ~/.ssh' - name: Add the SSH public key to the NAS authorized_keys >>>>>>> 1f4815ce65e05dc5fd5cb1a0b2d50a999060d539 when: ssh_key_path is defined ansible.builtin.command: ssh alex@alex-ds414.localdomain 'echo {{ ssh_pub_key.content | b64decode }} >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys' - name: Show debug info for rsync_user and rsync_password ansible.builtin.debug: msg: "rsync_user: {{ rsync_user }}, rsync_password: {{ rsync_password }}" - name: Wake up the NAS async: 0 poll: 0 become: true ansible.builtin.command: sudo etherwake -i {{ network_interface }} 00:11:32:43:FA:11 - name: Wait for 1 minute to allow NAS to start up initially ansible.builtin.wait_for: timeout: 60 - name: Check if NAS is reachable via SSH <<<<<<< HEAD command: "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -o ConnectTimeout=5 alex@alex-ds414.localdomain echo 'SSH connection successful'" ======= >>>>>>> 1f4815ce65e05dc5fd5cb1a0b2d50a999060d539 register: nas_ping_result ignore_errors: true ansible.builtin.command: ssh -o BatchMode=yes -o ConnectTimeout=5 alex@alex-ds414.localdomain echo 'SSH connection successful' - name: Fail if the NAS is not reachable via SSH when: nas_ping_result.rc != 0 ansible.builtin.fail: msg: NAS is not reachable via SSH. Exiting. - name: Perform the test rsync <<<<<<< HEAD command: rsync -av --dry-run --delete --info=progress2 {{ backup_dir }}/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/ ======= >>>>>>> 1f4815ce65e05dc5fd5cb1a0b2d50a999060d539 register: rsync_test ignore_errors: true failed_when: rsync_test.rc not in [0, 23] ansible.builtin.command: rsync -av --dry-run --delete {{ backup_dir }}/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/ - name: Fail if the rsync test fails for reasons other than permission issues when: rsync_test.rc not in [0, 23] ansible.builtin.fail: msg: rsync test failed for reasons other than permission issues. Exiting. - name: Perform the backup using rsync <<<<<<< HEAD command: rsync -av --delete --info=progress2 {{ backup_dir }}/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/ ======= >>>>>>> 1f4815ce65e05dc5fd5cb1a0b2d50a999060d539 when: rsync_test.rc in [0, 23] ignore_errors: true failed_when: rsync_test.rc not in [0, 23] ansible.builtin.command: rsync -av --delete {{ backup_dir }}/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/ - name: Check if cron job exists register: cron_present ignore_errors: true ansible.builtin.cron: name: "{{ cron_name }}" state: present - name: Add cron job for backup if not present when: rsync_test.rc in [0, 23] and (cron_present is not defined or cron_present is failed) become: true ansible.builtin.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] }}" <<<<<<< HEAD job: "sudo etherwake -i {{ network_interface }} 00:11:32:43:FA:11 && sleep 300 && rsync -av --info=progress2 --delete /home/ alex@alex-ds414.localdomain:{{ nas_target_base }}/{{ hostname }}/" when: rsync_test.rc == 0 and (cron_present is not defined or cron_present is failed) become: yes ======= 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 }}/ >>>>>>> 1f4815ce65e05dc5fd5cb1a0b2d50a999060d539