@ -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' | |||
... |