Encrypt borg repos with repokey-blake2 + shared passphrase

borg_passphrase is required (Semaphore secret, same across hosts).
The role writes it to /etc/borgmatic/passphrase (0600 root) and
configures borgmatic to use BORG_PASSCOMMAND=cat /etc/borgmatic/passphrase,
and runs `borg init --encryption=repokey-blake2` with BORG_PASSPHRASE in
the env. no_log on the tasks that touch the passphrase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 21:58:14 +02:00
parent 885a617388
commit 54e111338d
2 changed files with 22 additions and 2 deletions
+4 -1
View File
@@ -120,9 +120,12 @@
- name: Initialize borg repository (no-op if already initialized) - name: Initialize borg repository (no-op if already initialized)
ansible.builtin.command: ansible.builtin.command:
cmd: borg init --encryption=none {{ borgcontroller_repo_uri }} cmd: borg init --encryption=repokey-blake2 {{ borgcontroller_repo_uri }}
environment:
BORG_PASSPHRASE: "{{ borg_passphrase }}"
register: _borg_init register: _borg_init
changed_when: _borg_init.rc == 0 changed_when: _borg_init.rc == 0
failed_when: failed_when:
- _borg_init.rc != 0 - _borg_init.rc != 0
- "'already exists' not in (_borg_init.stderr | default(''))" - "'already exists' not in (_borg_init.stderr | default(''))"
no_log: true
+18 -1
View File
@@ -8,6 +8,13 @@
when: inventory_hostname in (backup_hosts | default({})) when: inventory_hostname in (backup_hosts | default({}))
block: block:
- name: Ensure borg_passphrase is set (Semaphore secret)
ansible.builtin.assert:
that:
- borg_passphrase is defined
- borg_passphrase | length > 0
fail_msg: "borg_passphrase must be defined (provided by Semaphore secrets)"
- name: Install borgmatic - name: Install borgmatic
ansible.builtin.package: ansible.builtin.package:
name: borgmatic name: borgmatic
@@ -21,6 +28,15 @@
group: root group: root
mode: '0750' mode: '0750'
- name: Write borg passphrase file
ansible.builtin.copy:
dest: /etc/borgmatic/passphrase
content: "{{ borg_passphrase }}"
owner: root
group: root
mode: '0600'
no_log: true
- name: Ensure root has an SSH key for the borg server - name: Ensure root has an SSH key for the borg server
ansible.builtin.user: ansible.builtin.user:
name: root name: root
@@ -36,7 +52,7 @@
- borgcontroller_username is defined - borgcontroller_username is defined
- borgcontroller_password is defined - borgcontroller_password is defined
- name: Build borgmatic config (strip controller-only keys, inject repository) - name: Build borgmatic config (strip controller-only keys, inject repository + passcommand)
ansible.builtin.set_fact: ansible.builtin.set_fact:
_borgmatic_config: >- _borgmatic_config: >-
{{ {{
@@ -44,6 +60,7 @@
| dict2items | dict2items
| rejectattr('key', 'in', ['storage_size_gb']) | rejectattr('key', 'in', ['storage_size_gb'])
| items2dict) | items2dict)
| combine({'encryption_passcommand': 'cat /etc/borgmatic/passphrase'})
| combine( | combine(
{'repositories': [{'path': borgcontroller_repo_uri, 'label': inventory_hostname}]} {'repositories': [{'path': borgcontroller_repo_uri, 'label': inventory_hostname}]}
if borgcontroller_repo_uri is defined else {} if borgcontroller_repo_uri is defined else {}