diff --git a/group_vars/crans_server/vars.yml b/group_vars/crans_server/vars.yml index 9d0200955d9f051a4bbdee5a0f0620ad2c2d0648..63212423c882f71ea90a20f69be866441b4363a1 100644 --- a/group_vars/crans_server/vars.yml +++ b/group_vars/crans_server/vars.yml @@ -9,3 +9,18 @@ debian_mirror: http://mirror.adm.crans.org/debian ubuntu_mirror: http://mirror.adm.crans.org/ubuntu debian_components: main non-free ubuntu_components: main restricted universe multiverse + +glob_borg: + to_backup: + - /etc + - /var + path: /backup/borg + remote: + - borg@zephir.adm.crans.org:/backup/borg/{{ ansible_hostname }} + retention: + - ["daily", 4] + - ["monthly", 6] + consistency_check: + - disabled + extra_init: + - make-parent-dirs \ No newline at end of file diff --git a/host_vars/zephir.adm.crans.org.yml b/host_vars/zephir.adm.crans.org.yml new file mode 100644 index 0000000000000000000000000000000000000000..541870153a981b7f3f8755b854fe01121e8cce37 --- /dev/null +++ b/host_vars/zephir.adm.crans.org.yml @@ -0,0 +1,7 @@ +--- + +loc_borg: + to_exclude: + - /var/lib/backuppc + remote: + - /backup/borg/zephir diff --git a/hosts b/hosts index a7ef2273e59b60f989712f7941e9db4aae4ddc08..7ed9d2a52d4c41317b4f9c3bb4a99aa766229cca 100644 --- a/hosts +++ b/hosts @@ -23,6 +23,9 @@ # [test_vm] # re2o-test.adm.crans.org +[backups] +zephir.adm.crans.org + [certbot] gitzly.adm.crans.org diff --git a/plays/backup.yml b/plays/backup.yml index 7d4681003714b72abccf903e7283c3094446d047..1949a5ca9821bd29b6a11b762a67564e08dc8b1d 100755 --- a/plays/backup.yml +++ b/plays/backup.yml @@ -1,15 +1,15 @@ #!/usr/bin/env ansible-playbook --- -# zephir backups virtual machines. -# omnomnom backups home dirs. -# Rsync client on all server to allow backup -#- hosts: server -# vars: -# # Backup password -# backuppc_rsyncd_passwd: "{{ vault_backuppc_rsyncd_passwd }}" -# roles: ["rsync-client"] +- hosts: server + vars: + borg: '{{ glob_borg | default({}) | combine(loc_borg | default({})) }}' + mirror: '{{ glob_mirror | default({}) | combine(loc_mirror | default({})) }}' + roles: + - borgbackup-client -# Backuppc backup software -#- hosts: zephir.adm.crans.org,omnomnom.adm.crans.org -# roles: ["backuppc"] +- hosts: backups + vars: + borg: '{{ glob_borg | default({}) | combine(loc_borg | default({})) }}' + roles: + - borgbackup-server diff --git a/roles/borgbackup-client/handlers/main.yml b/roles/borgbackup-client/handlers/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..6cd8da2ff530e84dae46a68b862003934bb38c90 --- /dev/null +++ b/roles/borgbackup-client/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart cron + service: + name: cron + state: restarted diff --git a/roles/borgbackup-client/tasks/main.yml b/roles/borgbackup-client/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..2325ea277fd420a9144c7a25c05d2cee3bae6171 --- /dev/null +++ b/roles/borgbackup-client/tasks/main.yml @@ -0,0 +1,60 @@ +--- +- name: Pin borgmatic + template: + src: "apt/{{ item }}.j2" + dest: "/etc/apt/{{ item }}" + loop: + - sources.list.d/bullseye.list + - preferences.d/borgmatic-bullseye + when: ansible_lsb.release | int <= 10 + +- name: Install borgbackup + apt: + update_cache: true + name: + - borgbackup + - borgmatic + state: present + register: apt_result + retries: 3 + until: apt_result is succeeded + +- name: Ensures /etc/borgmatic exists + file: + path: /etc/borgmatic + state: directory + mode: 0700 + owner: root + +- name: Deploy ssh private key + template: + src: "borgmatic/id_ed25519_borg.j2" + dest: "/etc/borgmatic/id_ed25519_borg" + mode: 0600 + owner: root + +- name: Deploy borgmatic config + template: + src: "borgmatic/config.yaml.j2" + dest: "/etc/borgmatic/config.yaml" + mode: 0600 + owner: root + group: root + +- name: Init borg repository + command: + cmd: /usr/bin/borgmatic init -e repokey + register: borg_init + changed_when: '"does not exist" in borg_init.stderr' + +- name: Deploy borg cron + template: + src: "cron.d/borg.j2" + dest: "/etc/cron.d/borg" + notify: restart cron + +- name: Indicate role in motd + template: + src: update-motd.d/04-service.j2 + dest: /etc/update-motd.d/04-borgbackup + mode: 0755 diff --git a/roles/borgbackup-client/templates/apt/preferences.d/borgmatic-bullseye.j2 b/roles/borgbackup-client/templates/apt/preferences.d/borgmatic-bullseye.j2 new file mode 100644 index 0000000000000000000000000000000000000000..32e59b73d3771cdfc5edb5aa491305a93de47d93 --- /dev/null +++ b/roles/borgbackup-client/templates/apt/preferences.d/borgmatic-bullseye.j2 @@ -0,0 +1,12 @@ +{{ ansible_header | comment }} + + +Package: * +Pin: release n=bullseye +Pin-Priority: 1 + + +Package: borgmatic +Pin: release n=bullseye +Pin-Priority: 900 + diff --git a/roles/borgbackup-client/templates/apt/sources.list.d/bullseye.list.j2 b/roles/borgbackup-client/templates/apt/sources.list.d/bullseye.list.j2 new file mode 100644 index 0000000000000000000000000000000000000000..e8bbe8d247ff27563951c1d55e30db2189fba97e --- /dev/null +++ b/roles/borgbackup-client/templates/apt/sources.list.d/bullseye.list.j2 @@ -0,0 +1,3 @@ +{{ ansible_header | comment }} + +deb http://{{ mirror.name }}/debian bullseye main diff --git a/roles/borgbackup-client/templates/borgmatic/config.yaml.j2 b/roles/borgbackup-client/templates/borgmatic/config.yaml.j2 new file mode 100644 index 0000000000000000000000000000000000000000..94750a2c7ac7e3017cd60f48927b9fe760197a16 --- /dev/null +++ b/roles/borgbackup-client/templates/borgmatic/config.yaml.j2 @@ -0,0 +1,88 @@ +{{ ansible_header | comment }} + +location: + source_directories: +{% for dir in borg.to_backup %} + - {{ dir }} +{% endfor %} + + repositories: +{% for remote in borg.remote %} + - {{ remote }} +{% endfor %} + + exclude_patterns: + - '*.pyc' + - '\#*\#' + - '*~' +{% for pattern in borg.to_exclude | default([]) %} + - {{ pattern }} +{% endfor %} + + exclude_caches: true + + exclude_if_present: + - .nobackup + + borgmatic_source_directory: /tmp/borgmatic + +storage: + encryption_passphrase: {{ vault_borgbackup_passwd }} + ssh_command: ssh -i /etc/borgmatic/id_ed25519_borg + borg_base_directory: /etc/borgmatic + borg_config_directory: /etc/borgmatic/config/ + borg_cache_directory: /etc/borgmatic/cache + borg_security_directory: /etc/borgmatic/config/security + borg_keys_directory: /etc/borgmatic/config/keys + compression: 'lz4' + umask: 0077 + lock_wait: 5 + archive_name_format: '{hostname}-{now}' +{% set extra_init = borg.extra_init | default([]) %} +{% set extra_prune = borg.extra_prune | default([]) %} +{% set extra_create = borg.extra_create | default([]) %} +{% set extra_check = borg.extra_check | default([]) %} +{% if extra_init or extra_prune or extra_create or extra_check %} + extra_borg_options: +{% endif %} +{% if extra_init %} + # Extra command-line options to pass to "borg init". + init: {% for cmd in extra_init %}--{{ cmd }} {% endfor %} +{% endif %} +{% if extra_prune %} + # Extra command-line options to pass to "borg prune". + prune: {% for cmd in extra_prune %}--{{ cmd }} {% endfor %} +{% endif %} + +{% if extra_create %} + # Extra command-line options to pass to "borg create". + create: {% for cmd in extra_create %}--{{ cmd }} {% endfor %} +{% endif %} + +{% if extra_check %} + # Extra command-line options to pass to "borg check". + check: {% for cmd in extra_check %}--{{ cmd }} {% endfor %} +{% endif %} + +retention: +{% for retention in borg.retention %} + keep_{{ retention[0] }}: {{ retention[1] }} +{% endfor %} + prefix: '{hostname}-' + +consistency: + checks: +{% for check in borg.consistency_check %} + - {{ check }} +{% endfor %} + +{% if borg.hooks | default([]) %} + hooks: + {% for hook in borg.hooks %} + {{ hook.type }}: + {% for value in hook.values %} + - {{ value }} + {% endfor %} + {% endfor %} + umask: 0077 +{% endif %} diff --git a/roles/borgbackup-client/templates/borgmatic/id_ed25519_borg.j2 b/roles/borgbackup-client/templates/borgmatic/id_ed25519_borg.j2 new file mode 100644 index 0000000000000000000000000000000000000000..1ef022e0994c22897203d5f3025f486fbf70edd8 --- /dev/null +++ b/roles/borgbackup-client/templates/borgmatic/id_ed25519_borg.j2 @@ -0,0 +1 @@ +{{ vault_borgbackup_ssh_privkey }} diff --git a/roles/borgbackup-client/templates/cron.d/borg.j2 b/roles/borgbackup-client/templates/cron.d/borg.j2 new file mode 100644 index 0000000000000000000000000000000000000000..41c84ebd340fe23903cb058b5b3df8fd11270c3e --- /dev/null +++ b/roles/borgbackup-client/templates/cron.d/borg.j2 @@ -0,0 +1,5 @@ +{{ ansible_header | comment }} + +PATH=$PATH:/usr/sbin:/usr/bin:/usr/local/bin:/sbin:/bin + +{{ 60 | random(seed=inventory_hostname) }} {{ 24 | random(seed=inventory_hostname) }} * * * root borgmatic --syslog-verbosity 1 diff --git a/roles/borgbackup-client/templates/update-motd.d/04-service.j2 b/roles/borgbackup-client/templates/update-motd.d/04-service.j2 new file mode 100755 index 0000000000000000000000000000000000000000..fcbc611dc308602bb6b657a90d5961f0adc7428b --- /dev/null +++ b/roles/borgbackup-client/templates/update-motd.d/04-service.j2 @@ -0,0 +1,3 @@ +#!/usr/bin/tail +14 +{{ ansible_header | comment }} +[0m> [38;5;82mBorgbackup (Client)[0m a été déployé sur cette machine. Voir [38;5;6m/etc/borgmatic/[0m. diff --git a/roles/borgbackup-server/tasks/main.yml b/roles/borgbackup-server/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..052347d5261eb91d1afa313980336be853d26789 --- /dev/null +++ b/roles/borgbackup-server/tasks/main.yml @@ -0,0 +1,38 @@ +--- +- name: Install borgbackup + apt: + update_cache: true + name: + - borgbackup + state: present + register: apt_result + retries: 3 + until: apt_result is succeeded + +- name: Create borgbackup user + user: + create_home: yes + home: '/var/lib/borg/' + system: yes + state: present + update_password: always + name: borg + +- name: Ensures .ssh dir exists + file: + path: /var/lib/borg/.ssh + state: directory + mode: 0700 + owner: borg + +- name: Deploy authorized_keys + template: + src: "authorized_keys.j2" + dest: "/var/lib/borg/.ssh/authorized_keys" + mode: 0600 + +- name: Indicate role in motd + template: + src: update-motd.d/05-service.j2 + dest: /etc/update-motd.d/05-borg + mode: 0755 diff --git a/roles/borgbackup-server/templates/authorized_keys.j2 b/roles/borgbackup-server/templates/authorized_keys.j2 new file mode 100644 index 0000000000000000000000000000000000000000..9c3ff0ca0009e9ff6a40660d7e0cd5a065a7e060 --- /dev/null +++ b/roles/borgbackup-server/templates/authorized_keys.j2 @@ -0,0 +1,3 @@ +{{ ansible_header | comment }} + +command="borg serve --restrict-to-path {{ borg.path }}",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding {{ vault_borgbackup_ssh_pubkey }} diff --git a/roles/borgbackup-server/templates/update-motd.d/05-service.j2 b/roles/borgbackup-server/templates/update-motd.d/05-service.j2 new file mode 100755 index 0000000000000000000000000000000000000000..f27119aa58fb0b3c924ecf85c793a8d92d9f35c0 --- /dev/null +++ b/roles/borgbackup-server/templates/update-motd.d/05-service.j2 @@ -0,0 +1,3 @@ +#!/usr/bin/tail +14 +{{ ansible_header | comment }} +[0m> [38;5;82mBorgbackup (Serveur)[0m a été déployé sur cette machine. Les backups sont situés dans [38;5;6m{{ borg.path }}[0m.