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:
@@ -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
|
||||||
|
|||||||
@@ -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 {}
|
||||||
|
|||||||
Reference in New Issue
Block a user