- name: fail if repo parameters are missing fail: msg: repo parameters are missing or incorrect when: (repo is not mapping) or (repo.user is not defined) or (repo.password is not defined) - name: protect against malicious repo names fail: msg: this backup repo name is reserved when: (repo.name is string) and (((repo.name | lower) == 'config') or ((repo.name | lower) == 'data') or ((repo.name | lower) == 'index') or ((repo.name | lower) == 'keys') or ((repo.name | lower) == 'locks') or ((repo.name | lower) == 'snapshots')) - name: get rest server hostname set_fact: rest_server_hostname: "{{ repo.server if (repo.server is string and repo.server | length > 0) else services.rest_server.hostname }}" - name: get rest server parms set_fact: rest_server_parms: conf_dir: "{{ hostvars[rest_server_hostname]['rest_server_conf_dir'] | d(rest_server_conf_dir) }}" data_dir: "{{ hostvars[rest_server_hostname]['rest_server_data_dir'] | d(rest_server_data_dir) }}" passwd_dir: "{{ hostvars[rest_server_hostname]['rest_server_passwd_dir'] | d(rest_server_passwd_dir) }}" user: "{{ hostvars[rest_server_hostname]['rest_server_user'] | d(rest_server_user) }}" group: "{{ hostvars[rest_server_hostname]['rest_server_group'] | d(rest_server_group) }}" maintenance_mark: "{{ hostvars[rest_server_hostname]['rest_server_maintenance_mark'] | d(rest_server_maintenance_mark) }}" - block: - name: ensure user exists in htpasswd file htpasswd: path: "{{ rest_server_parms.data_dir }}/.htpasswd" create: yes crypt_scheme: bcrypt mode: 0400 owner: "{{ rest_server_parms.user }}" group: "{{ rest_server_parms.group }}" name: "{{ repo.user }}" password: "{{ repo.password }}" - name: set restic repo and password facts set_fact: restic_repo: "{{ rest_server_parms.data_dir ~ '/' ~ repo.user ~ (('/' ~ repo.name) if (repo.name is string and repo.name | length > 0) else '') }}" restic_password: "{{ repo.repo_password if (repo.repo_password is string and repo.repo_password | length > 0) else repo.password }}" restic_passwd_file: "{{ rest_server_parms.passwd_dir ~ '/' ~ repo.user ~ (('.' ~ repo.name) if (repo.name is string and repo.name | length > 0) else '') }}" no_log: yes - name: set restic retention facts set_fact: restic_retention: "{{ [ (('--keep-last ' ~ (repo.retention.last | quote)) if (repo.retention.last is defined) else ''), (('--keep-hourly ' ~ (repo.retention.hourly | quote)) if (repo.retention.hourly is defined) else ''), (('--keep-daily ' ~ (repo.retention.daily | quote)) if (repo.retention.daily is defined) else ''), (('--keep-weekly ' ~ (repo.retention.weekly | quote)) if (repo.retention.weekly is defined) else ''), (('--keep-monthly ' ~ (repo.retention.monthly | quote)) if (repo.retention.monthly is defined) else ''), (('--keep-yearly ' ~ (repo.retention.yearly | quote)) if (repo.retention.yearly is defined) else ''), (('--keep-within ' ~ (repo.retention.within | quote)) if (repo.retention.within is defined) else ''), (('--keep-within-hourly ' ~ (repo.retention.within_hourly | quote)) if (repo.retention.within_hourly is defined) else ''), (('--keep-within-daily ' ~ (repo.retention.within_daily | quote)) if (repo.retention.within_daily is defined) else ''), (('--keep-within-weekly ' ~ (repo.retention.within_weekly | quote)) if (repo.retention.within_weekly is defined) else ''), (('--keep-within-monthly ' ~ (repo.retention.within_monthly | quote)) if (repo.retention.within_monthly is defined) else ''), (('--keep-within-yearly ' ~ (repo.retention.within_yearly | quote)) if (repo.retention.within_yearly is defined) else '') ] | select() | list | join(' ') }}" when: repo.retention is defined and repo.retention is mapping - name: create passwd file for repo copy: dest: "{{ restic_passwd_file }}" content: "{{ restic_password }}" mode: 0400 owner: "{{ rest_server_parms.user }}" group: "{{ rest_server_parms.group }}" - name: create repository shell: cmd: /usr/bin/restic init environment: RESTIC_REPOSITORY: "{{ restic_repo }}" RESTIC_PASSWORD: "{{ restic_password }}" register: result changed_when: "'created restic repository' in result.stdout" failed_when: "(result.rc != 0) and not ('config file already exists' in result.stderr)" become: yes become_user: "{{ rest_server_parms.user }}" become_method: su become_flags: "-s /bin/ash" - name: edit maintenance script lineinfile: path: "{{ rest_server_parms.conf_dir }}/maintenance.sh" regexp: '^/usr/bin/restic(\s+)--repo(\s+){{ restic_repo | quote | regex_escape }}(\s+)(.*)$' line: "/usr/bin/restic --repo {{ restic_repo | quote }} --password-file {{ restic_passwd_file | quote }} forget --prune {{ restic_retention | d('--keep-last 14') }}" insertbefore: "^# {{ rest_server_parms.maintenance_mark }}" firstmatch: yes - name: unset restic repo and password facts set_fact: restic_repo: "{{ None }}" restic_password: "{{ None }}" restic_passwd_file: "{{ None }}" no_log: yes delegate_to: "{{ rest_server_hostname }}" - name: unset facts set_fact: rest_server_parms: "{{ None }}" rest_server_hostname: "{{ None }}"