diff --git a/README.md b/README.md index 09a7aa6..f22c5c3 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,22 @@ # Borg backup role -This role installs Borg backup on backupservers and clients. The role contains a wrapper-script 'borg-backup' to ease the usage on the client. Supported options include borg-backup info | init | list | backup | mount. Automysqlbackup will run as pre-backup command if it's installed. +This role installs Borg backup on borgbackup\_servers and clients. The role contains a wrapper-script 'borg-backup' to ease the usage on the client. Supported options include borg-backup info | init | list | backup | mount. Automysqlbackup will run as pre-backup command if it's installed. The role supports both self hosted and rsync.net as Borg server. It's possible to configure append-only repositories to secure the backups against deletion from the client. ## Required variables -Define a group backupservers in your inventory with one or multiple hosts. +Define a group borgbackup\_servers in your inventory with one or multiple hosts. The group borgbackup\_management is only necessary if you want to enable append-only mode and prune the backups from a secured hosts. ``` -infra: -[backupservers] +[borgbackup_servers] backup1.fiaas.co [borgbackup_management] supersecurehost ``` -group\_vars/all.yml: +Define group- or hostvars for your backup endpoints and retention: ``` -backupservers: +borgbackup_servers: - fqdn: backup1.fiaas.co user: borgbackup type: normal @@ -30,9 +29,14 @@ backupservers: home: "" pool: repos options: "--remote-path=borg1" + +borgbackup_retention: + hourly: 12 + daily: 7 + weekly: 4 + monthly: 6 + yearly: 1 ``` -Contains the list of server you want to use on a certain client. -Allows to override backup servers on group or host level. *WARNING: the trailing / in item.home is required.* Define a borg\_passphrase for every host. diff --git a/tasks/borg-client.yml b/tasks/borg-client.yml index 09a89a4..7227a77 100644 --- a/tasks/borg-client.yml +++ b/tasks/borg-client.yml @@ -28,7 +28,7 @@ key_options: 'command="cd {{ item.home }}{{ item.pool }}/{{ inventory_hostname }};borg serve {% if borgbackup_appendonly %}--append-only {% endif %}--restrict-to-path {{ item.home }}/{{ item.pool }}/{{ inventory_hostname }}",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,no-user-rc' delegate_to: "{{ item.fqdn }}" when: item.type == 'normal' - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" # rsync.net has no python, so we can only use raw to manage ssh keys - workaround with local tmp file - name: client | get rsync.net authorized_keys file @@ -36,7 +36,7 @@ delegate_to: localhost become: no when: item.type == 'rsync.net' - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" changed_when: false - name: client | modify local rsync.net authorized_keys @@ -49,7 +49,7 @@ delegate_to: localhost become: no when: item.type == 'rsync.net' - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" register: authkeys - name: client | upload local authorized_keys to rsync.net @@ -57,7 +57,7 @@ delegate_to: localhost become: no when: item.type == 'rsync.net' and authkeys.changed - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" - name: client | remove tmp authorized_keys files file: @@ -65,7 +65,7 @@ state: absent delegate_to: localhost become: no - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" when: authkeys.changed changed_when: false diff --git a/tasks/borg-server.yml b/tasks/borg-server.yml index 8127678..45e47f6 100644 --- a/tasks/borg-server.yml +++ b/tasks/borg-server.yml @@ -8,7 +8,7 @@ mode: "0755" url: "{{ borgbackup_download_url }}" delegate_to: "{{ item.fqdn }}" - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" when: item.type == 'normal' - name: server | create user @@ -18,7 +18,7 @@ home: "{{ item.home }}" createhome: "yes" delegate_to: "{{ item.fqdn }}" - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" when: item.type == 'normal' - name: server | create directories @@ -28,4 +28,4 @@ owner: "{{ item.user }}" group: "{{ item.user }}" mode: "0770" - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" diff --git a/tasks/main.yml b/tasks/main.yml index 357a756..1bcdef8 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,17 +2,17 @@ - include: install.yml when: > borgbackup_required == True or - inventory_hostname in groups.backupservers + inventory_hostname in groups.borgbackup_servers - include: borg-server.yml - when: inventory_hostname in groups.backupservers + when: inventory_hostname in groups.borgbackup_servers - include: borg-client.yml when: > borgbackup_required == True and - inventory_hostname not in groups.backupservers + inventory_hostname not in groups.borgbackup_servers - include: management.yml when: > inventory_hostname in groups.borgbackup_management and - inventory_hostname not in groups.backupservers + inventory_hostname not in groups.borgbackup_servers diff --git a/tasks/management.yml b/tasks/management.yml index 0bb30fc..f27a43e 100644 --- a/tasks/management.yml +++ b/tasks/management.yml @@ -13,7 +13,7 @@ key: "{{ borgbackup_management_sshkey }}" delegate_to: "{{ item.fqdn }}" when: item.type == 'normal' - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" # rsync.net has no python, so we can only use raw to manage ssh keys - workaround with local tmp file @@ -22,7 +22,7 @@ delegate_to: localhost become: no when: item.type == 'rsync.net' - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" changed_when: false - name: management | modify local rsync.net authorized_keys @@ -34,7 +34,7 @@ delegate_to: localhost become: no when: item.type == 'rsync.net' - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" register: authkeys - name: management | upload local authorized_keys to rsync.net @@ -42,7 +42,7 @@ delegate_to: localhost become: no when: item.type == 'rsync.net' and authkeys.changed - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" - name: management | remove tmp authorized_keys files file: @@ -50,6 +50,6 @@ state: absent delegate_to: localhost become: no - with_items: "{{ backupservers }}" + with_items: "{{ borgbackup_servers }}" when: authkeys.changed changed_when: false diff --git a/templates/borg-backup.sh.j2 b/templates/borg-backup.sh.j2 index d01d21d..0e7bd60 100644 --- a/templates/borg-backup.sh.j2 +++ b/templates/borg-backup.sh.j2 @@ -14,7 +14,7 @@ fi if [ "$1" = "info" ] then if [ -z "$2" ]; then printf "run $0 with list and use the backup-tag to request information\n"; exit 1; fi -{% for b in backupservers %} +{% for b in borgbackup_servers %} REPOSITORY={{ b.user }}@{{ b.fqdn }}:{{ b.home }}{{ b.pool }}/{{ inventory_hostname }} /usr/local/bin/borg info $REPOSITORY::$2 {{ b.options }} {% endfor %} @@ -26,7 +26,7 @@ if [ "$1" = "mount" ] if [ -z "$2" ]; then printf "Select the backup-server\n"; exit 1; fi if [ -z "$3" ]; then printf "Select the backup to mount\n"; exit 1; fi if [ -z "$4" ]; then printf "Select the path to mount the backup on\n"; exit 1; fi -{% for b in backupservers %} +{% for b in borgbackup_servers %} REPOSITORY={{ b.user }}@{{ b.fqdn }}:{{ b.home }}{{ b.pool }}/{{ inventory_hostname }} /usr/local/bin/borg mount $REPOSITORY::$3 $4 {{ b.options }} if [ "$?" = "0" ]; then printf "Backup mounted on $4, do not forget to unmount!\n"; fi @@ -36,7 +36,7 @@ fi if [ "$1" = "list" ] then -{% for b in backupservers %} +{% for b in borgbackup_servers %} REPOSITORY={{ b.user }}@{{ b.fqdn }}:{{ b.home }}{{ b.pool }}/{{ inventory_hostname }} printf "Archives on {{ b.fqdn }} :\n" /usr/local/bin/borg list -v $REPOSITORY {{ b.options }} @@ -46,7 +46,7 @@ fi if [ "$1" = "init" ] then -{% for b in backupservers %} +{% for b in borgbackup_servers %} REPOSITORY={{ b.user }}@{{ b.fqdn }}:{{ b.home }}{{ b.pool }}/{{ inventory_hostname }} borg init $REPOSITORY {{ b.options }} {% endfor %} @@ -62,7 +62,7 @@ if [ "$1" = "backup" ] {{ precommand }} {% endfor %} -{% for b in backupservers %} +{% for b in borgbackup_servers %} printf "Backing up to {{ b.fqdn }} :\n" REPOSITORY={{ b.user }}@{{ b.fqdn }}:{{ b.home }}{{ b.pool }}/{{ inventory_hostname }} diff --git a/templates/prune.sh.j2 b/templates/prune.sh.j2 index 7157dda..f01bb2a 100644 --- a/templates/prune.sh.j2 +++ b/templates/prune.sh.j2 @@ -5,9 +5,9 @@ # Don't put it on the backup server, it contains all borg secrets! {% for h in groups['all'] %} - {% if hostvars[h].borgbackup_required is defined and hostvars[h].borgbackup_required %} + {% if hostvars[h].borgbackup_required | default(True) %} # Host: {{ h }} - {% for b in hostvars[h].backupservers %} + {% for b in hostvars[h].borgbackup_servers %} {% if hostvars[h].borgbackup_managementstation is defined and inventory_hostname == hostvars[h].borgbackup_managementstation %} export BORG_PASSPHRASE={{ hostvars[h].borgbackup_passphrase }} REPOSITORY={{ b.user }}@{{ b.fqdn }}:{{ b.home }}{{ b.pool }}/{{ h }} diff --git a/templates/ssh.config.j2 b/templates/ssh.config.j2 index ac4f8a1..0b80232 100644 --- a/templates/ssh.config.j2 +++ b/templates/ssh.config.j2 @@ -1,5 +1,5 @@ # backup hosts -{% for b in backupservers %} +{% for b in borgbackup_servers %} Host {{ b.fqdn }} StrictHostKeyChecking no {% if b.port is defined %}