From d5f4c17146dbe87d44770dc9dbf215b24eb2375b Mon Sep 17 00:00:00 2001 From: Aine Date: Thu, 14 Apr 2022 18:06:54 +0300 Subject: [PATCH 1/3] matrix-backup-borg: integrate postgres backups, add extended borgmatic configuration --- group_vars/matrix_servers | 26 ++++++++++-- roles/matrix-backup-borg/defaults/main.yml | 42 ++++++++++++++++--- .../tasks/setup_install.yml | 9 ++-- .../util/detect_existing_postgres_version.yml | 42 +++++++++++++++++++ .../templates/config.yaml.j2 | 10 +++++ setup.yml | 2 +- 6 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index 85b8a701..91324025 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -1081,13 +1081,33 @@ matrix_bot_mjolnir_systemd_required_services_list: | ###################################################################### matrix_backup_borg_enabled: false +matrix_backup_borg_container_image_self_build: "{{ matrix_architecture not in ['amd64', 'arm32', 'arm64'] }}" +matrix_backup_borg_postgresql_enabled: "{{ matrix_postgres_enabled }}" +matrix_backup_borg_postgresql_databases_hostname: "{{ matrix_postgres_connection_hostname }}" +matrix_backup_borg_postgresql_databases_username: "{{ matrix_postgres_connection_username }}" +matrix_backup_borg_postgresql_databases_password: "{{ matrix_postgres_connection_password }}" +matrix_backup_borg_postgresql_databases_port: "{{ matrix_postgres_connection_port }}" +matrix_backup_borg_postgresql_databases: | + {{ + (([{ + 'name': matrix_synapse_database_database + }] if (matrix_synapse_enabled and matrix_synapse_database_database == matrix_postgres_db_name and matrix_synapse_database_host == 'matrix-postgres') else []) + + + matrix_postgres_additional_databases)|map(attribute='name')|list + }} matrix_backup_borg_location_source_directories: - "{{ matrix_base_data_path }}" matrix_backup_borg_location_exclude_patterns: | {{ - { - 'synapse': ["{{ matrix_synapse_media_store_path }}/local_thumbnails", "{{ matrix_synapse_media_store_path }}/remote_thumbnail", "{{ matrix_synapse_media_store_path }}/url_cache", "{{ matrix_synapse_media_store_path }}/url_cache_thumbnails"], - }[matrix_homeserver_implementation] + ([matrix_synapse_media_store_path + '/local_thumbnails', matrix_synapse_media_store_path + '/remote_thumbnail', matrix_synapse_media_store_path + '/url_cache', matrix_synapse_media_store_path + '/url_cache_thumbnails'] if matrix_homeserver_implementation == 'synapse' else []) + + + ([matrix_postgres_data_path] if matrix_postgres_enabled else []) + }} +matrix_backup_borg_systemd_required_services_list: | + {{ + ['docker.service'] + + + (['matrix-postgres.service'] if matrix_postgres_enabled else []) }} ###################################################################### diff --git a/roles/matrix-backup-borg/defaults/main.yml b/roles/matrix-backup-borg/defaults/main.yml index c8a09f7f..374b5bef 100644 --- a/roles/matrix-backup-borg/defaults/main.yml +++ b/roles/matrix-backup-borg/defaults/main.yml @@ -1,17 +1,17 @@ --- matrix_backup_borg_enabled: true +matrix_backup_borg_base_path: "{{ matrix_base_data_path }}/backup-borg" +matrix_backup_borg_config_path: "{{ matrix_backup_borg_base_path }}/config" + matrix_backup_borg_container_image_self_build: false matrix_backup_borg_docker_repo: "https://github.com/borgmatic-collective/docker-borgmatic" -matrix_backup_borg_docker_src_files_path: "{{ matrix_base_data_path }}/borg/docker-src" +matrix_backup_borg_docker_src_files_path: "{{ matrix_backup_borg_base_path }}/docker-src" -matrix_backup_borg_version: latest +matrix_backup_borg_version: "" matrix_backup_borg_docker_image: "{{ matrix_backup_borg_docker_image_name_prefix }}etke.cc/borgmatic:{{ matrix_backup_borg_version }}" matrix_backup_borg_docker_image_name_prefix: "{{ 'localhost/' if matrix_backup_borg_container_image_self_build else 'registry.gitlab.com/' }}" -matrix_backup_borg_docker_image_force_pull: "{{ matrix_backup_borg_docker_image.endswith(':latest') }}" - -matrix_backup_borg_base_path: "{{ matrix_base_data_path }}/backup-borg" -matrix_backup_borg_config_path: "{{ matrix_backup_borg_base_path }}/config" +matrix_backup_borg_docker_image_force_pull: "{{ matrix_backup_borg_docker_image.endswith(':latest') or matrix_backup_borg_version|default('') == '' }}" # A list of extra arguments to pass to the container matrix_backup_borg_container_extra_arguments: [] @@ -28,6 +28,14 @@ matrix_backup_borg_schedule: "*-*-* 04:00:00" # what directories should be added to backup matrix_backup_borg_location_source_directories: [] +# postgres db backup +matrix_backup_borg_postgresql_enabled: true +matrix_backup_borg_postgresql_databases: [] +matrix_backup_borg_postgresql_databases_hostname: "matrix-postgres" +matrix_backup_borg_postgresql_databases_username: "matrix" +matrix_backup_borg_postgresql_databases_password: "" +matrix_backup_borg_postgresql_databases_port: 5432 + # target repositories matrix_backup_borg_location_repositories: [] @@ -61,3 +69,25 @@ matrix_backup_borg_retention_keep_yearly: 2 # retention prefix matrix_backup_borg_retention_prefix: "matrix-" + +# Default borgmatic configuration template which covers the generic use case. +# You can customize it by controlling the various variables inside it. +# +# For a more advanced customization, you can extend the default (see `matrix_backup_borg_configuration_extension_yaml`) +# or completely replace this variable with your own template. +matrix_backup_borg_configuration_yaml: "{{ lookup('template', 'templates/config.yaml.j2') }}" + +matrix_backup_borg_configuration_extension_yaml: | + # Your custom YAML configuration for borgmatic goes here. + # This configuration extends the default starting configuration (`matrix_borg_configuration_yaml`). + # + # You can override individual variables from the default configuration, or introduce new ones. + # + # If you need something more special, you can take full control by + # completely redefining `matrix_backup_borg_configuration_yaml`. + +matrix_backup_borg_configuration_extension: "{{ matrix_backup_borg_configuration_extension_yaml|from_yaml if matrix_backup_borg_configuration_extension_yaml|from_yaml is mapping else {} }}" + +# Holds the final borgmatic configuration (a combination of the default and its extension). +# You most likely don't need to touch this variable. Instead, see `matrix_backup_borg_configuration_yaml`. +matrix_backup_borg_configuration: "{{ matrix_backup_borg_configuration_yaml|from_yaml|combine(matrix_backup_borg_configuration_extension, recursive=True) }}" diff --git a/roles/matrix-backup-borg/tasks/setup_install.yml b/roles/matrix-backup-borg/tasks/setup_install.yml index 90757a80..9c34c53f 100644 --- a/roles/matrix-backup-borg/tasks/setup_install.yml +++ b/roles/matrix-backup-borg/tasks/setup_install.yml @@ -1,4 +1,7 @@ --- +- import_tasks: "{{ role_path }}/tasks/util/detect_existing_postgres_version.yml" + when: 'matrix_backup_borg_enabled|bool and matrix_backup_borg_postgresql_enabled|bool and matrix_postgres_backup_postgres_data_path != ""' + - name: Ensure borg paths exist file: path: "{{ item.path }}" @@ -11,9 +14,9 @@ - {path: "{{ matrix_backup_borg_docker_src_files_path }}", when: true} when: "item.when|bool" -- name: Ensure borg config is created - template: - src: "{{ role_path }}/templates/config.yaml.j2" +- name: Ensure borgmatic config is created + copy: + content: "{{ matrix_backup_borg_configuration|to_nice_yaml(indent=2, width=999999) }}" dest: "{{ matrix_backup_borg_config_path }}/config.yaml" owner: "{{ matrix_user_username }}" group: "{{ matrix_user_groupname }}" diff --git a/roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml b/roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml new file mode 100644 index 00000000..0d50d93f --- /dev/null +++ b/roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml @@ -0,0 +1,42 @@ +--- + +# This utility aims to determine if there is some existing Postgres version in use or not. +# If there is, it also tries to detect the Docker image that corresponds to that version. + +- name: Initialize Postgres version determination variables (default to empty) + set_fact: + matrix_backup_borg_postgresql_detection_pg_version_path: "{{ matrix_postgres_data_path }}/PG_VERSION" + matrix_backup_borg_postgresql_detected_existing: false + matrix_backup_borg_postgresql_detected_version: "" + matrix_backup_borg_version: "" + +- name: Determine existing Postgres version (check PG_VERSION file) + stat: + path: "{{ matrix_backup_borg_postgresql_detection_pg_version_path }}" + register: result_pg_version_stat + +- set_fact: + matrix_backup_borg_postgresql_detected_existing: true + when: "result_pg_version_stat.stat.exists" + +- name: Determine existing Postgres version (read PG_VERSION file) + slurp: + src: "{{ matrix_backup_borg_postgresql_detection_pg_version_path }}" + register: result_pg_version + when: matrix_backup_borg_postgresql_detected_existing|bool + +- name: Determine existing Postgres version (make sense of PG_VERSION file) + set_fact: + matrix_backup_borg_postgresql_detected_version: "{{ result_pg_version['content']|b64decode|replace('\n', '') }}" + when: matrix_backup_borg_postgresql_detected_existing|bool + +- name: Determine corresponding Docker image version to detected version + set_fact: + matrix_backup_borg_version: "{{ matrix_backup_borg_postgresql_detected_version }}" + when: "matrix_backup_borg_postgresql_detected_version == '12' or matrix_backup_borg_postgresql_detected_version.startswith('12.') or matrix_backup_borg_postgresql_detected_version == '13' or matrix_backup_borg_postgresql_detected_version.startswith('13.') or matrix_backup_borg_postgresql_detected_version == '14' or matrix_backup_borg_postgresql_detected_version.startswith('14.')" + +- name: Fail if existing Postgres version is not supported by borgmatic docker image + fail: + msg: >- + Your Postgres v{{ matrix_backup_borg_postgresql_detected_version }} is not supported. + when: "matrix_backup_borg_version == ''" diff --git a/roles/matrix-backup-borg/templates/config.yaml.j2 b/roles/matrix-backup-borg/templates/config.yaml.j2 index 89b6ab7d..8ac2a8b2 100644 --- a/roles/matrix-backup-borg/templates/config.yaml.j2 +++ b/roles/matrix-backup-borg/templates/config.yaml.j2 @@ -26,6 +26,16 @@ consistency: - archives hooks: +{% if matrix_backup_borg_postgresql_enabled %} + postgresql_databases: + {% for database in matrix_backup_borg_postgresql_databases %} + - name: {{ database }} + hostname: {{ matrix_backup_borg_postgresql_databases_hostname }} + username: {{ matrix_backup_borg_postgresql_databases_username }} + password: {{ matrix_backup_borg_postgresql_databases_password }} + port: {{ matrix_backup_borg_postgresql_databases_port }} + {% endfor %} +{% endif %} after_backup: - echo "Backup created." on_error: diff --git a/setup.yml b/setup.yml index 52079e32..de86665b 100755 --- a/setup.yml +++ b/setup.yml @@ -13,7 +13,6 @@ - matrix-postgres - matrix-redis - matrix-corporal - - matrix-backup-borg - matrix-bridge-appservice-discord - matrix-bridge-appservice-slack - matrix-bridge-appservice-webhooks @@ -62,4 +61,5 @@ - matrix-aux - matrix-postgres-backup - matrix-prometheus-postgres-exporter + - matrix-backup-borg - matrix-common-after From a9d0cbc560a380fb9a5147101c817574d9d134ab Mon Sep 17 00:00:00 2001 From: Aine Date: Fri, 15 Apr 2022 19:38:10 +0300 Subject: [PATCH 2/3] feedback --- roles/matrix-backup-borg/defaults/main.yml | 8 ++-- .../tasks/setup_install.yml | 14 ++++++- .../util/detect_existing_postgres_version.yml | 42 ------------------- .../templates/config.yaml.j2 | 32 +++++++------- 4 files changed, 33 insertions(+), 63 deletions(-) delete mode 100644 roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml diff --git a/roles/matrix-backup-borg/defaults/main.yml b/roles/matrix-backup-borg/defaults/main.yml index 374b5bef..189b6042 100644 --- a/roles/matrix-backup-borg/defaults/main.yml +++ b/roles/matrix-backup-borg/defaults/main.yml @@ -5,9 +5,10 @@ matrix_backup_borg_base_path: "{{ matrix_base_data_path }}/backup-borg" matrix_backup_borg_config_path: "{{ matrix_backup_borg_base_path }}/config" matrix_backup_borg_container_image_self_build: false -matrix_backup_borg_docker_repo: "https://github.com/borgmatic-collective/docker-borgmatic" +matrix_backup_borg_docker_repo: "https://gitlab.com/etke.cc/borgmatic" matrix_backup_borg_docker_src_files_path: "{{ matrix_backup_borg_base_path }}/docker-src" +# version determined automatically, based on postgres server version (if enabled), otherwise latest is used matrix_backup_borg_version: "" matrix_backup_borg_docker_image: "{{ matrix_backup_borg_docker_image_name_prefix }}etke.cc/borgmatic:{{ matrix_backup_borg_version }}" matrix_backup_borg_docker_image_name_prefix: "{{ 'localhost/' if matrix_backup_borg_container_image_self_build else 'registry.gitlab.com/' }}" @@ -30,6 +31,7 @@ matrix_backup_borg_location_source_directories: [] # postgres db backup matrix_backup_borg_postgresql_enabled: true +matrix_backup_borg_supported_postgres_versions: ['12', '13', '14'] matrix_backup_borg_postgresql_databases: [] matrix_backup_borg_postgresql_databases_hostname: "matrix-postgres" matrix_backup_borg_postgresql_databases_username: "matrix" @@ -55,7 +57,7 @@ matrix_backup_borg_storage_ssh_command: ssh -o "StrictHostKeyChecking accept-new matrix_backup_borg_storage_compression: lz4 # archive name format -matrix_backup_borg_storage_archive_name_format: "matrix-{now:%Y-%m-%d-%H%M%S}" +matrix_backup_borg_storage_archive_name_format: matrix-{now:%Y-%m-%d-%H%M%S} # repository passphrase matrix_backup_borg_storage_encryption_passphrase: "" @@ -68,7 +70,7 @@ matrix_backup_borg_retention_keep_monthly: 12 matrix_backup_borg_retention_keep_yearly: 2 # retention prefix -matrix_backup_borg_retention_prefix: "matrix-" +matrix_backup_borg_retention_prefix: matrix- # Default borgmatic configuration template which covers the generic use case. # You can customize it by controlling the various variables inside it. diff --git a/roles/matrix-backup-borg/tasks/setup_install.yml b/roles/matrix-backup-borg/tasks/setup_install.yml index 9c34c53f..1903d865 100644 --- a/roles/matrix-backup-borg/tasks/setup_install.yml +++ b/roles/matrix-backup-borg/tasks/setup_install.yml @@ -1,6 +1,16 @@ --- -- import_tasks: "{{ role_path }}/tasks/util/detect_existing_postgres_version.yml" - when: 'matrix_backup_borg_enabled|bool and matrix_backup_borg_postgresql_enabled|bool and matrix_postgres_backup_postgres_data_path != ""' +- block: + - import_tasks: "{{ role_path }}/../matrix-postgres/tasks/util/detect_existing_postgres_version.yml" + + - name: Fail if detected Postgres version is unsupported + fail: + msg: "You cannot use borg backup with such an old version ({{ matrix_postgres_detected_version }}) of Postgres. Consider upgrading - link to docs for upgrading Postgres: docs/maintenance-postgres.md#upgrading-postgresql" + when: "matrix_postgres_detected_version not in matrix_backup_borg_supported_postgres_versions" + + - name: Set the correct borg backup version to use + set_fact: + matrix_backup_borg_version: "{{ matrix_postgres_detected_version }}" + when: matrix_backup_borg_postgresql_enabled|bool and matrix_backup_borg_version == '' - name: Ensure borg paths exist file: diff --git a/roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml b/roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml deleted file mode 100644 index 0d50d93f..00000000 --- a/roles/matrix-backup-borg/tasks/util/detect_existing_postgres_version.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- - -# This utility aims to determine if there is some existing Postgres version in use or not. -# If there is, it also tries to detect the Docker image that corresponds to that version. - -- name: Initialize Postgres version determination variables (default to empty) - set_fact: - matrix_backup_borg_postgresql_detection_pg_version_path: "{{ matrix_postgres_data_path }}/PG_VERSION" - matrix_backup_borg_postgresql_detected_existing: false - matrix_backup_borg_postgresql_detected_version: "" - matrix_backup_borg_version: "" - -- name: Determine existing Postgres version (check PG_VERSION file) - stat: - path: "{{ matrix_backup_borg_postgresql_detection_pg_version_path }}" - register: result_pg_version_stat - -- set_fact: - matrix_backup_borg_postgresql_detected_existing: true - when: "result_pg_version_stat.stat.exists" - -- name: Determine existing Postgres version (read PG_VERSION file) - slurp: - src: "{{ matrix_backup_borg_postgresql_detection_pg_version_path }}" - register: result_pg_version - when: matrix_backup_borg_postgresql_detected_existing|bool - -- name: Determine existing Postgres version (make sense of PG_VERSION file) - set_fact: - matrix_backup_borg_postgresql_detected_version: "{{ result_pg_version['content']|b64decode|replace('\n', '') }}" - when: matrix_backup_borg_postgresql_detected_existing|bool - -- name: Determine corresponding Docker image version to detected version - set_fact: - matrix_backup_borg_version: "{{ matrix_backup_borg_postgresql_detected_version }}" - when: "matrix_backup_borg_postgresql_detected_version == '12' or matrix_backup_borg_postgresql_detected_version.startswith('12.') or matrix_backup_borg_postgresql_detected_version == '13' or matrix_backup_borg_postgresql_detected_version.startswith('13.') or matrix_backup_borg_postgresql_detected_version == '14' or matrix_backup_borg_postgresql_detected_version.startswith('14.')" - -- name: Fail if existing Postgres version is not supported by borgmatic docker image - fail: - msg: >- - Your Postgres v{{ matrix_backup_borg_postgresql_detected_version }} is not supported. - when: "matrix_backup_borg_version == ''" diff --git a/roles/matrix-backup-borg/templates/config.yaml.j2 b/roles/matrix-backup-borg/templates/config.yaml.j2 index 8ac2a8b2..2929db8b 100644 --- a/roles/matrix-backup-borg/templates/config.yaml.j2 +++ b/roles/matrix-backup-borg/templates/config.yaml.j2 @@ -7,18 +7,18 @@ location: exclude_patterns: {{ matrix_backup_borg_location_exclude_patterns|to_json }} storage: - compression: {{ matrix_backup_borg_storage_compression }} - ssh_command: {{ matrix_backup_borg_storage_ssh_command }} - archive_name_format: '{{ matrix_backup_borg_storage_archive_name_format }}' - encryption_passphrase: {{ matrix_backup_borg_storage_encryption_passphrase }} + compression: {{ matrix_backup_borg_storage_compression|to_json }} + ssh_command: {{ matrix_backup_borg_storage_ssh_command|to_json }} + archive_name_format: {{ matrix_backup_borg_storage_archive_name_format|to_json }} + encryption_passphrase: {{ matrix_backup_borg_storage_encryption_passphrase|to_json }} retention: - keep_hourly: {{ matrix_backup_borg_retention_keep_hourly }} - keep_daily: {{ matrix_backup_borg_retention_keep_daily }} - keep_weekly: {{ matrix_backup_borg_retention_keep_weekly }} - keep_monthly: {{ matrix_backup_borg_retention_keep_monthly }} - keep_yearly: {{ matrix_backup_borg_retention_keep_yearly }} - prefix: '{{ matrix_backup_borg_retention_prefix }}' + keep_hourly: {{ matrix_backup_borg_retention_keep_hourly|to_json }} + keep_daily: {{ matrix_backup_borg_retention_keep_daily|to_json }} + keep_weekly: {{ matrix_backup_borg_retention_keep_weekly|to_json }} + keep_monthly: {{ matrix_backup_borg_retention_keep_monthly|to_json }} + keep_yearly: {{ matrix_backup_borg_retention_keep_yearly|to_json }} + prefix: {{ matrix_backup_borg_retention_prefix|to_json }} consistency: checks: @@ -26,14 +26,14 @@ consistency: - archives hooks: -{% if matrix_backup_borg_postgresql_enabled %} +{% if matrix_backup_borg_postgresql_enabled and matrix_backup_borg_postgresql_databases|length > 0 %} postgresql_databases: {% for database in matrix_backup_borg_postgresql_databases %} - - name: {{ database }} - hostname: {{ matrix_backup_borg_postgresql_databases_hostname }} - username: {{ matrix_backup_borg_postgresql_databases_username }} - password: {{ matrix_backup_borg_postgresql_databases_password }} - port: {{ matrix_backup_borg_postgresql_databases_port }} + - name: {{ database|to_json }} + hostname: {{ matrix_backup_borg_postgresql_databases_hostname|to_json }} + username: {{ matrix_backup_borg_postgresql_databases_username|to_json }} + password: {{ matrix_backup_borg_postgresql_databases_password|to_json }} + port: {{ matrix_backup_borg_postgresql_databases_port|to_json }} {% endfor %} {% endif %} after_backup: From c520a758ec78f035a616195a141858ad11e2dbe5 Mon Sep 17 00:00:00 2001 From: Aine Date: Fri, 15 Apr 2022 19:43:45 +0300 Subject: [PATCH 3/3] fix linter --- roles/matrix-backup-borg/tasks/setup_install.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roles/matrix-backup-borg/tasks/setup_install.yml b/roles/matrix-backup-borg/tasks/setup_install.yml index 1903d865..6ef39863 100644 --- a/roles/matrix-backup-borg/tasks/setup_install.yml +++ b/roles/matrix-backup-borg/tasks/setup_install.yml @@ -9,7 +9,7 @@ - name: Set the correct borg backup version to use set_fact: - matrix_backup_borg_version: "{{ matrix_postgres_detected_version }}" + matrix_backup_borg_version: "{{ matrix_postgres_detected_version }}" when: matrix_backup_borg_postgresql_enabled|bool and matrix_backup_borg_version == '' - name: Ensure borg paths exist