diff --git a/ansible/inventories/distributed.yaml b/ansible/inventories/distributed.yaml index d251e2b..8e5af4b 100644 --- a/ansible/inventories/distributed.yaml +++ b/ansible/inventories/distributed.yaml @@ -4,7 +4,7 @@ new_sudo: hserve1: hserve2: mini1: - + backs.hassallab.it: distributed: @@ -28,4 +28,7 @@ distributed: forgejo: hosts: hserve1: + borg: + hosts: + backs.hassallab.it: diff --git a/ansible/inventories/group_vars/all/borg.yaml b/ansible/inventories/group_vars/all/borg.yaml new file mode 100644 index 0000000..94b8f8f --- /dev/null +++ b/ansible/inventories/group_vars/all/borg.yaml @@ -0,0 +1,4 @@ +--- +borg_user: borg +borg_backup_server: backs.hassallab.it +borg_repo_base_path: "ssh://{{ borg_user }}@{{ borg_backup_server }}/./" \ No newline at end of file diff --git a/ansible/inventories/group_vars/borg/auth_users.yaml b/ansible/inventories/group_vars/borg/auth_users.yaml new file mode 100644 index 0000000..1e1e04a --- /dev/null +++ b/ansible/inventories/group_vars/borg/auth_users.yaml @@ -0,0 +1,3 @@ +# auth_users: +# - host: johndoe.clnt.local +# key: "{{ lookup('file', '/path/to/keys/johndoe.clnt.local.pub') }}" diff --git a/ansible/playbooks/borg_server.yaml b/ansible/playbooks/borg_server.yaml new file mode 100644 index 0000000..ffdd33b --- /dev/null +++ b/ansible/playbooks/borg_server.yaml @@ -0,0 +1,28 @@ +--- +- hosts: backup01.srv.local + vars: + user: backup + group: backup + home: /home/backup + pool: "{{ home }}/repos" + auth_users: + - host: johndoe.clnt.local + key: "{{ lookup('file', '/path/to/keys/johndoe.clnt.local.pub') }}" + - host: web01.clnt.local + key: "{{ lookup('file', '/path/to/keys/web01.clnt.local.pub') }}" + - host: app01.clnt.local + key: "{{ lookup('file', '/path/to/keys/app01.clnt.local.pub') }}" + tasks: + - package: name=borg state=present + - group: name="{{ group }}" state=present + - user: name="{{ user }}" shell=/bin/bash home="{{ home }}" createhome=yes group="{{ group }}" groups= state=present + - file: path="{{ home }}" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory + - file: path="{{ home }}/.ssh" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory + - file: path="{{ pool }}" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory + - authorized_key: user="{{ user }}" + key="{{ item.key }}" + key_options='command="cd {{ pool }}/{{ item.host }};borg serve --restrict-to-path {{ pool }}/{{ item.host }}",restrict' + with_items: "{{ auth_users }}" + - file: path="{{ home }}/.ssh/authorized_keys" owner="{{ user }}" group="{{ group }}" mode=0600 state=file + - file: path="{{ pool }}/{{ item.host }}" owner="{{ user }}" group="{{ group }}" mode=0700 state=directory + with_items: "{{ auth_users }}" diff --git a/ansible/playbooks/roles/borg/defaults/main.yaml b/ansible/playbooks/roles/borg/defaults/main.yaml new file mode 100644 index 0000000..6e160ce --- /dev/null +++ b/ansible/playbooks/roles/borg/defaults/main.yaml @@ -0,0 +1,10 @@ +--- +borg_user: borg +borg_group: borg +borg_home: /home/borg +borg_pool: "{{ borg_home }}/repos" +borg_pool_dest : /usr/backups/borg_repos +auth_users: + - host: hserve1 + # Chiave di esempio per test + key: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArNhKFcJ6T08sn7kTTLf+rO9HEvgOvqfhv5HQ2sRf2tFYfjfCb0zHKnMkgW+sy5gMU10Lyx1r7juXCvqRC955uIM97m1B1Xc6sVqASVKuGPhCKfhxEaMAyBcWFdE+HYbCOPYVN+JMrcwWfbblwiZTtK1OCqaEUvDDI7cFeU68noXwggEp46T48eqMUdi541D9Y+BVx9HYAo6OCQz0+6eXwxJL+tpRcAAXIMMWv362CYHoOgIU45R7xVSMLY1k/HLrcEAblwxEaSpduCH5cWUXZE/56IyxpvP44BxZkVhNdqJLmg4hxBQWhoMNYiTZxbLay3W2TwBCM111cAtUx4M/jQ==" \ No newline at end of file diff --git a/ansible/playbooks/roles/borg/tasks/configure_borg_client.yaml b/ansible/playbooks/roles/borg/tasks/configure_borg_client.yaml new file mode 100644 index 0000000..e69de29 diff --git a/ansible/playbooks/roles/borg/tasks/configure_borg_server.yaml b/ansible/playbooks/roles/borg/tasks/configure_borg_server.yaml new file mode 100644 index 0000000..06ee884 --- /dev/null +++ b/ansible/playbooks/roles/borg/tasks/configure_borg_server.yaml @@ -0,0 +1,46 @@ +--- +- name: Set borg user group + group: + name: "{{ borg_group }}" + state: present + +- name: Set borg user + user: + name: "{{ borg_user }}" + shell: /bin/bash + home: "{{ borg_home }}" + createhome: yes + group: "{{ borg_group }}" + state: present + +- name: Set home directory + file: + path: "{{ borg_home }}" + owner: "{{ borg_user }}" + group: "{{ borg_group }}" + mode: "0700" + state: directory + +- name: Set ssh directory + file: + path: "{{ borg_home }}/.ssh" + owner: "{{ borg_user }}" + group: "{{ borg_group }}" + mode: "0700" + state: directory + +- name: Set pool directory link + file: + src: "{{ borg_pool }}" + dest: "{{ borg_pool_dest }}" + state: link + + +- name: Add authorized keys + authorized_key: + user: "{{ borg_user }}" + key: "{{ item.key }}" + key_options: "command=cd {{ borg_pool }}/{{ item.host }};borg serve --restrict-to-path {{ borg_pool }}/{{ item.host }},restrict" + with_items: "{{ borg_auth_users }}" + + diff --git a/ansible/playbooks/roles/borg/tasks/main.yaml b/ansible/playbooks/roles/borg/tasks/main.yaml new file mode 100644 index 0000000..e493ba7 --- /dev/null +++ b/ansible/playbooks/roles/borg/tasks/main.yaml @@ -0,0 +1,8 @@ +--- +include_tasks: prepare_borg.yaml +include_tasks: configure_borg_server.yaml + when: + - configure_borg_server +include_tasks: configure_borg_client.yaml + when: + - configure_borg_client \ No newline at end of file diff --git a/ansible/playbooks/roles/borg/tasks/prepare_borg.yaml b/ansible/playbooks/roles/borg/tasks/prepare_borg.yaml new file mode 100644 index 0000000..89a8adb --- /dev/null +++ b/ansible/playbooks/roles/borg/tasks/prepare_borg.yaml @@ -0,0 +1,6 @@ +--- +- name: Install borg and requirements +- package: + name: borg + state: present + diff --git a/ansible/playbooks/roles/borg/templates/backup_script.sh.j2 b/ansible/playbooks/roles/borg/templates/backup_script.sh.j2 new file mode 100644 index 0000000..12a36b0 --- /dev/null +++ b/ansible/playbooks/roles/borg/templates/backup_script.sh.j2 @@ -0,0 +1,86 @@ +#!/bin/bash +{% for repo_item in borg_repos %} + +# Setting this, so the repo does not need to be given on the commandline: +export BORG_REPO="{{borg_repo_base}}{{repo_item.name}}" + +# See the section "Passphrase notes" for more infos. +export BORG_PASSPHRASE="'{{ repo_item.borg_passphrase }}'" + +# some helpers and error handling: +info() { logger "$*"; } +trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM + +info "Trying to initialize repo. NB returns error if already initialized" +borg init --encryption=repokey + +info "Starting backup for repo {{repo_item.name}}" + +# Backup the most important directories into an archive named after +# the machine this script is currently running on: + +borg create \ + --verbose \ + --filter AME \ + --list \ + --stats \ + --show-rc \ + --compression lz4 \ + --exclude-caches \ + --exclude 'home/*/.cache/*' \ + --exclude 'var/tmp/*' \ + \ + ::"'{{ inventory_hostname }}-{now}'"\ + {% for item in repo_item.paths_to_backup %} + {{ item }}\ + {% endfor %} + +backup_exit=$? + +info "Pruning repository {{ repo_item.name }}" + +# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly +# archives of THIS machine. The '{hostname}-*' matching is very important to +# limit prune's operation to this machine's archives and not apply to +# other machines' archives also: + +borg prune \ + --list \ + --glob-archives "'{{ inventory_hostname }}-*'" \ + --show-rc \ + --keep-daily 7 \ + --keep-weekly 4 \ + --keep-monthly 6 + +prune_exit=$? + +# actually free repo disk space by compacting segments + +info "Compacting repository {{ repo_item.name }}" + +borg compact + +compact_exit=$? + +# use highest exit code as global exit code +global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit )) +global_exit=$(( compact_exit > global_exit ? compact_exit : global_exit )) + +if [ ${global_exit} -eq 0 ]; then + info "Backup, Prune, and Compact finished successfully" +elif [ ${global_exit} -eq 1 ]; then + info "Backup, Prune, and/or Compact finished with warnings" +else + info "Backup, Prune, and/or Compact finished with errors" +fi + + +# end loop for repos + +{% endfor %} + + +exit ${global_exit} + + + diff --git a/ansible/playbooks/roles/borg/templates/borg_backup.service.j2 b/ansible/playbooks/roles/borg/templates/borg_backup.service.j2 new file mode 100644 index 0000000..578173b --- /dev/null +++ b/ansible/playbooks/roles/borg/templates/borg_backup.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=Borg Backup + +[Service] +Type=oneshot +User={{ borg_user }} +ExecStart=/home/{{borg_user}}/backup_script.sh + +AmbientCapabilities=CAP_DAC_READ_SEARCH + +StandardOutput=journal +StandardError=journal +SyslogIdentifier=borg \ No newline at end of file