Add borg backup playbook/roles/tasks + Implement for Vaultwarden.

This commit is contained in:
Viyurz 2024-02-22 19:09:43 +01:00
parent baab29b4a5
commit e31b9b260d
Signed by: Viyurz
SSH key fingerprint: SHA256:IskOHTmhHSJIvAt04N6aaxd5SZCVWW1Guf9tEcxIMj8
12 changed files with 170 additions and 26 deletions

View file

@ -18,3 +18,15 @@ sudo apt install -y certbot python3-certbot-dns-ovh
Copy the existing `secrets.yml.example` to `secrets.yml`, run `ansible-vault encrypt secrets.yml` to encrypt the file with a password, and finally edit the newly encrypted file with `ansible-vault edit secrets.yml`.
If you want to change the vault password run `ansible-vault rekey secrets.yml`.
## Backups
Run the `backup-services.yml` playbook once to setup the passphrase file.
After that, you can create a root cronjob to run this playbook without requiring interactivity:
```
ANSIBLE_ROLES_PATH=/home/viyurz/vps/roles/ ansible-playbook /home/viyurz/vps/playbooks/backup-services.yml -e include_secrets=false -e selected_projects=''
```
Here we leave `selected_projects` empty to backup all projects.

19
env.yml
View file

@ -7,7 +7,10 @@ docker_projects_dir: "{{ ansible_env['HOME'] }}/docker-projects"
uid_shift: 99999
cifs_host: "{{ cifs_credentials['username'] }}.your-storagebox.de"
# cifs_credentials is undefined when we run the backup playbook
# as a cronjob, so set empty default value to prevent errors,
# which is fine because we don't use it.
cifs_host: "{{ cifs_credentials['username'] | default('') }}.your-storagebox.de"
cifs_mounts:
backups:
@ -46,6 +49,20 @@ projects:
- vaultwarden
projects_to_backup:
- vaultwarden
borg_repodir: "{{ cifs_mounts['backups']['path'] }}/borg"
borg_passphrase_file: /etc/borg-passphrase.txt
borg_prune_options: |
--keep-within=1d
--keep-daily=7
--keep-weekly=4
--keep-monthly=12
--keep-yearly=10
# Ports exposed to host
ports:
coturn_listening: 3478

View file

@ -0,0 +1,31 @@
- name: Include variables files & run borg-init role
hosts: localhost
roles:
- include-vars
- borg-init
- name: Backup project(s)
hosts: localhost
vars:
run_backup: true
run_update: false
vars_prompt:
- name: selected_projects
prompt: "Choose projects to backup (leave empty to backup all. Projects list: {{ hostvars['localhost']['projects_to_backup'] }})"
private: false
unsafe: true
tasks:
- name: Backup project(s)
include_role:
name: "{{ project }}"
loop: "{{ (selected_projects | split) | default(projects_to_backup, true) }}"
loop_control:
# Do not use default variable name 'item' to prevent collisions with loops in roles.
loop_var: project
when: project in projects_to_backup
- name: Compact borg repository
hosts: localhost
roles:
- borg-compact

View file

@ -6,6 +6,9 @@
- name: Update project(s)
hosts: localhost
vars:
run_backup: false
run_update: true
vars_prompt:
- name: selected_projects
prompt: "Choose projects to update (Keep empty to update all. Projects list: {{ hostvars['localhost']['projects'] }})"

View file

@ -0,0 +1,4 @@
- name: Compact borg repository
command:
cmd: "borg compact {{ borg_repodir }}"
become: true

View file

