From 069bf669bf462ed65c87956143fac3b918114fea Mon Sep 17 00:00:00 2001 From: "pulsar89.5" Date: Mon, 18 Dec 2023 17:12:52 +0100 Subject: [PATCH] refactor: Rewrite all --- defaults/main.yml | 26 +++++--- handlers/main.yml | 50 ++++++++------- tasks/configuration.yml | 84 +++++++++++++++++++------ tasks/configuration_borgserver.yml | 20 ++++++ tasks/configuration_borgwarehouse.yml | 38 +++++++++++ tasks/installation-apt.yml | 39 ++++++++++++ tasks/installation-atomic_container.yml | 18 ++++++ tasks/installation.yml | 27 -------- tasks/main.yml | 9 ++- tasks/restore.yml | 10 --- templates/borgmatic.service.j2 | 4 +- templates/borgmatic.timer.j2 | 2 + templates/config.yaml.j2 | 60 +++++++++++++----- vars/main.yml | 13 ++++ 14 files changed, 293 insertions(+), 107 deletions(-) create mode 100644 tasks/configuration_borgserver.yml create mode 100644 tasks/configuration_borgwarehouse.yml create mode 100644 tasks/installation-apt.yml create mode 100644 tasks/installation-atomic_container.yml delete mode 100644 tasks/installation.yml delete mode 100644 tasks/restore.yml create mode 100644 vars/main.yml diff --git a/defaults/main.yml b/defaults/main.yml index a740a89..20aa271 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,11 +1,8 @@ --- # defaults file for borgmatic -borgmatic_distribution_release: bullseye - -borgmatic_keys: - private: "" - public: "" +# Define path to store borgmatic configuration and ssh keys +borgmatic_conf_path: /etc/borgmatic.d borgmatic_checks: - name: repository @@ -29,7 +26,22 @@ borgmatic_retention: weekly: 4 borgmatic_name: "{{ inventory_hostname }}_{now}" -borgmatic_compression: none +borgmatic_compression: lz4 borgmatic_passphrase: "" -borgmatic_restore_first: false +borgmatic_actions: {} + +borgmatic_mariadb_enabled: false +borgmatic_postgresql_enabled: false +borgmatic_restore_first: true + +# Informations to configure BorgWarehouse +borgmatic_borgwarehouse_url: "" +borgmatic_borgwarehouse_key: "" +borgmatic_borgwarehouse_alias: "{{ inventory_hostname }}" +borgmatic_borgwarehouse_sshPublicKey: "" +borgmatic_borgwarehouse_storageSize: 100 +borgmatic_borgwarehouse_comment: "" +borgmatic_borgwarehouse_alert: 90000 # one day +borgmatic_borgwarehouse_lanCommand: true +borgmatic_borgwarehouse_appendOnlyMode: false diff --git a/handlers/main.yml b/handlers/main.yml index 5218062..1fe51c3 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,31 +1,35 @@ --- # handlers file for borgmatic -- name: Créer le dépôt +- name: Apply installation ansible.builtin.command: - cmd: borg init -e repokey-blake2 {{ item.path }} + argv: + - /usr/bin/rpm-ostree + - apply-live + become: true + +- name: Initialize repository + ansible.builtin.command: + argv: + - "{{ which_borgmatic.stdout }}" + - init + - --encryption + - repokey + when: repo_infos | length == 0 become: true loop: "{{ borgmatic_repositories }}" - register: borg_init - failed_when: - - "'A repository already exists' not in borg_init.stderr" - - borg_init.rc != 0 - changed_when: - - "'A repository already exists' not in borg_init.stderr" - - borg_init.rc == 0 -- name: Activer la planification - ansible.builtin.systemd: - daemon_reload: true - enabled: true - state: stopped - name: borgmatic.timer - become: true - -- name: Activer et démarrer le service - ansible.builtin.systemd: - daemon_reload: true - enabled: false - state: started - name: borgmatic.service +- name: Restore repository + ansible.builtin.command: + argv: + - "{{ which_borgmatic.stdout }}" + - extract + - --archive + - latest + - --destination + - / + when: + - repo_infos | length > 0 + - borgmatic_restore_first become: true + loop: "{{ borgmatic_repositories }}" diff --git a/tasks/configuration.yml b/tasks/configuration.yml index 5e8e6f4..1f5ae91 100644 --- a/tasks/configuration.yml +++ b/tasks/configuration.yml @@ -1,33 +1,63 @@ --- # tasks file for borgmatic +# +- name: Récupérer le chemin complet du binaire + ansible.builtin.command: + cmd: which borgmatic + become: true + register: which_borgmatic -- name: Déployer la clef privée - ansible.builtin.copy: - content: "{{ borgmatic_keys.private }}" - dest: /etc/borgmatic/id_ed25519 - owner: root - group: root - mode: u=rw,g=,o= +- name: Créer l'exemple de configuration + ansible.builtin.command: + argv: + - "{{ which_borgmatic.stdout }}" + - config + - generate + - --destination + - "{{ borgmatic_conf_path }}/config.yaml" + creates: "{{ borgmatic_conf_path }}/config.yaml" become: true -- name: Déployer la clef publique - ansible.builtin.copy: - content: "{{ borgmatic_keys.public }}" - dest: /etc/borgmatic/id_ed25519.pub - owner: root - group: root - mode: u=rw,g=r,o=r +- name: Créer la paire de clés + community.crypto.openssh_keypair: + path: "{{ borgmatic_conf_path }}/id_ed25519" + comment: borgmatic@{{ inventory_hostname }} + type: ed25519 become: true +- name: Récupérer le contenu de la clé publique + ansible.builtin.slurp: + src: "{{ borgmatic_conf_path }}/id_ed25519.pub" + become: true + register: id_ed25519 + +- name: Import task to manage borgwarehouse repository + ansible.builtin.import_tasks: + file: configuration_borgwarehouse.yml + when: borgmatic_borgwarehouse_url | length > 0 + +- name: Import task to manage borgserver repository + ansible.builtin.import_tasks: + file: configuration_borgserver.yml + when: borgmatic_server | length > 0 + - name: Déployer la configuration de SSH ansible.builtin.blockinfile: path: /root/.ssh/config + owner: root + group: root + mode: u=rw,g=r,o= create: true marker: "# {mark} ANSIBLE MANAGED BLOCK for role_borgmatic" block: | {% for repository in borgmatic_repositories %} Host {{ repository.path | ansible.builtin.urlsplit('hostname') }} - IdentityFile /etc/borgmatic/id_ed25519 + Compression yes + Protocol 2 + PreferredAuthentications=publickey + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + IdentityFile {{ borgmatic_conf_path }}/id_ed25519 IdentitiesOnly yes {% endfor %} become: true @@ -35,12 +65,15 @@ - name: Déployer la configuration ansible.builtin.template: src: config.yaml.j2 - dest: /etc/borgmatic/config.yaml + dest: "{{ borgmatic_conf_path }}/config.yaml" owner: root group: root mode: u=rw,g=,o= + validate: borgmatic config validate --config %s become: true - notify: Créer le dépôt + notify: + - Initialize repository + - Restore repository - name: Déployer le service ansible.builtin.template: @@ -50,7 +83,13 @@ group: root mode: u=rw,g=r,o=r become: true - notify: Activer et démarrer le service + +- name: S'assurer que le service est désactivé + ansible.builtin.systemd: + enabled: false + state: stopped + name: borgmatic.service + become: true - name: Déployer le service et la planification ansible.builtin.template: @@ -60,4 +99,11 @@ group: root mode: u=rw,g=r,o=r become: true - notify: Activer la planification + +- name: Activer la planification + ansible.builtin.systemd: + daemon_reload: true + enabled: true + state: started + name: borgmatic.timer + become: true diff --git a/tasks/configuration_borgserver.yml b/tasks/configuration_borgserver.yml new file mode 100644 index 0000000..ddd616f --- /dev/null +++ b/tasks/configuration_borgserver.yml @@ -0,0 +1,20 @@ +--- + +- name: Créer le dépôt sur Borg server + ansible.builtin.file: + path: "{{ borgmatic_server.repo_path }}/{{ inventory_hostname }}" + state: directory + owner: "{{ borgmatic_server.user }}" + group: "{{ borgmatic_server.group }}" + mode: u=rwX,g=rX,o= + become: true + delegate_to: "{{ borgmatic_server.host }}" + +- name: Ajouter la clef publique + ansible.posix.authorized_key: + user: "{{ borgmatic_server.user }}" + state: present + key: "{{ key['content'] | b64decode }}" + key_options: 'command="cd {{ borgmatic_server.repo_path }}/{{ inventory_hostname }};borg serve --restrict-to-path {{ borgmatic_server.repo_path }}/{{ inventory_hostname }}",restrict' + become: true + delegate_to: "{{ borgmatic_server.host }}" diff --git a/tasks/configuration_borgwarehouse.yml b/tasks/configuration_borgwarehouse.yml new file mode 100644 index 0000000..4ad5e77 --- /dev/null +++ b/tasks/configuration_borgwarehouse.yml @@ -0,0 +1,38 @@ +--- + +- name: Get list of repositories + ansible.builtin.uri: + url: "{{ borgmatic_borgwarehouse_url }}/api/repo" + method: GET + headers: + Authorization: "Bearer {{ borgmatic_borgwarehouse_key }}" + Content-Type: "application/json" + body_format: json + return_content: true + register: repo_list + +- name: Get repository informations + ansible.builtin.set_fact: + repo_infos: "{{ repo_list.json.repoList | selectattr('alias', 'equalto', inventory_hostname) }}" + +- name: Create repository + ansible.builtin.uri: + url: "{{ borgmatic_borgwarehouse_url }}/api/repo/add" + method: POST + headers: + Authorization: "Bearer {{ borgmatic_borgwarehouse_key }}" + Content-Type: "application/json" + body_format: json + body: "{{ borgwarehouse_body }}" + when: repo_infos | length == 0 + +- name: Update repository + ansible.builtin.uri: + url: "{{ borgmatic_borgwarehouse_url }}/api/repo/id/{{ repo_infos[0].id }}/edit" + method: PATCH + headers: + Authorization: "Bearer {{ borgmatic_borgwarehouse_key }}" + Content-Type: "application/json" + body_format: json + body: "{{ borgwarehouse_body }}" + when: repo_infos | length > 0 diff --git a/tasks/installation-apt.yml b/tasks/installation-apt.yml new file mode 100644 index 0000000..a340e80 --- /dev/null +++ b/tasks/installation-apt.yml @@ -0,0 +1,39 @@ +--- +# tasks file for borgmatic + +- name: Installer les prérequis + ansible.builtin.apt: + name: + - pipx + - build-essential + - libacl1-dev + - libacl1 + - libb2-dev + - liblz4-dev + - libssl-dev + - libxxhash-dev + - libzstd-dev + - pkg-config + - python3 + - python3-dev + - python3-pkgconfig + become: true + +- name: Installer les paquets + community.general.pipx: + state: latest + name: "{{ item }}" + install_deps: true + include_injected: true + become: true + environment: + PIPX_HOME: /opt/pipx + PIPX_BIN_DIR: /usr/local/bin + loop: + - borgbackup + - borgmatic + +- name: S'assurer que les paquets sont inclus dans le path # noqa: no-changed-when + ansible.builtin.command: + cmd: pipx ensurepath + become: true diff --git a/tasks/installation-atomic_container.yml b/tasks/installation-atomic_container.yml new file mode 100644 index 0000000..31e078b --- /dev/null +++ b/tasks/installation-atomic_container.yml @@ -0,0 +1,18 @@ +--- +# tasks file for borgmatic + +- name: Install borgmatic package + ansible.builtin.command: + argv: + - /usr/bin/rpm-ostree + - install + - --allow-inactive + - --assumeyes + - --idempotent + - borgmatic + creates: /sysroot/ostree/repo/refs/heads/rpmostree/pkg/borgmatic + become: true + notify: Apply installation + +- name: Flush handlers + meta: flush_handlers diff --git a/tasks/installation.yml b/tasks/installation.yml deleted file mode 100644 index 8774963..0000000 --- a/tasks/installation.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -# tasks file for borgmatic - -- name: Installer python3-pip - ansible.builtin.apt: - name: python3-pip - state: latest - become: true - -- name: Installer borgbackup - ansible.builtin.apt: - name: borgbackup - state: latest - default_release: "{{ borgmatic_distribution_release }}-backports" - become: true - -- name: Installer le paquet avec pip - ansible.builtin.pip: - name: borgmatic - state: latest - become: true - -- name: Créer l'exemple de configuration - ansible.builtin.command: - cmd: generate-borgmatic-config - creates: /etc/borgmatic/config.yaml - become: true diff --git a/tasks/main.yml b/tasks/main.yml index 41f7ac3..07c2281 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,10 +2,9 @@ # tasks file for borgmatic - name: Importer les tâches d'installation - ansible.builtin.import_tasks: installation.yml + ansible.builtin.include_tasks: + file: installation-{{ ansible_facts['pkg_mgr'] }}.yml - name: Importer les tâches de configuration - ansible.builtin.import_tasks: configuration.yml - -- name: Importer les tâches de restauration - ansible.builtin.import_tasks: restore.yml + ansible.builtin.import_tasks: + file: configuration.yml diff --git a/tasks/restore.yml b/tasks/restore.yml deleted file mode 100644 index 75ccd1a..0000000 --- a/tasks/restore.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -# tasks file for borgmatic - -- name: Restaurer la sauvegarde la plus récente la sauvegarde la plus récente - ansible.builtin.command: - cmd: borgmatic extract --archive latest --path {{ directory }} - chdir: "{{ directory }}" - removes: "{{ directory }}" - when: borgmatic_restore_first - loop: "{{ borgmatic_source_directories }}" diff --git a/templates/borgmatic.service.j2 b/templates/borgmatic.service.j2 index 555e154..79e77f8 100644 --- a/templates/borgmatic.service.j2 +++ b/templates/borgmatic.service.j2 @@ -1,3 +1,5 @@ +# {{ ansible_managed }} + [Unit] Description=borgmatic backup Wants=network-online.target @@ -61,4 +63,4 @@ LogRateLimitIntervalSec=0 # Delay start to prevent backups running during boot. Note that systemd-inhibit requires dbus and # dbus-user-session to be installed. ExecStartPre=sleep 1m -ExecStart=systemd-inhibit --who="borgmatic" --what="sleep:shutdown" --why="Prevent interrupting scheduled backup" /usr/local/bin/borgmatic --verbosity -1 --syslog-verbosity 1 +ExecStart=systemd-inhibit --who="borgmatic" --what="sleep:shutdown" --why="Prevent interrupting scheduled backup" {{ which_borgmatic.stdout }} --verbosity -1 --syslog-verbosity 1 diff --git a/templates/borgmatic.timer.j2 b/templates/borgmatic.timer.j2 index d51c9b2..4a98b80 100644 --- a/templates/borgmatic.timer.j2 +++ b/templates/borgmatic.timer.j2 @@ -1,3 +1,5 @@ +# {{ ansible_managed }} + [Unit] Description=Run borgmatic backup diff --git a/templates/config.yaml.j2 b/templates/config.yaml.j2 index f10c8d6..34853f7 100644 --- a/templates/config.yaml.j2 +++ b/templates/config.yaml.j2 @@ -1,4 +1,5 @@ --- +# {{ ansible_managed }} repositories: {% for repository in borgmatic_repositories %} @@ -6,36 +7,65 @@ repositories: path: {{ repository.path }} {% endfor %} +{% if borgmatic_exclude_patterns | length > 0 %} exclude_patterns: {% for pattern in borgmatic_exclude_patterns %} - {{ pattern }} {% endfor %} +{% endif %} +{% if borgmatic_source_directories | length > 0%} source_directories: {% for directory in borgmatic_source_directories %} - {{ directory }} {% endfor %} +{% endif %} archive_name_format: {{ borgmatic_name }} compression: {{ borgmatic_compression }} encryption_passphrase: {{ borgmatic_passphrase }} -consistency: - checks: +checks: {% for check in borgmatic_checks %} - - name: {{ check.name }} - frequency: {{ check.frequency }} + - name: {{ check.name }} + frequency: {{ check.frequency }} {% endfor %} -hooks: - healthchecks: - ping_url: {{ borgmatic_healthchecks }} - send_logs: false - states: - - finish - - fail +healthchecks: + ping_url: {{ borgmatic_healthchecks }} + send_logs: false +# states: +# - finish +# - fail -retention: - keep_daily: {{ borgmatic_retention.daily }} - keep_monthly: {{ borgmatic_retention.monthly }} - keep_weekly: {{ borgmatic_retention.weekly }} +{% if borgmatic_retention | length > 0 %} +{% for param, value in borgmatic_retention.items() %} +keep_{{ param }}: {{ value }} +{% endfor %} +{% endif %} + +{% if borgmatic_actions | length > 0 %} +{% for param, values in borgmatic_actions.items() %} +{{ param }}: +{% for value in values %} + - {{ value }} +{% endfor %} +{% endfor %} +{% endif %} + +{% if borgmatic_mariadb_enabled %} +mariadb_databases: + - name: all + format: sql + add_drop_database: true +{% endif %} + +{% if borgmatic_postgresql_enabled %} +postgresql_databases: + - name: all + username: postgres + format: plain + pg_dump_command: sudo -u postgres pg_dump + pg_restore_command: sudo -u postgres pg_restore + psql_command: sudo -u postgres psql +{% endif %} diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..72ca385 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,13 @@ +--- +# vars file for borgmatic + +borgwarehouse_body: > + { + "alert": {{ borgmatic_borgwarehouse_alert }}, + "alias": "{{ borgmatic_borgwarehouse_alias }}", + "appendOnlyMode": {{ borgmatic_borgwarehouse_appendOnlyMode }}, + "comment": "{{ borgmatic_borgwarehouse_comment }}", + "lanCommand": {{ borgmatic_borgwarehouse_lanCommand }}, + "sshPublicKey": "{{ id_ed25519['content'] | b64decode | trim }}", + "storageSize": {{ borgmatic_borgwarehouse_storageSize | int }}, + }