support append_only mode

This commit is contained in:
Luc Stroobant 2017-10-01 19:24:50 +02:00
parent fadd36625d
commit dc72e03bb3
7 changed files with 94 additions and 6 deletions

View File

@ -2,6 +2,7 @@
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 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.
The role supports both self hosted and rsync.net as Borg server. 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 ## Required variables
Define a group backupservers in your inventory with one or multiple hosts. Define a group backupservers in your inventory with one or multiple hosts.
@ -9,6 +10,9 @@ Define a group backupservers in your inventory with one or multiple hosts.
infra: infra:
[backupservers] [backupservers]
backup1.fiaas.co backup1.fiaas.co
[borgbackup_management]
supersecurehost
``` ```
group\_vars/all.yml: group\_vars/all.yml:
@ -37,6 +41,8 @@ host\_vars\client1:
borgbackup_passphrase: Ahl9EiNohr5koosh1Wohs3Shoo3ooZ6p borgbackup_passphrase: Ahl9EiNohr5koosh1Wohs3Shoo3ooZ6p
``` ```
Set borgbackup\_appendonly: True in host or group vars if you want append-only repositories. In that case it's possible to define a hostname in borgbackup\_management\_station where a borg prune script will be configured.
*Make sure to check the configured defaults for this role, which contains the list of default locations being backed up in backup_include.* Override this in your inventory where required. *Make sure to check the configured defaults for this role, which contains the list of default locations being backed up in backup_include.* Override this in your inventory where required.
## Usage ## Usage

View File

@ -22,4 +22,7 @@ borgbackup_retention:
monthly: 6 monthly: 6
yearly: 1 yearly: 1
borgbackup_appendonly: False
borgbackup_management_station: '' borgbackup_management_station: ''
borgbackup_management_user: ''
borgbackup_management_sshkey: ''

View File

@ -25,7 +25,7 @@
authorized_key: authorized_key:
user: "{{ item.user }}" user: "{{ item.user }}"
key: "{{ sshkey.stdout }}" key: "{{ sshkey.stdout }}"
key_options: 'command="cd {{ item.home }}{{ item.pool }}/{{ inventory_hostname }};borg serve --restrict-to-path {{ item.home }}/{{ item.pool }}/{{ inventory_hostname }}",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,no-user-rc' 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 }}" delegate_to: "{{ item.fqdn }}"
when: item.type == 'normal' when: item.type == 'normal'
with_items: "{{ backupservers }}" with_items: "{{ backupservers }}"
@ -43,7 +43,7 @@
authorized_key: authorized_key:
user: "{{ ansible_user_id }}" user: "{{ ansible_user_id }}"
key: "{{ sshkey.stdout }}" key: "{{ sshkey.stdout }}"
key_options: 'command="cd {{ item.home }}{{ item.pool }}/{{ inventory_hostname }};borg serve --restrict-to-path {{ item.home }}/{{ item.pool }}/{{ inventory_hostname }}",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,no-user-rc' 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'
path: "/tmp/rsync.net-{{ item.fqdn }}-authkeys" path: "/tmp/rsync.net-{{ item.fqdn }}-authkeys"
manage_dir: no manage_dir: no
delegate_to: localhost delegate_to: localhost

View File

@ -1,5 +1,4 @@
--- ---
- include: install.yml - include: install.yml
when: > when: >
borgbackup_required == True or borgbackup_required == True or
@ -12,3 +11,8 @@
when: > when: >
borgbackup_required == True and borgbackup_required == True and
inventory_hostname not in groups.backupservers inventory_hostname not in groups.backupservers
- include: management.yml
when: >
inventory_hostname in groups.borgbackup_management and
inventory_hostname not in groups.backupservers

55
tasks/management.yml Normal file
View File