@ -0,0 +1,35 @@
- name:
become: true
block:
- name: Install packages borgbackup & sqlite3
apt:
name:
- borgbackup
# SQLite required for Vaultwarden
- sqlite3
- name: Get borg passphrase file stat
stat:
path: "{{ borg_passphrase_file }}"
register: borg_stat_passphrase_file_result
- name: "Template borg-passphrase.txt to {{ borg_passphrase_file }}"
template:
src: borg-passphrase.txt
dest: "{{ borg_passphrase_file }}"
owner: root
group: root
mode: '600'
when: not borg_stat_passphrase_file_result.stat.exists or borg_update_passphrase | default(false) | bool
- name: Get borg repository stat
stat:
path: "{{ borg_repodir }}"
register: borg_stat_repodir_result
- name: Create borg repository
command:
cmd: "borg init --encryption repokey {{ borg_repodir }}"
environment:
BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}"
when: not borg_stat_repodir_result.stat.exists

View file

@ -0,0 +1 @@
{{ borg_passphrase }}

View file

@ -5,3 +5,4 @@
- name: Include secrets from secrets.yml file
include_vars:
file: "{{ playbook_dir }}/../secrets.yml"
when: include_secrets | default(true) | bool

View file

@ -0,0 +1,29 @@
- name:
become: true
block:
- name: Backup SQLite database
command:
cmd: |
sqlite3
"{{ volumes['vaultwarden_datadir'] }}/db.sqlite3"
".backup {{ volumes['vaultwarden_datadir'] }}/db-backup.sqlite3"
- name: Create borg backup
command:
cmd: |
borg create
--compression=lzma
"{{ borg_repodir }}::{{ role_name }}-{now:%Y-%m-%d_%H-%M-%S}"
{{ volumes['vaultwarden_datadir'] }}/db-backup.sqlite3
environment:
BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}"
- name: Prune borg repository
command:
cmd: |
borg prune
--glob-archives='{{ role_name }}-*'
{{ borg_prune_options }}
{{ borg_repodir }}
environment:
BORG_PASSCOMMAND: "cat {{ borg_passphrase_file }}"

View file

@ -1,26 +1,9 @@
- name: "Create {{ vaultwarden_project_dir }} project directory"
file:
path: "{{ vaultwarden_project_dir }}"
state: directory
- name: Include backup tasks
include_tasks:
file: backup.yml
when: run_backup | default(false) | bool
- name: Template docker-compose.yaml to project directory
template:
src: docker-compose.yaml
dest: "{{ vaultwarden_project_dir }}/docker-compose.yaml"
owner: "{{ ansible_env['USER'] }}"
group: "{{ ansible_env['USER'] }}"
mode: '640'
- name: "Create directory {{ volumes['vaultwarden_datadir'] }} with correct permissions"
file:
path: "{{ volumes['vaultwarden_datadir'] }}"
state: directory
owner: "{{ users['vaultwarden'] + uid_shift }}"
group: "{{ users['vaultwarden'] + uid_shift }}"
mode: '770'
become: true
- name: Pull/Create/Restart project services
community.docker.docker_compose:
project_src: "{{ vaultwarden_project_dir }}"
pull: "{{ docker_pull_images | bool }}"
- name: Include update tasks
include_tasks:
file: update.yml
when: run_update | default(false) | bool

View file

@ -0,0 +1,26 @@
- name: "Create {{ vaultwarden_project_dir }} project directory"
file:
path: "{{ vaultwarden_project_dir }}"
state: directory
- name: Template docker-compose.yaml to project directory
template:
src: docker-compose.yaml
dest: "{{ vaultwarden_project_dir }}/docker-compose.yaml"
owner: "{{ ansible_env['USER'] }}"
group: "{{ ansible_env['USER'] }}"
mode: '640'
- name: "Create directory {{ volumes['vaultwarden_datadir'] }} with correct permissions"
file:
path: "{{ volumes['vaultwarden_datadir'] }}"
state: directory
owner: "{{ users['vaultwarden'] + uid_shift }}"
group: "{{ users['vaultwarden'] + uid_shift }}"
mode: '770'
become: true
- name: Pull/Create/Restart project services
community.docker.docker_compose:
project_src: "{{ vaultwarden_project_dir }}"
pull: "{{ docker_pull_images | bool }}"

View file

@ -1,5 +1,7 @@
ansible_become_password:
borg_passphrase:
cifs_credentials:
username:
password: