From 6e49d2b6c76bdc11c42fb292f7bdafc95e492d51 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Thu, 11 Feb 2021 19:10:38 +0100 Subject: Revitalized the borg role --- README | 16 ++++++++++++++++ files/borg.fact | 26 ++++++++++++++------------ tasks/client.yml | 35 ++++++++++------------------------- tasks/client_Alpine.yml | 6 ++++++ tasks/client_Gentoo.yml | 7 +++++++ tasks/client_OpenBSD.yml | 7 +++++++ tasks/client_RedHat.yml | 7 +++++++ tasks/client_Ubuntu.yml | 7 +++++++ tasks/server.yml | 1 + templates/backup.sh.j2 | 6 ++++++ vars/Debian.yml | 4 ++++ 11 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 README create mode 100644 tasks/client_Alpine.yml create mode 100644 tasks/client_Gentoo.yml create mode 100644 tasks/client_OpenBSD.yml create mode 100644 tasks/client_RedHat.yml create mode 100644 tasks/client_Ubuntu.yml create mode 100644 vars/Debian.yml diff --git a/README b/README new file mode 100644 index 0000000..98d7b5b --- /dev/null +++ b/README @@ -0,0 +1,16 @@ +There are several variables you can define to configure a machines response to the borg role : +- is_borg_server: a boolean that indicates if a machine will act as a borg server +- borg_server: a string that contains a borg servers hostname +- borg_jobs: a list of dict, one item per job with the following keys: + - name: the name of the borg job + - path: an optional path containing the files to backup + - command_to_pipe: an optional command to pipe the backup data from + - pre_command: an optional command to run before a job + - post_command: an optional command to run after a job + +To be valid, a borg job entry needs to have exactly one of the path or command_to_pipe keys. + +Here are some job examples : +- { name: etc, path: "/etc" } +- { name: mysqldump, command_to_pipe: "/usr/bin/mysqldump -h {{ mysql_server }} -u{{ ansible_hostname }} -p{{ ansible_local.mysql_client.password }} --single-transaction --add-drop-database -B {{ ansible_hostname }}" } +- { name: gitea, path: "/tmp/gitea.zip", pre_command: "echo '/usr/local/sbin/gitea -C /etc/gitea -c /etc/gitea/app.ini dump -f /tmp/gitea.zip' | su -l _gitea", post_command: "rm -f /tmp/gitea.zip" } diff --git a/files/borg.fact b/files/borg.fact index ee6504c..a27d5b0 100644 --- a/files/borg.fact +++ b/files/borg.fact @@ -4,19 +4,21 @@ # ~~~~ ~~~~ # ############################################################################### -echo '{' +printf "{\n" if [ -e '/root/.ssh/borg.pub' ]; then - pubkey=`cat /root/.ssh/borg.pub | tr -d "\n"` - echo -ne ' "pubkey": "'$pubkey'"' - pubkey_prefix=",\n" + pubkey=`cat /root/.ssh/borg.pub | tr -d "\n"` + printf " \"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 }" + printf "${pubkey_prefix:-} \"repos\": {\n" + for repo in `ls /srv/borg/repos/`; do + if [ -e "/srv/borg/repos/${repo}/config" ]; then + id=`awk '/^id =/ {print $3}' /srv/borg/repos/${repo}/config` + printf "${repo_prefix:-} \"$repo\": \"$id\"" + repo_prefix=",\n" + fi + done + printf "\n }" fi -echo -ne "\n}" +printf "\n}" diff --git a/tasks/client.yml b/tasks/client.yml index 7eedbe7..0ae0142 100644 --- a/tasks/client.yml +++ b/tasks/client.yml @@ -27,10 +27,7 @@ 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 + shell: "echo \"borg init --encryption=none /srv/borg/repos/{{ ansible_hostname }}\" | su -l borg" delegate_to: "{{ borg_server }}" args: creates: "/srv/borg/repos/{{ ansible_hostname }}/config" @@ -56,10 +53,15 @@ - 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" + dest: "/root/.config/borg/security/{{ hostvars[borg_server]['ansible_local']['borg']['repos'][ansible_hostname] }}/{{ item.dest }}" + content: "{{ item.content }}" owner: root mode: 0600 + loop: + - { dest: key-type, content: "2" } + - { dest: location, content: "ssh://borg@{{ borg_server }}/srv/borg/repos/{{ ansible_hostname }}" } + - { dest: manifest-timestamp, content: "{{ ansible_date_time['iso8601_micro'] }}" } + changed_when: false - name: deploy borg backup script template: @@ -68,23 +70,6 @@ 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' - notify: restart openbsd cron +- name: Run OS specific tasks + include_tasks: "roles/borg/tasks/client_{{ ansible_distribution }}.yml" ... diff --git a/tasks/client_Alpine.yml b/tasks/client_Alpine.yml new file mode 100644 index 0000000..3334be5 --- /dev/null +++ b/tasks/client_Alpine.yml @@ -0,0 +1,6 @@ +--- +- name: activate borg cron + lineinfile: + line: '0 23 * * * /usr/local/bin/adyxax_backup.sh' + path: /etc/crontabs/root +... diff --git a/tasks/client_Gentoo.yml b/tasks/client_Gentoo.yml new file mode 100644 index 0000000..a6c6317 --- /dev/null +++ b/tasks/client_Gentoo.yml @@ -0,0 +1,7 @@ +--- +- name: activate borg cron + file: + state: link + src: /usr/local/bin/adyxax_backup.sh + dest: /etc/cron.daily/backup +... diff --git a/tasks/client_OpenBSD.yml b/tasks/client_OpenBSD.yml new file mode 100644 index 0000000..a566949 --- /dev/null +++ b/tasks/client_OpenBSD.yml @@ -0,0 +1,7 @@ +--- +- name: activate borg cron + lineinfile: + line: '0 23 * * * /usr/local/bin/adyxax_backup.sh' + path: /var/cron/tabs/root + notify: restart openbsd cron +... diff --git a/tasks/client_RedHat.yml b/tasks/client_RedHat.yml new file mode 100644 index 0000000..a6c6317 --- /dev/null +++ b/tasks/client_RedHat.yml @@ -0,0 +1,7 @@ +--- +- name: activate borg cron + file: + state: link + src: /usr/local/bin/adyxax_backup.sh + dest: /etc/cron.daily/backup +... diff --git a/tasks/client_Ubuntu.yml b/tasks/client_Ubuntu.yml new file mode 100644 index 0000000..a6c6317 --- /dev/null +++ b/tasks/client_Ubuntu.yml @@ -0,0 +1,7 @@ +--- +- name: activate borg cron + file: + state: link + src: /usr/local/bin/adyxax_backup.sh + dest: /etc/cron.daily/backup +... diff --git a/tasks/server.yml b/tasks/server.yml index bd40dab..c166dcf 100644 --- a/tasks/server.yml +++ b/tasks/server.yml @@ -7,6 +7,7 @@ - name: Create borg user on server user: name: borg + group: borg shell: /bin/sh home: /srv/borg createhome: yes diff --git a/templates/backup.sh.j2 b/templates/backup.sh.j2 index a5a65c9..9ac8f1d 100644 --- a/templates/backup.sh.j2 +++ b/templates/backup.sh.j2 @@ -9,11 +9,17 @@ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin export BORG_RSH="ssh -i /root/.ssh/borg" {% for job in borg_jobs %} +{% if job.pre_command is defined %} +{{ job.pre_command }} +{% endif %} {% if job.command_to_pipe is defined %} {{ job.command_to_pipe }} | borg create borg@{{ borg_server }}:/srv/borg/repos/{{ ansible_hostname }}::{{ job.name }}-{now} {{ job.path | default('-') }} {% else %} borg create borg@{{ borg_server }}:/srv/borg/repos/{{ ansible_hostname }}::{{ job.name }}-{now} {{ job.path }} {% endif %} +{% if job.post_command is defined %} +{{ job.post_command }} +{% endif %} {% endfor %} borg prune borg@{{ borg_server }}:/srv/borg/repos/{{ ansible_hostname }} {{ borg_prune_arguments }} diff --git a/vars/Debian.yml b/vars/Debian.yml new file mode 100644 index 0000000..83a9fbe --- /dev/null +++ b/vars/Debian.yml @@ -0,0 +1,4 @@ +--- +borg_packages: + - borgbackup +... -- cgit v1.2.3