aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md229
1 files changed, 208 insertions, 21 deletions
diff --git a/README.md b/README.md
index d556818..5281a01 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
-Ansible Role: BorgBackup
-========================
+# Ansible Role: BorgBackup
An Ansible role that installs and configures a systemd service for BorgBackup on
a client and (delegated) server.
@@ -9,8 +8,7 @@ The documentation assumes basic knowledge about BorgBackup. You can get up to
speed with Borg by reading their excellent documentation on
<https://borgbackup.readthedocs.io>.
-How it works
-------------
+## How it works
```mermaid
sequenceDiagram
@@ -27,8 +25,7 @@ borg-client->>Ansible: Store decryption keys
borg-client-->borg-server: Do Backup
```
-Installation
-------------
+## Installation
via ansible-galaxy
@@ -54,8 +51,7 @@ ansible-galaxy role install git+https://github.com/kliwniloc/ansible-role-borgba
name: kliwniloc.borgbackup
```
-Role Variables
---------------
+## Role Variables
For more details, see: [`defaults/main.yml`](defaults/main.yml)
@@ -76,7 +72,7 @@ will default to `borg_server_host`.
```yaml
borg_server_host: "" # Required
borg_server_host_ssh_key: "" # Required
-borg_server_host_url: {{ borg_server_host }} # Optional
+borg_server_host_url: { { borg_server_host } } # Optional
```
The role creates a user for the Borg repositories on the Borg server. You can
@@ -121,6 +117,8 @@ your Borg backups, but it is not used by default.
> If you want true end-to-end encryption, you should configure a passphrase
> Read more: [BorgBackup Security](https://borgbackup.readthedocs.io/en/stable/internals/security.html#offline-key-security)
+<!-- TODO: Include keyfile backup mode -->
+
`borg_included_dirs` and `borg_excluded_dirs` finally picks what directories
will be backed up by Borg.
@@ -167,18 +165,17 @@ see man-page systemd.timer(5).
borg_backup_script_location: /usr/local/bin/run_borg_backup
borg_backup_timer_name: borg_backup
borg_backup_service_name: borg_backup
-borg_backup_argument: '{{ borg_server_host_url }}'
-borg_systemd_oncalendar: '*-*-* 02:00:00'
+borg_backup_argument: "{{ borg_server_host_url }}"
+borg_systemd_oncalendar: "*-*-* 02:00:00"
borg_systemd_accuracysec: 60min
```
-Example Playbooks
------------------
+## Example Playbooks
-Simple Playbook
+### Simple Playbook
```yaml
-- name: >
+- name: >-
Add Borg backup to the borg-client and save the
decryption keys alongside the playbook
hosts: borg-client
@@ -192,10 +189,10 @@ Simple Playbook
- /opt/project
```
-Multiple Backup servers
+### Multiple Backup Servers
```yaml
-- name: >
+- name: >-
Add Borg backup with multiple borg servers to the borg-client and
save the decryption keys alongside the playbook
hosts: borg-client
@@ -212,12 +209,202 @@ Multiple Backup servers
borg_server_host_ssh_key: ssh-rsa BBBBBBBB...
```
-Dependencies
-------------
+### Multiple Repositories on Single Server, Single Client (Multi-Instance)
+
+> [!NOTE]
+> **This is considered a beta feature**
+> This feature is still being developed and has some quirks around it.
+> We plan to release this properly on the next major version with some breaking
+> changes to make this less of a footgun. Until then, read this section
+> carefully.
+
+When a single client host needs to back up different data sets to the same Borg
+server (e.g., system configs and user data), you can run the role multiple times
+with different `borg_repo_name` values.
+
+**Important:** Each invocation must have a unique `borg_backup_argument` to create
+separate systemd timer units.
+
+<!-- TODO: (next major version): Change default borg_backup_argument to include
+ borg_repo_name for uniqueness:
+ "{{ borg_server_host_url }}-{{ borg_repo_name }}".
+ This will be a breaking change requiring migration of existing systemd
+ units. -->
+
+```yaml
+- name: Configure multi-instance backup (same host, different repos)
+ hosts: borg-client
+ vars:
+ borg_server_host: borg-server
+ borg_server_host_ssh_key: ssh-rsa AAAAAAAA...
+ borg_decryption_keys_yaml_path: "{{ playbook_dir }}/decryption_keys.yml"
+
+ roles:
+ - role: kliwniloc.borgbackup
+ vars:
+ borg_repo_name: configs
+ borg_backup_argument: configs
+ borg_compression: zstd
+ borg_included_dirs:
+ - /etc
+ borg_systemd_oncalendar: "*-*-* 02:00:00"
+
+ - role: kliwniloc.borgbackup
+ vars:
+ borg_repo_name: home-data
+ borg_backup_argument: home-data
+ borg_compression: lz4
+ borg_included_dirs:
+ - /home
+ borg_excluded_dirs:
+ - /home/*/.cache
+ borg_systemd_oncalendar: "*-*-* 04:00:00"
+```
+
+This creates:
+
+- Two repositories on the Borg server: `/opt/borg/configs` and `/opt/borg/home-data`
+- Two systemd timers: `borg_backup@configs.timer` and `borg_backup@home-data.timer`
+- A single SSH keypair shared between both repositories
+- A single `authorized_keys` entry with both repositories in `--restrict-to-repository`
+
+## Important Behaviors and Limitations
+
+### Consistent `--append-only` Setting Required
+
+All repositories for a given host must use the same `borg_mode_append_only`
+setting. The role will fail with an error if you attempt to configure
+repositories with conflicting `--append-only` settings for the same host.
+
+This is because the SSH `authorized_keys` entry uses a single `--append-only`
+flag that applies to all repositories accessible via that key.
+
+```yaml
+# This will FAIL - conflicting append-only settings
+roles:
+ - role: kliwniloc.borgbackup
+ vars:
+ borg_repo_name: configs
+ borg_mode_append_only: false # ERROR: inconsistent
+
+ - role: kliwniloc.borgbackup
+ vars:
+ borg_repo_name: home-data
+ borg_mode_append_only: true # ERROR: inconsistent
+```
+
+### Single SSH Key per Host\*\*
+
+The role generates one SSH keypair per client host. All repositories for that
+host share the same SSH key for authentication to the Borg server.
+
+### Decryption Keys Storage Format
+
+Decryption keys are stored in the `decryption_keys.yml` file using the format:
+
+```yaml
+hostname_repo_name: |
+ To restore key use borg key import --paper /path/to/repo
+ BORG PAPER KEY v1
+ ...
+```
+
+For hosts with multiple repos, each repository has its own entry:
+
+- `borg-client_configs`
+- `borg-client_home-data`
+
+### Deprovisioning Borg Repositories
+
+This role does not currently handle deprovisioning or removing repositories.
+Deprovisioning must be done manually or via separate playbooks.
+
+### Removing a Repository
+
+To remove a specific repository (applies to both single and multi-instance setups):
+
+1. Stop and disable the systemd timer and service:
+
+ ```bash
+ systemctl stop borg_backup@ARGUMENT.timer
+ systemctl disable borg_backup@ARGUMENT.timer
+ systemctl stop borg_backup@ARGUMENT.service
+ systemctl disable borg_backup@ARGUMENT.service
+ ```
+
+ Replace `ARGUMENT` with the `borg_backup_argument` value for that repository.
+
+2. Remove the backup script:
+
+ ```bash
+ rm /usr/local/bin/run_borg_backup@ARGUMENT
+ ```
+
+3. _(Multi-instance only)_ Edit the base backup script to remove the repository block:
+
+ ```bash
+ # Edit /usr/local/bin/run_borg_backup
+ # Remove the ANSIBLE MANAGED BLOCK for the deleted repository
+ ```
+
+4. _(If other repositories remain)_ Update `authorized_keys` on the Borg server
+ to remove the repository restriction. Edit `/opt/borg/.ssh/authorized_keys`
+ and remove the `--restrict-to-repository /opt/borg/REPONAME` from the
+ appropriate line.
+
+ If this is the last repository for the host, remove the entire line instead.
+
+5. Delete the repository on the Borg server:
+
+ ```bash
+ ssh borg@SERVER "borg delete /opt/borg/REPONAME"
+ # Or simply: ssh borg@SERVER "rm -rf /opt/borg/REPONAME"
+ ```
+
+6. Remove the decryption key entry from your `decryption_keys.yml`.
+
+## Deprovisioning a Complete Host
+
+To remove all backup configuration for a host:
+
+1. Stop and disable all systemd timers and services:
+
+ ```bash
+ systemctl list-units --type=timer --all | grep borg_backup
+ # For each relevant timer:
+ systemctl stop borg_backup@*.timer
+ systemctl disable borg_backup@*.timer
+ ```
+
+2. Remove all backup scripts:
+
+ ```bash
+ rm -f /usr/local/bin/run_borg_backup*
+ ```
+
+3. Remove the SSH key from the Borg server's `authorized_keys`:
+
+ ```bash
+ # On the Borg server, edit /opt/borg/.ssh/authorized_keys
+ # Remove the line containing root@HOSTNAME
+ ```
+
+4. Delete all repositories for the host on the Borg server:
+
+ ```bash
+ ssh borg@SERVER "rm -rf /opt/borg/HOSTNAME"
+ # For multi-instance:
+ ssh borg@SERVER "rm -rf /opt/borg/HOSTNAME_repo1"
+ ssh borg@SERVER "rm -rf /opt/borg/HOSTNAME_repo2"
+ ```
+
+5. Remove all decryption key entries for the host from your
+ `decryption_keys.yml`.
+
+## Dependencies
None.
-License
--------
+## License
MIT