From 8a14457aef5dc203e14d7bae86c3270585f877a7 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Tue, 14 Jan 2025 13:10:52 +0100 Subject: [PATCH] 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