Backup server: incremental mirror, client subset, configurable compression
- local_backup rsynced every repository into an empty folder each night (full transfer); keep a persistent mirror (backup_server_mirror) and rsync --delete into it - backup_server_clients: clients handled by the server (app names must be unique, e.g. two 'webserver' apps collided) - backup_server_local_skip: apps that are pruned remotely but not mirrored - backup_server_compression: borg repos are encrypted already, allow 'none' Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1d99257ead
commit
c0155e3396
3 files changed
+27
-18
No files matched your search
@@ -23,6 +23,12 @@ backup_cron_owner: "{{ backup_owner }}"
|
||||
backup_server_remote_prune_time: 6
|
||||
backup_server_remote_backup_time: 8
|
||||
backup_server_local_prune_time: 10
|
||||
#server: clients to prune/mirror (defaults to backup_clients), apps not mirrored locally, local compression
|
||||
backup_server_clients: "{{ backup_clients }}"
|
||||
backup_server_local_skip: []
|
||||
backup_server_compression: lzma
|
||||
#local mirror of the remote repositories (defaults to <backup_root>/storage/remote-backups)
|
||||
#backup_server_mirror: /mnt/nas/backup/mirror
|
||||
|
||||
|
||||
backup_script:
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@
|
||||
group: "{{ backup_group }}"
|
||||
mode: "0750"
|
||||
loop:
|
||||
- "{{ backup_remotes_folder }}"
|
||||
- "{{ backup_server_mirror | default(backup_remotes_folder) }}"
|
||||
- "{{ backup_location }}/{{ backup_app }}"
|
||||
|
||||
- name: setup borg local repository
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
{% set server_clients = backup_server_clients | default(backup_clients) %}
|
||||
#!/bin/bash
|
||||
|
||||
BORGUSER="{{ backup_owner }}";
|
||||
TARGETFOLDER="{{ backup_remotes_folder }}";
|
||||
LOCALREPOLOCATION="{{ backup_location }}/{{ backup_app }}";
|
||||
APPLIST="{{ backup_clients | json_query('*.app') | join(' ') }}";
|
||||
APPLIST="{{ server_clients | json_query('*.app') | join(' ') }}";
|
||||
# repos that are only pruned remotely, not mirrored locally
|
||||
LOCALAPPLIST="{{ server_clients | json_query('*.app') | difference(backup_server_local_skip) | join(' ') }}";
|
||||
MIRRORFOLDER="{{ backup_server_mirror | default(backup_remotes_folder) }}";
|
||||
|
||||
declare -A BORG_CLIENT_MAP
|
||||
{% for client in backup_clients %}
|
||||
BORG_CLIENT_MAP[{{ backup_clients[client].app }}]="{{ client }}";
|
||||
{% for client in server_clients %}
|
||||
BORG_CLIENT_MAP[{{ server_clients[client].app }}]="{{ client }}";
|
||||
{% endfor %}
|
||||
|
||||
declare -A BORG_USER_MAP
|
||||
{% for client in backup_clients %}
|
||||
BORG_USER_MAP[{{ backup_clients[client].app }}]="{{ backup_clients[client].owner }}";
|
||||
{% for client in server_clients %}
|
||||
BORG_USER_MAP[{{ server_clients[client].app }}]="{{ server_clients[client].owner }}";
|
||||
{% endfor %}
|
||||
|
||||
|
||||
@@ -36,8 +40,8 @@ COMMAND:
|
||||
|
||||
|
||||
APPS: A single app or comma-separated (sub-)set of below listed apps to be considered.
|
||||
{% for client in backup_clients %}
|
||||
- {{ backup_clients[client].app }}
|
||||
{% for client in server_clients %}
|
||||
- {{ server_clients[client].app }}
|
||||
{% endfor %}
|
||||
";
|
||||
}
|
||||
@@ -177,25 +181,24 @@ local_prune () {
|
||||
|
||||
local_backup () {
|
||||
ARCHIVENAME="{{ backup_app }}-$(date '+%s')";
|
||||
mkdir -p $TARGETFOLDER/$ARCHIVENAME;
|
||||
chown $BORGUSER: $TARGETFOLDER/$ARCHIVENAME;
|
||||
for APP in $APPLIST;
|
||||
mkdir -p $MIRRORFOLDER;
|
||||
chown $BORGUSER: $MIRRORFOLDER;
|
||||
# keep a persistent mirror so rsync only transfers what changed
|
||||
for APP in $LOCALAPPLIST;
|
||||
do
|
||||
sudo -H -u $BORGUSER bash -c '
|
||||
TARGETFOLDER='$TARGETFOLDER';
|
||||
ARCHIVENAME='$ARCHIVENAME';
|
||||
MIRRORFOLDER='$MIRRORFOLDER';
|
||||
REPOLOCATION='${BORG_CLIENT_MAP[$APP]}':'$APP';
|
||||
rsync -azr $REPOLOCATION $TARGETFOLDER/$ARCHIVENAME/;';
|
||||
rsync -ar --delete $REPOLOCATION $MIRRORFOLDER/;';
|
||||
done
|
||||
|
||||
# borg repositories are encrypted already, compression rarely helps
|
||||
sudo -H -u $BORGUSER bash -c '
|
||||
TARGETFOLDER='$TARGETFOLDER';
|
||||
MIRRORFOLDER='$MIRRORFOLDER';
|
||||
REPOLOCATION='$LOCALREPOLOCATION';
|
||||
ARCHIVENAME='$ARCHIVENAME';
|
||||
export BORG_PASSPHRASE=$(cat {{ backup_home }}/.borg.key);
|
||||
borg create -C lzma $REPOLOCATION::$ARCHIVENAME $TARGETFOLDER/$ARCHIVENAME;';
|
||||
|
||||
rm -rf $TARGETFOLDER/$ARCHIVENAME;
|
||||
borg create -C {{ backup_server_compression }} $REPOLOCATION::$ARCHIVENAME $MIRRORFOLDER;';
|
||||
}
|
||||
|
||||
local_delete () {
|
||||
|
||||
Reference in new issue
Block a user