@ -0,0 +1,10 @@ | |||||
--- | |||||
host_fqdn: '{{ ansible_hostname }}.dmz.{{ domain }}' | |||||
borgrepo_force_new_key: false | |||||
borgrepo_backup_host: 'backup' | |||||
borgrepo_repos: | |||||
picture: | |||||
folder: a | |||||
baobab: | |||||
pgsq: fff | |||||
... |
@ -0,0 +1,5 @@ | |||||
--- | |||||
- name: 'reload systemd' | |||||
debug: | |||||
msg: noop | |||||
... |
@ -0,0 +1,167 @@ | |||||
--- | |||||
- name: 'install borg' | |||||
apt: | |||||
pkg: 'borgbackup' | |||||
state: 'latest' | |||||
update_cache: true | |||||
cache_valid_time: 3600 | |||||
- name: 'create .ssh folder' | |||||
file: | |||||
path: '/root/.ssh' | |||||
mode: '0700' | |||||
state: 'directory' | |||||
- name: 'create backup keypair' | |||||
openssh_keypair: | |||||
path: '/root/.ssh/id_ed25519_BORG' | |||||
force: '{{ borgrepo_force_new_key }}' | |||||
type: 'ed25519' | |||||
comment: 'backup@{{ host_fqdn }}' | |||||
register: ssh_keypair | |||||
- name: 'create host repos namespace' | |||||
file: | |||||
path: '/home/backup/repos/{{ host_fqdn }}' | |||||
owner: 'backup' | |||||
group: 'backup' | |||||
mode: '0700' | |||||
state: 'directory' | |||||
delegate_to: '{{ borgrepo_backup_host }}' | |||||
- name: 'authorize host key' | |||||
lineinfile: | |||||
path: '/home/backup/.ssh/authorized_keys' | |||||
owner: 'backup' | |||||
group: 'backup' | |||||
mode: '0600' | |||||
create: yes | |||||
line: >- | |||||
command="cd {{ repodir }}; borg serve --append-only --restrict-to-path {{ repodir }}",restrict | |||||
{{ ssh_keypair.public_key }} | |||||
regexp: '{{ ssh_keypair.comment }}$' | |||||
state: 'present' | |||||
vars: | |||||
repodir: '/home/backup/repos/{{ host_fqdn }}' | |||||
delegate_to: '{{ borgrepo_backup_host }}' | |||||
- name: 'upload host ssh ca' | |||||
copy: | |||||
content: | | |||||
{% for ca in ssh_server_ca %} | |||||
@cert-authority *.dmz.{{ domain }} {{ ca }} | |||||
{% endfor %} | |||||
dest: '/root/.ssh/known_hosts' | |||||
mode: '0600' | |||||
##ToDo setup encryption | |||||
- name: 'initialize repo' | |||||
shell: | |||||
cmd: > | |||||
borg init -e none backup@{{ borgrepo_backup_host }}.dmz.{{ domain }}:{{ item.key }} | |||||
register: borgrepo_init_cmd | |||||
failed_when: | |||||
- borgrepo_init_cmd.rc != 0 | |||||
- borgrepo_init_cmd.stderr !='A repository already exists at backup@backup.dmz.lilik.it:'+item.key+'.' | |||||
changed_when: borgrepo_init_cmd.rc == 0 | |||||
environment: | |||||
BORG_RSH: 'ssh -i /root/.ssh/id_ed25519_BORG' | |||||
loop: '{{ borgrepo_repos|dict2items }}' | |||||
- name: 'create backup directory' | |||||
file: | |||||
path: '/etc/backup' | |||||
state: 'directory' | |||||
owner: 'root' | |||||
group: 'root' | |||||
mode: '0700' | |||||
- name: 'create log backup directory' | |||||
file: | |||||
path: '/var/log/backup-status' | |||||
state: 'directory' | |||||
owner: 'root' | |||||
group: 'root' | |||||
mode: '0755' | |||||
- name: 'create repo log directory' | |||||
file: | |||||
path: '/var/log/backup-status/{{ item.key }}' | |||||
state: 'directory' | |||||
owner: 'root' | |||||
group: 'root' | |||||
mode: '0755' | |||||
loop: '{{ borgrepo_repos|dict2items }}' | |||||
- name: 'create backup scripts' | |||||
template: | |||||
src: 'backupscript.sh.j2' | |||||
dest: '/etc/backup/{{ item.key }}.sh' | |||||
owner: 'root' | |||||
group: 'root' | |||||
mode: '0700' | |||||
loop: '{{ borgrepo_repos|dict2items }}' | |||||
- name: 'create systemd service' | |||||
template: | |||||
src: 'backupservice.service' | |||||
dest: '/etc/systemd/system/borg-backup@.service' | |||||
notify: reload systemd | |||||
- name: 'create systemd timers' | |||||
copy: | |||||
content: | | |||||
[Unit] | |||||
Description=BorgBackup %I repo timer. | |||||
[Timer] | |||||
WakeSystem=false | |||||
OnCalendar=*-*-* 02:00:00 | |||||
RandomizedDelaySec=20min | |||||
[Install] | |||||
WantedBy=timers.target | |||||
dest: '/etc/systemd/system/borg-backup@.timer' | |||||
notify: reload systemd | |||||
- name: 'enable systemd timers' | |||||
systemd: | |||||
name: 'borg-backup@{{ item.key }}.timer' | |||||
daemon_reload: true | |||||
enabled: true | |||||
state: 'restarted' | |||||
loop: '{{ borgrepo_repos|dict2items }}' | |||||
- name: 'MONITORING | create entry' | |||||
set_fact: | |||||
borg_monitoring_repos: > | |||||
{{ borg_monitoring_repos|d({})|combine({ | |||||
item.key: | |||||
{ | |||||
"backup_wage": item.value.interval|d(86400)|int, | |||||
"backup_cage": (item.value.interval|d(86400)|int+7200)*2 | |||||
} | |||||
}) }} | |||||
loop: '{{ borgrepo_repos|dict2items }}' | |||||
tags: | |||||
- 'monitoring' | |||||
- name: 'MONITORING | update facts' | |||||
set_fact: | |||||
monitoring_facts: > | |||||
{{ hostvars[monitoring_host]["monitoring_facts"] | |||||
| default({}) | |||||
| combine({ | |||||
host_fqdn: | |||||
{ | |||||
"address": ansible_host, | |||||
"borg_repos": borg_monitoring_repos | |||||
} | |||||
}, recursive=True) }} | |||||
delegate_to: '{{ monitoring_host }}' | |||||
delegate_facts: true | |||||
loop: '{{ borgrepo_repos|dict2items }}' | |||||
tags: | |||||
- 'monitoring' | |||||
... |
@ -0,0 +1,160 @@ | |||||
#!/bin/bash | |||||
REPO="backup@{{ borgrepo_backup_host }}.dmz.{{ domain }}:{{ item.key }}" | |||||
export BORG_RSH="ssh -i /root/.ssh/id_ed25519_BORG" | |||||
export BORG_PASSPHRASE="" | |||||
export BORG_RELOCATED_REPO_ACCESS_IS_OK="no" | |||||
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK="no" | |||||
borg --version | |||||
{% for folder in item.value.folders|d({})|dict2items %} | |||||
##### Folder {{ folder.key }} | |||||
BEGIN_EPOCH=$(date +%s) | |||||
DATE="folder-{{ folder.key }}-$(date --iso-8601)-$(hostname)" | |||||
echo "Starting backup for $DATE" | |||||
borg create \ | |||||
--verbose \ | |||||
--filter AME \ | |||||
--list \ | |||||
--stats \ | |||||
--show-rc \ | |||||
--compression lz4 \ | |||||
--exclude-caches \ | |||||
{% for exclude in folder.value.excludes|d([]) %} | |||||
--exclude '{{ exclude }}' \ | |||||
{% endfor %} | |||||
\ | |||||
${REPO}::'folder-{{ folder.key }}-{hostname}-{now:%Y-%m-%d@%H:%M}' \ | |||||
{{ folder.value.path }} | |||||
backup_rc=$? | |||||
prune_rc=99 | |||||
if [ "${backup_rc}" = "2" ]; then | |||||
echo "Failed backup for $DATE" | |||||
else | |||||
echo "Completed backup for $DATE" | |||||
echo "Pruning archives for $DATE" | |||||
borg prune \ | |||||
--list \ | |||||
--prefix 'folder-{{ folder.key }}-{hostname}-' \ | |||||
--show-rc \ | |||||
--keep-daily {{ folder.value.daily|d(7) }} \ | |||||
--keep-weekly {{ folder.value.weekly|d(4) }} \ | |||||
--keep-monthly {{ folder.value.monthly|d(6) }} \ | |||||
${REPO} | |||||
prune_rc=$? | |||||
if [ "${prune_rc}" = "2" ]; then | |||||
echo "Failed pruning for $DATE" | |||||
else | |||||
echo "Completed pruning for $DATE" | |||||
fi | |||||
fi | |||||
echo "$(date +%s)|${BEGIN_EPOCH}|${backup_rc}|${prune_rc}" > /var/log/backup-status/{{ item.key }}/folder-{{ folder.key }} | |||||
{% endfor %} | |||||
##### | |||||
{% for db in item.value.pgsql_dbs|d({})|dict2items %} | |||||
##### pgSQL DB {{ db.key }} | |||||
DATE="pgsqldb-{{ db.key }}-$(date --iso-8601)-$(hostname)" | |||||
echo "Starting backup for $DATE" | |||||
su postgres -c 'pg_dump -d {{ db.value.dbname }}' | borg create \ | |||||
--verbose \ | |||||
--filter AME \ | |||||
--list \ | |||||
--stats \ | |||||
--show-rc \ | |||||
--compression lz4 \ | |||||
--stdin-name "{{ db.value.dbname }}.sql" \ | |||||
\ | |||||
${REPO}::'pgsqldb-{{ db.key }}-{hostname}-{now:%Y-%m-%d@%H:%M}' \ | |||||
- | |||||
backup_rc=$? | |||||
prune_rc=99 | |||||
if [ "${backup_rc}" = "2" ]; then | |||||
echo "Failed backup for $DATE" | |||||
else | |||||
echo "Completed backup for $DATE" | |||||
echo "Pruning archives for $DATE" | |||||
borg prune \ | |||||
--list \ | |||||
--prefix 'pgsqldb-{{ db.key }}-{hostname}-' \ | |||||
--show-rc \ | |||||
--keep-daily {{ db.value.daily|d(7) }} \ | |||||
--keep-weekly {{ db.value.weekly|d(4) }} \ | |||||
--keep-monthly {{ db.value.monthly|d(6) }} \ | |||||
${REPO} | |||||
prune_rc=$? | |||||
if [ "${prune_rc}" = "2" ]; then | |||||
echo "Failed pruning for $DATE" | |||||
else | |||||
echo "Completed pruning for $DATE" | |||||
fi | |||||
fi | |||||
echo "$(date +%s)|${BEGIN_EPOCH}|${backup_rc}|${prune_rc}" > /var/log/backup-status/{{ item.key }}/pgsqldb-{{ db.key }} | |||||
{% endfor %} | |||||
{% for db in item.value.ldap_dbs|d({})|dict2items %} | |||||
##### LDAP DB {{ db.key }} | |||||
DATE="ldapdb-{{ db.key }}-$(date --iso-8601)-$(hostname)" | |||||
echo "Starting backup for $DATE" | |||||
slapcat -n {{ db.value.dbnum }} | borg create \ | |||||
--verbose \ | |||||
--filter AME \ | |||||
--list \ | |||||
--stats \ | |||||
--show-rc \ | |||||
--compression lz4 \ | |||||
--stdin-name "slapcat.db{{ db.value.dbnum }}.ldif" \ | |||||
\ | |||||
${REPO}::'ldapdb-{{ db.key }}-{hostname}-{now:%Y-%m-%d@%H:%M}' \ | |||||
- | |||||
backup_rc=$? | |||||
prune_rc=99 | |||||
if [ "${backup_rc}" = "2" ]; then | |||||
echo "Failed backup for $DATE" | |||||
else | |||||
echo "Completed backup for $DATE" | |||||
echo "Pruning archives for $DATE" | |||||
borg prune \ | |||||
--list \ | |||||
--prefix 'ldapdb-{{ db.key }}-{hostname}-' \ | |||||
--show-rc \ | |||||
--keep-daily {{ db.value.daily|d(7) }} \ | |||||
--keep-weekly {{ db.value.weekly|d(4) }} \ | |||||
--keep-monthly {{ db.value.monthly|d(6) }} \ | |||||
${REPO} | |||||
prune_rc=$? | |||||
if [ "${prune_rc}" = "2" ]; then | |||||
echo "Failed pruning for $DATE" | |||||
else | |||||
echo "Completed pruning for $DATE" | |||||
fi | |||||
fi | |||||
echo "$(date +%s)|${BEGIN_EPOCH}|${backup_rc}|${prune_rc}" > /var/log/backup-status/{{ item.key }}/ldapdb-{{ db.key }} | |||||
{% endfor %} |
@ -0,0 +1,15 @@ | |||||
[Unit] | |||||
Description=BorgBackup script for Repository %I | |||||
After=network.target | |||||
[Service] | |||||
Type=oneshot | |||||
Nice=19 | |||||
IOSchedulingClass=2 | |||||
IOSchedulingPriority=7 | |||||
Environment=BORG_RSH="ssh -i /root/.ssh/id_ed25519_BORG" | |||||
ExecStartPre=/usr/bin/borg break-lock backup@{{ borgrepo_backup_host }}.dmz.{{ domain }}:%i | |||||
ExecStart=/etc/backup/%i.sh | |||||
PIDFile=/tmp/borg_backup_%i.pid | |||||
User=root | |||||
Group=root |
@ -0,0 +1,46 @@ | |||||
--- | |||||
- name: 'install borgbackup' | |||||
apt: | |||||
pkg: 'borgbackup' | |||||
state: 'latest' | |||||
update_cache: true | |||||
cache_valid_time: 3600 | |||||
- name: 'create backup group' | |||||
group: | |||||
name: 'backup' | |||||
state: 'present' | |||||
- name: 'create backup user' | |||||
user: | |||||
name: 'backup' | |||||
shell: '/bin/bash' | |||||
home: '/home/backup' | |||||
createhome: true | |||||
group: 'backup' | |||||
state: 'present' | |||||
- name: 'create home folder' | |||||
file: | |||||
path: '/home/backup/repos' | |||||
owner: 'backup' | |||||
group: 'backup' | |||||
mode: '0700' | |||||
state: 'directory' | |||||
- name: 'create .ssh folder' | |||||
file: | |||||
path: '/home/backup/repos' | |||||
owner: 'backup' | |||||
group: 'backup' | |||||
mode: '0700' | |||||
state: 'directory' | |||||
- name: 'create repos folder' | |||||
file: | |||||
path: '/home/backup/repos' | |||||
owner: 'backup' | |||||
group: 'backup' | |||||
mode: '0700' | |||||
state: 'directory' | |||||
... |