--- - name: Assert backup_source parameters are sane ansible.builtin.assert: that: - backup_source_name | length > 0 - backup_source_description | length > 0 - backup_source_dump_command | length > 0 - backup_source_recipient | length > 0 - backup_source_recipient is match('^age1[0-9a-z]{58}$') fail_msg: >- backup_source: '{{ backup_source_name | default("") }}' needs a name, description, dump command and a valid age recipient (age1... 62 chars). quiet: true # Declared here rather than assumed. Stage 1 installed it by hand; this is what # makes a rebuilt host get it too. - name: Ensure age is installed ansible.builtin.apt: name: age state: present update_cache: yes cache_valid_time: 3600 # The pull account: unprivileged, no sudo, exists only so small-backups-box can # read the dump directory. Trust points one way — the box can read backups, and # can do nothing else on this host. - name: "Ensure the {{ backup_source_pull_user }} account exists" ansible.builtin.user: name: "{{ backup_source_pull_user }}" system: yes shell: /bin/sh # rsync-over-ssh needs a shell; nologin breaks it home: "/var/lib/{{ backup_source_pull_user }}" create_home: yes password: '!' # no password login, ever when: backup_source_pull_user | length > 0 - name: "Authorise the backup box's key for {{ backup_source_pull_user }}" ansible.posix.authorized_key: user: "{{ backup_source_pull_user }}" key: "{{ backup_source_pull_key }}" key_options: "restrict" # no pty, no forwarding, no user rc exclusive: yes state: present when: backup_source_pull_user | length > 0 # The shared container above the per-service directories. It must be traversable # or the pull account cannot reach its own directory. The script's `mkdir -p` # runs under `umask 077` and would otherwise create this 0700. - name: "Ensure {{ backup_source_dir | dirname }} is traversable" ansible.builtin.file: path: "{{ backup_source_dir | dirname }}" state: directory owner: root group: root mode: '0755' - name: "Ensure {{ backup_source_dir }} exists" ansible.builtin.file: path: "{{ backup_source_dir }}" state: directory owner: root group: "{{ backup_source_pull_user | default('root', true) }}" mode: '0750' - name: "Install the {{ backup_source_name }} backup script" ansible.builtin.template: src: backup.sh.j2 dest: "/usr/local/bin/{{ backup_source_name }}-backup.sh" owner: root group: root mode: '0750' validate: "bash -n %s" - name: "Install the {{ backup_source_name }}-backup systemd units" ansible.builtin.template: src: "backup.{{ item }}.j2" dest: "/etc/systemd/system/{{ backup_source_name }}-backup.{{ item }}" owner: root group: root mode: '0644' loop: [service, timer] notify: Reload systemd for backup units - name: "Enable the {{ backup_source_name }}-backup timer" ansible.builtin.systemd: name: "{{ backup_source_name }}-backup.timer" enabled: yes state: started daemon_reload: yes