---
# This ansible-playbook prepares hosts for use of borg backup
#
# What it does:
#   - enable borg ppa
#   - install borg client
#   - create SSH key for passwordless login
#   - generate passphrase for borgi (/root/backup/.borg_passphrase)
#   - add SSH key at remote storagebox authorized_keys
#   - create borg dirs (log, root/backup)
#   - create scripts in /root/backup/ for borg handling
#   - initialize backup repo on remote machine(s) running borg-init.sh
#   - install CRON jobs for regular backups
#   - download generated keyfiles/passwords to local machine (borg-creds/)
#
##
#
# This playbook will normally be run like this:
#
#  ansible-playbook -b -i h8.waeup.org, --ask-vault-pass playbook-install-borg.yml
#
# Cf.: https://github.com/noplanman/ansible-role-borgbackup/blob/master/tasks/borg-client.yml
#
##
#
# PLEASE NOTE: this playbook requires a gazillion parameters to be set via host vars.
#              As some of these are hopefully encrypted, you also need the respective
#              passwords.
#
##
- hosts: h9.waeup.org
  become: yes
  vars:
  tasks:
  - name: "Activate borg PPA"
    apt_repository:
        repo: "ppa:costamagnagianfranco/borgbackup"
        codename: "{{ ansible_distribution_release }}"
        state: present

  - name: "Install packages for borg backup"
    apt:
        name: ['borgbackup', 'pwgen', 'sshpass']
        state: present

  - name: "Generate ssh-key for backup."
    openssh_keypair:
        path: "/root/.ssh/id_backup"
        type: "ed25519"
    register: sshkey

  - name: "Create directories for config and logs."
    file:
        path: '{{ item.path }}'
        state: directory
        owner: root
        group: root
        mode: '{{ item.mode }}'
    loop:
        - { path: '/root/backup', mode: '0700' }
        - { path: '/var/log/borg', mode: '0755' }

  - name: "Generate a backup password."
    shell:
        cmd: echo 'export BORG_PASSPHRASE="'$(pwgen -s -1 64)'"' > "/root/backup/.borg_passphrase"
        creates: "/root/backup/.borg_passphrase"

  - name: "Fix file permissions of password."
    file:
        path: '/root/backup/.borg_passphrase'
        owner: root
        group: root
        mode: '0600'

  - name: "Get authorized_keys from backup server"
    shell:
        cmd: >
            SSHPASS={{ item.password }}
            sshpass -e scp
            -o BatchMode=no -o StrictHostKeyChecking=no
            {{ item.user }}@{{ item.fqdn }}:.ssh/authorized_keys
            /tmp/authkeys-{{ item.type }}-{{ item.fqdn }}-authkeys
    when: item.type in ['hetzner',]
    with_items: "{{ borgbackup_servers }}"
    changed_when: false
    failed_when: false

  - name: "update authorized_keys"
    authorized_key:
        user: "root"
        key: "{{ sshkey.public_key }}"
        path: /tmp/authkeys-{{ item.type }}-{{ item.fqdn }}-authkeys
        manage_dir: false
    when: item.type in ['hetzner', ]
    with_items: "{{ borgbackup_servers }}"
    register: authkeys

  - name: "Upload changed authorized_keys"
    shell:
        cmd: |
            SSHPASS={{ item.password }} sshpass -e sftp -oBatchMode=no -oStrictHostKeyChecking=no {{ item.user }}@{{ item.fqdn }} << EOF
              mkdir ./.ssh
              chmod 0700 ./.ssh
              cd .ssh
              put /tmp/authkeys-{{ item.type }}-{{ item.fqdn }}-authkeys authorized_keys
              chmod 0600 authorized_keys
              bye
            EOF
    when: (item.type in ['hetzner', ]) and (authkeys.changed)
    with_items: "{{ borgbackup_servers }}"

  - name: "Remove tmp authorized_keys files"
    file:
        path: /tmp/authkeys-{{ item.type }}-{{ item.fqdn }}-authkeys
        state: absent
    with_items: "{{ borgbackup_servers }}"

  - name: "Disable strict host key checks for backup server"
    blockinfile:
        dest: "/root/.ssh/config"
        create: true
        marker: "### {mark} ANSIBLE MANAGED BLOCK {{ item.fqdn }} ###"
        content: |
            Host {{ item.fqdn  }}
              StrictHostKeyChecking no
              IdentityFile /root/.ssh/id_backup
              {% if item.port is defined %}Port {{ item.port }}{% endif %}
    with_items: "{{ borgbackup_servers }}"

  - name: "Upload borg-init.sh script"
    template:
        src: "borg-init.sh.j2"
        dest: "/root/backup/borg-init.sh"
        owner: "root"
        group: "root"
        mode: "0744"
        force: no

  - name: "Upload borg-backup.sh script"
    template:
        src: "borg-backup.sh.j2"
        dest: "/root/backup/borg-backup.sh"
        owner: "root"
        group: "root"
        mode: "0744"
        force: no

  - name: "Upload sb-ftp.sh script"
    template:
        src: "sb-ftp.sh.j2"
        dest: "/root/backup/sb-ftp.sh"
        owner: "root"
        group: "root"
        mode: "0744"
        force: no

  - name: "Create env scripts"
    template:
        src: "borg-env.sh.j2"
        dest: "/root/backup/env-{{ item.fqdn }}.sh"
        owner: "root"
        group: "root"
        mode: "0600"
        force: no
    with_items: "{{ borgbackup_servers }}"

  - name: "Initialize repo"
    command: /root/backup/borg-init.sh
    args:
        creates: /root/.config/borg/keys/

  - name: "Create backup cronjob"
    cron:
      cron_file: "borg-backup"
      user: "root"
      name: "borg-backup"
      minute: "{{ borgbackup_cron_minute }}"
      hour: "{{ borgbackup_cron_hour }}"
      day: "{{ borgbackup_cron_day }}"
      job: "/root/backup/borg-backup.sh > /dev/null 2>&1"

  - name: "Fetch keyfiles to localhost"
    fetch:
      src: /root/.config/borg/keys/{{ item.fqdn | replace('.', '_') | replace('-', '_') }}__{{ item.home }}{{ item.pool }}_{{ inventory_hostname_short }}
      dest: borg-creds/
      flat: yes
    with_items: "{{ borgbackup_servers }}"

  - name: "Fetch passwordfile to localhost"
    fetch:
      src: /root/backup/.borg_passphrase
      dest: borg-creds/_borg_passphrase-{{ inventory_hostname_short }}
      flat: yes

  - debug:
      msg:
         - "A copy of the keyfile and the borg password were saved to the"
         - "local borg-creds/ directory."
         - "Please keep them in a safe place, away from the backup machine"
         - "and the backuped machine. You might want to encrypt them."

