From 5b953c8dba0d7d4be10f93dfa10da975e5be1294 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Tue, 9 Jul 2019 11:45:03 +0200 Subject: Added borg backup role --- defaults/main.yml | 3 ++ files/borg.fact | 18 ++++++++++ tasks/client.yml | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ tasks/common.yml | 25 ++++++++++++++ tasks/main.yml | 10 ++++++ tasks/server.yml | 26 +++++++++++++++ templates/backup.sh.j2 | 11 +++++++ vars/Alpine.yml | 4 +++ vars/Gentoo.yml | 4 +++ vars/OpenBSD.yml | 4 +++ vars/RedHat.yml | 4 +++ 11 files changed, 198 insertions(+) create mode 100644 defaults/main.yml create mode 100644 files/borg.fact create mode 100644 tasks/client.yml create mode 100644 tasks/common.yml create mode 100644 tasks/main.yml create mode 100644 tasks/server.yml create mode 100644 templates/backup.sh.j2 create mode 100644 vars/Alpine.yml create mode 100644 vars/Gentoo.yml create mode 100644 vars/OpenBSD.yml create mode 100644 vars/RedHat.yml diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..c798f67 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,3 @@ +--- +borg_prune_arguments: '--keep-within 30d' +... diff --git a/files/borg.fact b/files/borg.fact new file mode 100644 index 0000000..555143d --- /dev/null +++ b/files/borg.fact @@ -0,0 +1,18 @@ +#!/bin/sh + +echo '{' +if [ -e '/root/.ssh/borg.pub' ]; then + pubkey=`cat /root/.ssh/borg.pub | tr -d "\n"` + echo -ne ' "pubkey": "'$pubkey'"' + pubkey_prefix=",\n" +fi +if [ -e '/srv/borg/repos/' ]; then + echo -ne "${pubkey_prefix:-}"' "repos": {'"\n" + for repo in `ls /srv/borg/repos/`; do + id=`awk '/^id =/ {print $3}' /srv/borg/repos/${repo}/config` + echo -ne ${repo_prefix:-}' "'$repo'": "'$id'"' + repo_prefix=",\n" + done + echo -ne "\n }" +fi +echo -ne "\n}" diff --git a/tasks/client.yml b/tasks/client.yml new file mode 100644 index 0000000..b4c4b22 --- /dev/null +++ b/tasks/client.yml @@ -0,0 +1,89 @@ +--- +- name: generate borg ssh key on client + openssh_keypair: + owner: root + mode: 0400 + path: /root/.ssh/borg + type: ed25519 + register: borg_ssh_key + +- name: reload ansible_local + setup: filter=ansible_local + when: borg_ssh_key.changed + +- name: Enforce borg authorized key on server + authorized_key: + user: borg + key: "{{ ansible_local.borg.pubkey }}" + key_options: 'command="cd /srv/borg/repos/{{ ansible_hostname }}; borg serve --restrict-to-path /srv/borg/repos/{{ ansible_hostname }}",restrict' + delegate_to: "{{ borg_server }}" + +- name: create borg client repo directory on server + file: + path: "/srv/borg/repos/{{ ansible_hostname }}" + state: directory + owner: borg + mode: 0700 + delegate_to: "{{ borg_server }}" + +- name: create borg client repo on server + command: "borg init --encryption=none /srv/borg/repos/{{ ansible_hostname }}" + become: yes + become_method: su + become_user: borg + delegate_to: "{{ borg_server }}" + args: + creates: "/srv/borg/repos/{{ ansible_hostname }}/config" + +- name: reload ansible_local + setup: filter=ansible_local + delegate_to: "{{ borg_server }}" + delegate_facts: True + when: hostvars[borg_server]['ansible_local']['borg']['repos'][ansible_hostname] is not defined + +- name: make the server known to the client + lineinfile: + line: "{{ borg_server }} ecdsa-sha2-nistp256 {{ hostvars[borg_server]['ansible_ssh_host_key_ecdsa_public'] }}" + path: /root/.ssh/known_hosts + create: yes + +- name: make the repo directory on the client + file: + state: directory + path: "/root/.config/borg/security/{{ hostvars[borg_server]['ansible_local']['borg']['repos'][ansible_hostname] }}" + owner: root + mode: 0700 + +- name: make the repo known to the client + copy: + dest: "/root/.config/borg/security/{{ hostvars[borg_server]['ansible_local']['borg']['repos'][ansible_hostname] }}/key-type" + content: "2" + owner: root + mode: 0600 + +- name: deploy borg backup script + template: + dest: /usr/local/bin/adyxax_backup.sh + src: backup.sh.j2 + owner: root + mode: 0500 + +- name: activate borg cron on alpine + lineinfile: + line: '0 23 * * * /usr/local/bin/adyxax_backup.sh' + path: /etc/crontabs/root + when: ansible_os_family == 'Alpine' + +- name: activate borg cron on gentoo or redhat + file: + state: link + src: /usr/local/bin/adyxax_backup.sh + dest: /etc/cron.daily/backup + when: ansible_os_family == 'Gentoo' or ansible_os_family == 'RedHat' + +- name: activate borg cron on openbsd + lineinfile: + line: '0 23 * * * /usr/local/bin/adyxax_backup.sh' + path: /var/cron/tabs/root + when: ansible_os_family == 'OpenBSD' +... diff --git a/tasks/common.yml b/tasks/common.yml new file mode 100644 index 0000000..057cd25 --- /dev/null +++ b/tasks/common.yml @@ -0,0 +1,25 @@ +--- +- name: set distro-specific server variables + include_vars: '{{ ansible_os_family }}.yml' + +- name: Check if borg is supported on distro + fail: + msg: "borg tasks are not supported on this operating system yet." + when: borg_packages is not defined + +- name: Ensure borg is installed + package: + name: "{{ borg_packages }}" + +- name: Push borg gathering fact on client + copy: + src: borg.fact + dest: /etc/ansible/facts.d/ + mode: 0500 + owner: root + register: borg_gathering_fact + +- name: reload ansible_local + setup: filter=ansible_local + when: borg_gathering_fact.changed +... diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..e49b440 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,10 @@ +--- +- import_tasks: common.yml + when: (is_borg_server|default(false)) or borg_server is defined + +- import_tasks: server.yml + when: (is_borg_server|default(false)) + +- import_tasks: client.yml + when: borg_server is defined +... diff --git a/tasks/server.yml b/tasks/server.yml new file mode 100644 index 0000000..bd40dab --- /dev/null +++ b/tasks/server.yml @@ -0,0 +1,26 @@ +--- +- name: Create borg group on server + group: + name: borg + system: yes + +- name: Create borg user on server + user: + name: borg + shell: /bin/sh + home: /srv/borg + createhome: yes + system: yes + password_lock: yes + +- name: Ensure borg directories exist on server + file: + state: directory + path: "{{ item }}" + owner: borg + mode: 0700 + loop: + - /srv/borg + - /srv/borg/.ssh + - /srv/borg/repos +... diff --git a/templates/backup.sh.j2 b/templates/backup.sh.j2 new file mode 100644 index 0000000..a029080 --- /dev/null +++ b/templates/backup.sh.j2 @@ -0,0 +1,11 @@ +#!/bin/sh + +{% for job in borg_jobs %} +{% if job.command_to_pipe is defined %} +{{ job.command_to_pipe }} | BORG_RSH="ssh -i /root/.ssh/borg" borg create borg@{{ borg_server }}:/srv/borg/repos/{{ ansible_hostname }}::{{ job.name }}-{now} {{ job.path | default('-') }} +{% else %} +BORG_RSH="ssh -i /root/.ssh/borg" borg create borg@{{ borg_server }}:/srv/borg/repos/{{ ansible_hostname }}::{{ job.name }}-{now} {{ job.path }} +{% endif %} +{% endfor %} + +BORG_RSH="ssh -i /root/.ssh/borg" borg prune borg@{{ borg_server }}:/srv/borg/repos/{{ ansible_hostname }} {{ borg_prune_arguments }} diff --git a/vars/Alpine.yml b/vars/Alpine.yml new file mode 100644 index 0000000..ff545b1 --- /dev/null +++ b/vars/Alpine.yml @@ -0,0 +1,4 @@ +--- +borg_packages: + - 'borgbackup' +... diff --git a/vars/Gentoo.yml b/vars/Gentoo.yml new file mode 100644 index 0000000..a9eb31c --- /dev/null +++ b/vars/Gentoo.yml @@ -0,0 +1,4 @@ +--- +borg_packages: + - 'app-backup/borgbackup' +... diff --git a/vars/OpenBSD.yml b/vars/OpenBSD.yml new file mode 100644 index 0000000..ff545b1 --- /dev/null +++ b/vars/OpenBSD.yml @@ -0,0 +1,4 @@ +--- +borg_packages: + - 'borgbackup' +... diff --git a/vars/RedHat.yml b/vars/RedHat.yml new file mode 100644 index 0000000..83a9fbe --- /dev/null +++ b/vars/RedHat.yml @@ -0,0 +1,4 @@ +--- +borg_packages: + - borgbackup +... -- cgit v1.2.3