@ -0,0 +1,55 @@
---
- name: management | put management station prune script
template:
src: prune.sh.j2
dest: "~{{ borgbackup_management_user }}/prune.sh"
owner: "{{ borgbackup_management_user }}"
group: "{{ borgbackup_management_user }}"
mode: 0700
- name: management | put management sshpubkey on the normal backupserver
authorized_key:
user: "{{ item.user }}"
key: "{{ borgbackup_management_sshkey }}"
delegate_to: "{{ item.fqdn }}"
when: item.type == 'normal'
with_items: "{{ backupservers }}"
# rsync.net has no python, so we can only use raw to manage ssh keys - workaround with local tmp file
- name: management | get rsync.net authorized_keys file
raw: scp {{ item.user }}@{{ item.fqdn }}:.ssh/authorized_keys /tmp/rsync.net-{{ item.fqdn }}-authkeys
delegate_to: localhost
become: no
when: item.type == 'rsync.net'
with_items: "{{ backupservers }}"
changed_when: false
- name: management | modify local rsync.net authorized_keys
authorized_key:
user: "{{ ansible_user_id }}"
key: "{{ borgbackup_management_sshkey }}"
path: "/tmp/rsync.net-{{ item.fqdn }}-authkeys"
manage_dir: no
delegate_to: localhost
become: no
when: item.type == 'rsync.net'
with_items: "{{ backupservers }}"
register: authkeys
- name: management | upload local authorized_keys to rsync.net
raw: scp /tmp/rsync.net-{{ item.fqdn }}-authkeys {{ item.user }}@{{ item.fqdn }}:.ssh/authorized_keys
delegate_to: localhost
become: no
when: item.type == 'rsync.net' and authkeys.changed
with_items: "{{ backupservers }}"
- name: management | remove tmp authorized_keys files
file:
path: /tmp/rsync.net-{{ item.fqdn }}-authkeys
state: absent
delegate_to: localhost
become: no
with_items: "{{ backupservers }}"
when: authkeys.changed
changed_when: false

View File

@ -69,10 +69,11 @@ if [ "$1" = "backup" ]
/usr/local/bin/borg create --compression zlib,6 --stats $REPOSITORY::$date {{ b.options }} {% for dir in borgbackup_include %}{{ dir }} {% endfor %}{% if automysql.stat.isdir is defined and automysql.stat.isdir == True %}/var/lib/automysqlbackup{% endif %} /usr/local/bin/borg create --compression zlib,6 --stats $REPOSITORY::$date {{ b.options }} {% for dir in borgbackup_include %}{{ dir }} {% endfor %}{% if automysql.stat.isdir is defined and automysql.stat.isdir == True %}/var/lib/automysqlbackup{% endif %}
if [ "$?" -eq "0" ]; then printf "Backup succeeded on $date\n" >> /var/log/borg-backup.log; fi if [ "$?" -eq "0" ]; then printf "Backup succeeded on $date\n" >> /var/log/borg-backup.log; fi
# Use the `prune` subcommand to maintain 7 daily, 4 weekly {% if not borgbackup_appendonly %}
# and 6 monthly archives. # prune old backups
/usr/local/bin/borg prune -v $REPOSITORY {{ b.options }} -H {{ borgbackup_retention.hourly }} -d {{ borgbackup_retention.daily }} -w {{ borgbackup_retention.weekly }} -m {{ borgbackup_retention.monthly }} -y {{ borgbackup_retention.yearly }} /usr/local/bin/borg prune -v $REPOSITORY {{ b.options }} -H {{ borgbackup_retention.hourly }} -d {{ borgbackup_retention.daily }} -w {{ borgbackup_retention.weekly }} -m {{ borgbackup_retention.monthly }} -y {{ borgbackup_retention.yearly }}
{% endif %}
{% endfor %} {% endfor %}
fi fi

19
templates/prune.sh.j2 Normal file
View File

@ -0,0 +1,19 @@
#!/bin/bash
# This script is intended to run on a trusted management station to purge borg repo's in
# append-only mode.
# 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 %}
# Host: {{ h }}
{% for b in hostvars[h].backupservers %}
{% 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 }}
/usr/local/bin/borg prune -v $REPOSITORY {{ b.options }} -H {{ hostvars[h].borgbackup_retention.hourly }} -d {{ hostvars[h].borgbackup_retention.daily }} -w {{ hostvars[h].borgbackup_retention.weekly }} -m {{ hostvars[h].borgbackup_retention.monthly }} -y {{ hostvars[h].borgbackup_retention.yearly }}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}