From 090ea867ed6558f5c579e3e7619a15de482c60a5 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Sat, 11 Jan 2025 12:59:11 +0100 Subject: [PATCH 1/7] Install backup dependencies --- roles/packages/tasks/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roles/packages/tasks/main.yml b/roles/packages/tasks/main.yml index 5b58c6a..53e1bab 100644 --- a/roles/packages/tasks/main.yml +++ b/roles/packages/tasks/main.yml @@ -8,6 +8,8 @@ - dnsutils - rsyslog - snapd + - yq + - borgbackup state: present - name: Install Snap Core become: true From 8a14457aef5dc203e14d7bae86c3270585f877a7 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 13:10:52 +0100 Subject: [PATCH 2/7] Add first step of postgresql dump procedure --- roles/backups/files/backup_script.sh | 69 +++++++++++++++++++ roles/backups/tasks/main.yml | 25 +++++++ .../templates/backup_configuration.yaml | 6 ++ roles/backups/vars/main/defaults.yml | 3 + roles/backups/vars/main/vault.yml | 9 +++ roles/packages/tasks/main.yml | 1 + 6 files changed, 113 insertions(+) create mode 100644 roles/backups/files/backup_script.sh create mode 100644 roles/backups/tasks/main.yml create mode 100644 roles/backups/templates/backup_configuration.yaml create mode 100644 roles/backups/vars/main/defaults.yml create mode 100644 roles/backups/vars/main/vault.yml diff --git a/roles/backups/files/backup_script.sh b/roles/backups/files/backup_script.sh new file mode 100644 index 0000000..fbb3ed5 --- /dev/null +++ b/roles/backups/files/backup_script.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +# Inspiration of script from: https://borgbackup.readthedocs.io/en/stable/quickstart.html#automating-backups + +logInfo() { printf '%(%Y-%m-%d %H:%m:%S)T [INFO]: %s\n' -1 "$*" >&2; } + +configurationFileLocation=$1 + +workDirPath=/root/backup_work_dir +logInfo "Creating working directory at: $workDirPath..." +mkdir -p "$workDirPath" + +cleanup() { + logInfo "Backup interrupted" + # rm -f "$workDirPath" # TODO: Enable + exit 2 +} +trap 'cleanup' INT TERM + +# region: ---------------------------------- DBBACKUPS ---------------------------------- +createDatabaseBackup() { + host=$1 + dbname=$2 + username=$3 + password=$4 + targetFolderPath=$5 + + logInfo "Dumping database: $dbname to $targetFolderPath..." + + # Getting the correct version tools installed on the host proofed to be a very frustrating experience. + # So instead we'll do the dumping on the container. + postgresContainerName='postgres-postgres-1' + containerDumpPath=/dump.sql + + logInfo "Dumping database $dbname on container: $postgresContainerName..." + docker exec "$postgresContainerName" bash -c "(export PGPASSWORD='$password'; pg_dump $dbname \ + --file $containerDumpPath \ + --host $host \ + --username $username)" + + logInfo "Extracting the archive from the container..." + docker cp "$postgresContainerName:$containerDumpPath" "$targetFolderPath/$dbname.sql" 2>/dev/null + + logInfo "Removing the file from the docker container..." + docker exec "$postgresContainerName" rm "$containerDumpPath" +} + +createAllDatabaseBackups() { + nrOfConfigurations="$(yq '.database_backups | length' <"$configurationFileLocation")" + logInfo "Backing up from $nrOfConfigurations database configurations..." + + postgresBackupDirectory="$workDirPath/postgres" + mkdir -p "$postgresBackupDirectory" + + for ((i = 0 ; i < "$nrOfConfigurations" ; i++)); do + dbConfiguration="$(yq ".database_backups[$i]" <"$configurationFileLocation")" + host="$(echo "$dbConfiguration" | jq -r '.host')" + dbname="$(echo "$dbConfiguration" | jq -r '.dbname')" + username="$(echo "$dbConfiguration" | jq -r '.username')" + password="$(echo "$dbConfiguration" | jq -r '.password')" + targetFolderPath="$postgresBackupDirectory" + + createDatabaseBackup "$host" "$dbname" "$username" "$password" "$targetFolderPath" + done +} +# endregion: ------------------------------- DBBACKUPS ---------------------------------- + +createAllDatabaseBackups diff --git a/roles/backups/tasks/main.yml b/roles/backups/tasks/main.yml new file mode 100644 index 0000000..e7106e9 --- /dev/null +++ b/roles/backups/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: Copy over script + become: true + ansible.builtin.copy: + src: backup_script.sh + dest: "{{ backups_script_path }}" + owner: root + group: root + mode: '0700' +- name: Ensure directory for configuration file exists + become: true + ansible.builtin.file: + path: "{{ backups_configuration_path | dirname }}" + state: directory + owner: root + group: root + mode: '0755' +- name: Copy over configuration + become: true + ansible.builtin.template: + src: backup_configuration.yaml + dest: "{{ backups_configuration_path }}" + owner: root + group: root + mode: '0400' diff --git a/roles/backups/templates/backup_configuration.yaml b/roles/backups/templates/backup_configuration.yaml new file mode 100644 index 0000000..9aa367c --- /dev/null +++ b/roles/backups/templates/backup_configuration.yaml @@ -0,0 +1,6 @@ +--- +database_backups: + - host: postgres.kleinendorst.info + dbname: wedding + username: wedding + password: "{{ wedding_postgres_pass }}" diff --git a/roles/backups/vars/main/defaults.yml b/roles/backups/vars/main/defaults.yml new file mode 100644 index 0000000..e032d70 --- /dev/null +++ b/roles/backups/vars/main/defaults.yml @@ -0,0 +1,3 @@ +--- +backups_script_path: /usr/local/bin/backup_script.sh +backups_configuration_path: /etc/borg_backup_script/backup_configuration.yaml diff --git a/roles/backups/vars/main/vault.yml b/roles/backups/vars/main/vault.yml new file mode 100644 index 0000000..68b8b5f --- /dev/null +++ b/roles/backups/vars/main/vault.yml @@ -0,0 +1,9 @@ +$ANSIBLE_VAULT;1.1;AES256 +34646535396461343238663938663633376230346637306632616463383661613861343831303338 +6530366639356331656239303662316131373434333365360a303064623064613461366263613639 +30393537343934613038303263373566333861663061366334313331653934393530333630376338 +6236653034303738340a323835383034343132336462363461303463663565326235633461386536 +33303139393736346364636636376632663732313334353132613239383632613761373536643438 +36343262343436663866346463393138386437666566353038396432383730366536303763313461 +38653735633137303231343864643432666637333065663465363239376333646534333034383535 +64336434373339373532 diff --git a/roles/packages/tasks/main.yml b/roles/packages/tasks/main.yml index 53e1bab..72cd669 100644 --- a/roles/packages/tasks/main.yml +++ b/roles/packages/tasks/main.yml @@ -3,6 +3,7 @@ become: true ansible.builtin.apt: pkg: + - tldr - git - vim - dnsutils From 51915829abc8614ff5cbee3a6517d09afb5cafa5 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 13:44:49 +0100 Subject: [PATCH 3/7] Add docker volume backups --- roles/backups/files/backup_script.sh | 50 ++++++++++++++++++- .../templates/backup_configuration.yaml | 13 +++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/roles/backups/files/backup_script.sh b/roles/backups/files/backup_script.sh index fbb3ed5..c67a382 100644 --- a/roles/backups/files/backup_script.sh +++ b/roles/backups/files/backup_script.sh @@ -18,7 +18,7 @@ cleanup() { } trap 'cleanup' INT TERM -# region: ---------------------------------- DBBACKUPS ---------------------------------- +# region: ------ DB_BACKUPS ----------------------------------------------------------------------- createDatabaseBackup() { host=$1 dbname=$2 @@ -64,6 +64,52 @@ createAllDatabaseBackups() { createDatabaseBackup "$host" "$dbname" "$username" "$password" "$targetFolderPath" done } -# endregion: ------------------------------- DBBACKUPS ---------------------------------- +# endregion: --- DB_BACKUPS ----------------------------------------------------------------------- +# region: ------ DOCKER_VOLUME_BACKUPS ------------------------------------------------------------ +createDockerVolumeBackup() { + containerName=$1 + volumeName=$2 + specificVolumeBackupPath=$3 + + logInfo "Backup up Docker volume: $volumeName from running container: $containerName..." + + logInfo "Stopping container: $containerName..." + docker stop "$containerName" + + logInfo "Starting new container which copies over files..." + start=$SECONDS + docker run --rm -v "$volumeName:/volume" -v "$specificVolumeBackupPath:/target" --entrypoint "ash"\ + alpine -c "cp -rf /volume/* /target/" + + elapsedSeconds=$(( SECONDS - start )) + logInfo "Copying succeeded (in $elapsedSeconds seconds), restarting container..." + docker start "$containerName" +} + +createAllDockerVolumeBackups() { + nrOfConfigurations="$(yq '.docker_volume_backups | length' <"$configurationFileLocation")" + logInfo "Backing up from $nrOfConfigurations docker configurations..." + + dockerVolumeBackupPath="$workDirPath/docker_volumes" + mkdir -p "$dockerVolumeBackupPath" + + for ((i = 0 ; i < "$nrOfConfigurations" ; i++)); do + dockerConfiguration="$(yq ".docker_volume_backups[$i]" <"$configurationFileLocation")" + containerName="$(echo "$dockerConfiguration" | jq -r '.container_name')" + volumeName="$(echo "$dockerConfiguration" | jq -r '.volume_name')" + + specificVolumeBackupPath="$dockerVolumeBackupPath/$volumeName" + mkdir -p "$specificVolumeBackupPath" + + createDockerVolumeBackup "$containerName" "$volumeName" "$specificVolumeBackupPath" + done +} +# endregion: --- DOCKER_VOLUME_BACKUPS ------------------------------------------------------------ + + +# region: ------ PREPARE_BACKUP_FILES ------------------------------------------------------------- createAllDatabaseBackups +echo +createAllDockerVolumeBackups +# endregion: --- PREPARE_BACKUP_FILES ------------------------------------------------------------- diff --git a/roles/backups/templates/backup_configuration.yaml b/roles/backups/templates/backup_configuration.yaml index 9aa367c..2a5f4a6 100644 --- a/roles/backups/templates/backup_configuration.yaml +++ b/roles/backups/templates/backup_configuration.yaml @@ -4,3 +4,16 @@ database_backups: dbname: wedding username: wedding password: "{{ wedding_postgres_pass }}" +docker_volume_backups: + - volume_name: actual_data + container_name: actual-server + - volume_name: grafana_data + container_name: grafana-server + - volume_name: changedetection_changedetection_data + container_name: changedetection-changedetection-server-1 + - volume_name: hoarder_hoarder_data + container_name: hoarder-web-1 + - volume_name: hoarder_meilisearch + container_name: hoarder-meilisearch-1 + - volume_name: portainer_data + container_name: portainer From b6532afc9d459189b781eb8bdb3c6298fa5c57b9 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 14:37:48 +0100 Subject: [PATCH 4/7] Create backups in backup script --- roles/backups/files/backup_script.sh | 33 +++++++++++++++++++++++++++- roles/backups/vars/main/vault.yml | 18 ++++++++------- roles/packages/tasks/main.yml | 1 + 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/roles/backups/files/backup_script.sh b/roles/backups/files/backup_script.sh index c67a382..349bc00 100644 --- a/roles/backups/files/backup_script.sh +++ b/roles/backups/files/backup_script.sh @@ -7,7 +7,11 @@ logInfo() { printf '%(%Y-%m-%d %H:%m:%S)T [INFO]: %s\n' -1 "$*" >&2; } configurationFileLocation=$1 -workDirPath=/root/backup_work_dir +# Working on the bulk directory which is mounted on a very big SSD, this way we don't have to wory about +# running out of disk space. Note however that borg specifically might make use of cache directories +# in the home directory which aren't on this disk, let's tackle this problem when it actually starts failing... +workDirPath=/bulk/backup_work_dir +borgRepoDir="$workDirPath/borg_backups" # Used throughout the script logInfo "Creating working directory at: $workDirPath..." mkdir -p "$workDirPath" @@ -107,9 +111,36 @@ createAllDockerVolumeBackups() { } # endregion: --- DOCKER_VOLUME_BACKUPS ------------------------------------------------------------ +# region: ------ BORG_BACKUPS --------------------------------------------------------------------- +createArchiveInRepository() { + logInfo "Creating new archive in Borg repository (at $borgRepoDir)..." + + ( + cd "$workDirPath" + + # Note that BORG_PASSPHRASE is supposed to be set, otherwise a passowrd prompt will be present... + borg create --stats --verbose --show-rc --compression zstd,11 \ + "$borgRepoDir::{fqdn}-{now:%Y-%m-%d}" \ + ./docker_volumes ./postgres + + logInfo "Pruning old backups..." + # Copied from: https://borgbackup.readthedocs.io/en/stable/quickstart.html as it seems + # like good defaults. + borg prune --verbose --glob-archives '{fqdn}-*' --show-rc \ + --keep-daily 7 --keep-weekly 4 --keep-monthly 6 \ + "$borgRepoDir" + + logInfo "Compacting repository..." + borg compact --verbose --show-rc "$borgRepoDir" + ) +} +# endregion: --- BORG_BACKUPS --------------------------------------------------------------------- # region: ------ PREPARE_BACKUP_FILES ------------------------------------------------------------- createAllDatabaseBackups echo createAllDockerVolumeBackups +echo +# TODO: fetchOldBackupRepositoryFromCloud +createArchiveInRepository # endregion: --- PREPARE_BACKUP_FILES ------------------------------------------------------------- diff --git a/roles/backups/vars/main/vault.yml b/roles/backups/vars/main/vault.yml index 68b8b5f..16b7cc2 100644 --- a/roles/backups/vars/main/vault.yml +++ b/roles/backups/vars/main/vault.yml @@ -1,9 +1,11 @@ $ANSIBLE_VAULT;1.1;AES256 -34646535396461343238663938663633376230346637306632616463383661613861343831303338 -6530366639356331656239303662316131373434333365360a303064623064613461366263613639 -30393537343934613038303263373566333861663061366334313331653934393530333630376338 -6236653034303738340a323835383034343132336462363461303463663565326235633461386536 -33303139393736346364636636376632663732313334353132613239383632613761373536643438 -36343262343436663866346463393138386437666566353038396432383730366536303763313461 -38653735633137303231343864643432666637333065663465363239376333646534333034383535 -64336434373339373532 +37316361316463376662353834626533623465383237343034393765616538313262303031383832 +3833623665663331383131373264366564376539386631320a363861643632663233326564616665 +39393161363661373764353534393865663264653861303033373034323836656137303162653631 +3764393530646366330a306338346531663932343531326361613238366434396433623838366334 +33636530656466623735346661373130613461616532626430346132303261366133343034336535 +64386365303937343637643366356133646434366566373532393431383864663635623164656262 +34613562396136616531383461656331383436363461626136396139303263653431626233633438 +36623332376436316236373737613632323630306331316264633432303265343931303034363333 +65353631316264356530383938636662366637616430336566363063653866333366666131313036 +3935303838363737303862613161656664666463643137336135 diff --git a/roles/packages/tasks/main.yml b/roles/packages/tasks/main.yml index 72cd669..fcecb77 100644 --- a/roles/packages/tasks/main.yml +++ b/roles/packages/tasks/main.yml @@ -4,6 +4,7 @@ ansible.builtin.apt: pkg: - tldr + - tree - git - vim - dnsutils From 3c0ea05f5cbdad89a42e0cf49a8a420849fdc1bc Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 17:03:11 +0100 Subject: [PATCH 5/7] Finish backup script with remote repo --- roles/backups/files/backup_script.sh | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/roles/backups/files/backup_script.sh b/roles/backups/files/backup_script.sh index 349bc00..ad22196 100644 --- a/roles/backups/files/backup_script.sh +++ b/roles/backups/files/backup_script.sh @@ -11,16 +11,15 @@ configurationFileLocation=$1 # running out of disk space. Note however that borg specifically might make use of cache directories # in the home directory which aren't on this disk, let's tackle this problem when it actually starts failing... workDirPath=/bulk/backup_work_dir -borgRepoDir="$workDirPath/borg_backups" # Used throughout the script logInfo "Creating working directory at: $workDirPath..." mkdir -p "$workDirPath" cleanup() { - logInfo "Backup interrupted" - # rm -f "$workDirPath" # TODO: Enable - exit 2 + logInfo "Removing working directory at: $workDirPath..." + rm -rf "$workDirPath" } -trap 'cleanup' INT TERM +trap 'logInfo "Backup interrupted"; cleanup; exit 2' INT TERM +trap 'logInfo "Backup completed, cleaning up..."; cleanup' EXIT # region: ------ DB_BACKUPS ----------------------------------------------------------------------- createDatabaseBackup() { @@ -113,25 +112,24 @@ createAllDockerVolumeBackups() { # region: ------ BORG_BACKUPS --------------------------------------------------------------------- createArchiveInRepository() { - logInfo "Creating new archive in Borg repository (at $borgRepoDir)..." + logInfo "Creating new archive in Borg repository (at $BORG_REPO)..." ( cd "$workDirPath" - # Note that BORG_PASSPHRASE is supposed to be set, otherwise a passowrd prompt will be present... + # Note that both BORG_PASSPHRASE and BORG_REPO should be set, otherwise a password prompt will be present... borg create --stats --verbose --show-rc --compression zstd,11 \ - "$borgRepoDir::{fqdn}-{now:%Y-%m-%d}" \ + "::{fqdn}-{now:%Y-%m-%d}" \ ./docker_volumes ./postgres logInfo "Pruning old backups..." # Copied from: https://borgbackup.readthedocs.io/en/stable/quickstart.html as it seems # like good defaults. borg prune --verbose --glob-archives '{fqdn}-*' --show-rc \ - --keep-daily 7 --keep-weekly 4 --keep-monthly 6 \ - "$borgRepoDir" + --keep-daily 7 --keep-weekly 4 --keep-monthly 6 logInfo "Compacting repository..." - borg compact --verbose --show-rc "$borgRepoDir" + borg compact --verbose --show-rc ) } # endregion: --- BORG_BACKUPS --------------------------------------------------------------------- @@ -141,6 +139,5 @@ createAllDatabaseBackups echo createAllDockerVolumeBackups echo -# TODO: fetchOldBackupRepositoryFromCloud createArchiveInRepository # endregion: --- PREPARE_BACKUP_FILES ------------------------------------------------------------- From cf23a37aa02dc49b8339b10ffd39ce09bbfa39d0 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 17:03:28 +0100 Subject: [PATCH 6/7] Add dependencies of backup script --- roles/backups/tasks/main.yml | 24 ++++++++++++++++++++---- roles/backups/templates/ssh_config | 5 +++++ roles/backups/vars/main/defaults.yml | 1 + roles/backups/vars/main/vault.yml | 27 +++++++++++++++++---------- 4 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 roles/backups/templates/ssh_config diff --git a/roles/backups/tasks/main.yml b/roles/backups/tasks/main.yml index e7106e9..94084bc 100644 --- a/roles/backups/tasks/main.yml +++ b/roles/backups/tasks/main.yml @@ -1,12 +1,28 @@ --- -- name: Copy over script +# From within the script we're pushing backups to a specialised service (BorgBackup), This step ensure that an SSH key is present to use +# for verification on that service. Currently it has to be manually read out and entered in the service. This step has to be repeated +# when freshly applying this setup. +- name: Generate an OpenSSH keypair with the default values (4096 bits, rsa) become: true - ansible.builtin.copy: - src: backup_script.sh - dest: "{{ backups_script_path }}" + community.crypto.openssh_keypair: + path: "{{ backup_script_ssh_key_location }}" +# Needed for the task after this apparently... +- name: Install SSH config file + become: true + ansible.builtin.template: + src: ssh_config + dest: /root/.ssh/config owner: root group: root mode: '0700' +# - name: Copy over script +# become: true +# ansible.builtin.copy: +# src: backup_script.sh +# dest: "{{ backups_script_path }}" +# owner: root +# group: root +# mode: '0700' - name: Ensure directory for configuration file exists become: true ansible.builtin.file: diff --git a/roles/backups/templates/ssh_config b/roles/backups/templates/ssh_config new file mode 100644 index 0000000..8a8252e --- /dev/null +++ b/roles/backups/templates/ssh_config @@ -0,0 +1,5 @@ +Host {{ borg_base.remote_host }} + HostName {{ borg_base.remote_host }} + User {{ borg_base.remote_user }} + IdentityFile {{ backup_script_ssh_key_location }} + StrictHostKeyChecking accept-new diff --git a/roles/backups/vars/main/defaults.yml b/roles/backups/vars/main/defaults.yml index e032d70..320628f 100644 --- a/roles/backups/vars/main/defaults.yml +++ b/roles/backups/vars/main/defaults.yml @@ -1,3 +1,4 @@ --- +backup_script_ssh_key_location: /root/.ssh/id_ssh_rsa backups_script_path: /usr/local/bin/backup_script.sh backups_configuration_path: /etc/borg_backup_script/backup_configuration.yaml diff --git a/roles/backups/vars/main/vault.yml b/roles/backups/vars/main/vault.yml index 16b7cc2..cffe045 100644 --- a/roles/backups/vars/main/vault.yml +++ b/roles/backups/vars/main/vault.yml @@ -1,11 +1,18 @@ $ANSIBLE_VAULT;1.1;AES256 -37316361316463376662353834626533623465383237343034393765616538313262303031383832 -3833623665663331383131373264366564376539386631320a363861643632663233326564616665 -39393161363661373764353534393865663264653861303033373034323836656137303162653631 -3764393530646366330a306338346531663932343531326361613238366434396433623838366334 -33636530656466623735346661373130613461616532626430346132303261366133343034336535 -64386365303937343637643366356133646434366566373532393431383864663635623164656262 -34613562396136616531383461656331383436363461626136396139303263653431626233633438 -36623332376436316236373737613632323630306331316264633432303265343931303034363333 -65353631316264356530383938636662366637616430336566363063653866333366666131313036 -3935303838363737303862613161656664666463643137336135 +36663737323462306164663362663633363838633165303464666233333364323330613933326237 +3565663233613037336633313537346534333432633036360a353064366464333164393161653038 +30633966613031363932633736333337653464373866333836353032356431393866303836343166 +6464333031323639660a306631363234383366643435366536323861356434393566643633643839 +35313064653536393366366536386331663062663132313331353238653933356234333338343436 +32616565323636633239346366323934303766353936653336353063373663623932353532386532 +32633736323866313133363438373639396663333737363536353731353236303333626364386632 +64363336356566653130303765396232646231333436366434353634316631313365373561383636 +38386636623265643762613065376362653964653935306338653763306137323165346332623264 +33636164613562636164363065623564363965626235643238363630666639363866663631643530 +65613938663131396630303565646335623764353830356536376465346339363034316666306134 +31353731316430663136613061386566613832626234656337343065363331636239326365343762 +33663965626538643937323832663638613766323331623133376632666131353936346238386437 +61306135386131653466633331313165626162306639323633383133643761633466373234353134 +39323237666334323232623230643734363765376163333762643962356365343364383939333132 +63363961383934643935323264326133313135336638323833336539393136306435663134333930 +32343762623636323637383530366434326537313431636131343533613733613063 From b7183ceeae19cff03e1aefaf5d9e4e70d4ef937e Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 17:16:21 +0100 Subject: [PATCH 7/7] Wrap backup script in systemd service and timer --- roles/backups/files/borg_backup.timer | 10 ++++++ roles/backups/tasks/main.yml | 35 ++++++++++++++----- .../backups/templates/borg_backup.service.j2 | 15 ++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 roles/backups/files/borg_backup.timer create mode 100644 roles/backups/templates/borg_backup.service.j2 diff --git a/roles/backups/files/borg_backup.timer b/roles/backups/files/borg_backup.timer new file mode 100644 index 0000000..6ee4d8c --- /dev/null +++ b/roles/backups/files/borg_backup.timer @@ -0,0 +1,10 @@ +[Unit] +Description=BorgBase backup timer + +[Timer] +OnCalendar=daily +RandomizedDelaySec=900 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/roles/backups/tasks/main.yml b/roles/backups/tasks/main.yml index 94084bc..3a5a5d4 100644 --- a/roles/backups/tasks/main.yml +++ b/roles/backups/tasks/main.yml @@ -15,14 +15,14 @@ owner: root group: root mode: '0700' -# - name: Copy over script -# become: true -# ansible.builtin.copy: -# src: backup_script.sh -# dest: "{{ backups_script_path }}" -# owner: root -# group: root -# mode: '0700' +- name: Copy over script + become: true + ansible.builtin.copy: + src: backup_script.sh + dest: "{{ backups_script_path }}" + owner: root + group: root + mode: '0700' - name: Ensure directory for configuration file exists become: true ansible.builtin.file: @@ -39,3 +39,22 @@ owner: root group: root mode: '0400' +- name: Install BorgBase backup service file + become: true + ansible.builtin.template: + src: borg_backup.service.j2 + dest: "/lib/systemd/system/borg_backup.service" + mode: '0644' +- name: Install BorgBase backup timer file + become: true + ansible.builtin.copy: + src: borg_backup.timer + dest: "/lib/systemd/system/borg_backup.timer" + mode: '0644' +- name: Enable the newly added systemd timer + become: true + ansible.builtin.systemd_service: + daemon_reload: true + name: "borg_backup.timer" + state: started + enabled: true diff --git a/roles/backups/templates/borg_backup.service.j2 b/roles/backups/templates/borg_backup.service.j2 new file mode 100644 index 0000000..b8a6793 --- /dev/null +++ b/roles/backups/templates/borg_backup.service.j2 @@ -0,0 +1,15 @@ +[Unit] +Description=BorgBase backup service +Wants=network-online.target +After=network-online.target + +[Service] +Type=oneshot +User=root +Group=root +ExecStart={{ backups_script_path }} {{ backups_configuration_path }} +Environment="BORG_REPO={{ borg_base.repo_url }}" +Environment="BORG_PASSPHRASE={{ borg_backup_password }}" + +[Install] +WantedBy=default.target