Compare commits
10 commits
967780f160
...
63527da633
Author | SHA1 | Date | |
---|---|---|---|
63527da633 | |||
4c9e3b1830 | |||
b69c807b82 | |||
|
535396963a | ||
|
a633f76efc | ||
|
e8595c4167 | ||
|
35d84f2f7f | ||
|
f7a45a9f7a | ||
|
fd989a95b1 | ||
|
e17443ad10 |
11 changed files with 80 additions and 55 deletions
|
@ -1,2 +1,4 @@
|
||||||
skip_list:
|
skip_list:
|
||||||
- '106' # Role name {} does not match ``^[a-z][a-z0-9_]+$`` pattern'
|
- "106" # Role name {} does not match ``^[a-z][a-z0-9_]+$`` pattern'
|
||||||
|
warn_list:
|
||||||
|
- yaml[line-length]
|
||||||
|
|
14
.github/workflows/push.yml
vendored
14
.github/workflows/push.yml
vendored
|
@ -1,14 +0,0 @@
|
||||||
name: ansible-lint
|
|
||||||
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: ansible-lint
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
- uses: actions/setup-python@v2
|
|
||||||
- run: pip install ansible ansible-lint
|
|
||||||
- run: ansible-lint --version
|
|
||||||
- run: ansible-lint .
|
|
10
.woodpecker/push.yaml
Normal file
10
.woodpecker/push.yaml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: lint
|
||||||
|
image: docker.io/libary/python:3-alpine
|
||||||
|
commands:
|
||||||
|
- pip install ansible ansible-lint
|
||||||
|
- ansible-lint --version
|
||||||
|
- ansible-lint .
|
|
@ -31,8 +31,8 @@ Each folder has a `path` and an `exclude` property (which defaults to nothing).
|
||||||
|
|
||||||
Each database has a `name` property which will be the name of the restic snapshot (`{{ database.name }}.sql`). They also have a `dump_command` property which is the command to dump the database to stdout (like `mysqldump dbname`).
|
Each database has a `name` property which will be the name of the restic snapshot (`{{ database.name }}.sql`). They also have a `dump_command` property which is the command to dump the database to stdout (like `mysqldump dbname`).
|
||||||
|
|
||||||
- `restic_forget`: run `restic forget` as `ExecStartPost` with `--keep-within {{ restic_forget_keep_within }}` (`true`)
|
- `restic_forget`: run `restic forget` as `ExecStartPost` (`true`)
|
||||||
- `restic_forget_keep_within`: period of time to use with `--keep-within` (`30d`)
|
- `restic_forget_args`: period of time to keep backups for. args passed to `restic forget` if `restic_forget` is enabled (`--keep-within 30d`)
|
||||||
- `restic_prune`: run `restic prune` as `ExecStartPost` (`true`)
|
- `restic_prune`: run `restic prune` as `ExecStartPost` (`true`)
|
||||||
|
|
||||||
### SSH/SFTP backend configuration
|
### SSH/SFTP backend configuration
|
||||||
|
@ -49,7 +49,7 @@ The SSH configuration will be written in `{{ restic_user_home }}/.ssh/config`.
|
||||||
### S3 backend configuration
|
### S3 backend configuration
|
||||||
|
|
||||||
- `restic_ssh_enabled`: set to false
|
- `restic_ssh_enabled`: set to false
|
||||||
- `restic_repository_name`: set to s3 endpoint + bucket, restic syntax (e.g. `s3:https://s3.fr-par.scw.cloud/restic-bucket`)
|
- `restic_repository`: set to s3 endpoint + bucket, restic syntax (e.g. `s3:https://s3.fr-par.scw.cloud/restic-bucket`)
|
||||||
- `restic_aws_access_key_id`: `AWS_ACCESS_KEY_ID`
|
- `restic_aws_access_key_id`: `AWS_ACCESS_KEY_ID`
|
||||||
- `restic_aws_secret_access_key`: `AWS_SECRET_ACCESS_KEY`
|
- `restic_aws_secret_access_key`: `AWS_SECRET_ACCESS_KEY`
|
||||||
|
|
||||||
|
@ -70,7 +70,6 @@ You can see the logs of the backup with `journalctl`. (`journalctl -xefu restic-
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
|
|
||||||
- hosts: myhost
|
- hosts: myhost
|
||||||
roles: restic
|
roles: restic
|
||||||
vars:
|
vars:
|
||||||
|
@ -97,7 +96,6 @@ S3 example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
|
|
||||||
- hosts: myhost
|
- hosts: myhost
|
||||||
roles: restic
|
roles: restic
|
||||||
vars:
|
vars:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
restic_install: false
|
restic_install: false
|
||||||
restic_version: 0.14.0
|
restic_version: 0.17.3
|
||||||
restic_path: /usr/local/bin/restic
|
restic_path: /usr/local/bin/restic
|
||||||
restic_user: root
|
restic_user: root
|
||||||
restic_user_home: /root
|
restic_user_home: /root
|
||||||
|
@ -14,7 +14,7 @@ restic_folders: []
|
||||||
restic_databases: []
|
restic_databases: []
|
||||||
restic_dump_compression_enabled: false
|
restic_dump_compression_enabled: false
|
||||||
restic_forget: true
|
restic_forget: true
|
||||||
restic_forget_keep_within: 30d
|
restic_forget_args: "--keey-within 30d"
|
||||||
restic_prune: true
|
restic_prune: true
|
||||||
restic_check: true
|
restic_check: true
|
||||||
|
|
||||||
|
@ -25,3 +25,10 @@ restic_ssh_private_key_path: "/root/.ssh/backup"
|
||||||
|
|
||||||
restic_systemd_timer_on_calender: "*-*-* 03:00:00"
|
restic_systemd_timer_on_calender: "*-*-* 03:00:00"
|
||||||
restic_systemd_timer_randomized_delay_sec: 0
|
restic_systemd_timer_randomized_delay_sec: 0
|
||||||
|
|
||||||
|
restic_failure_webhook_url: null
|
||||||
|
|
||||||
|
restic_arch_map:
|
||||||
|
i386: '386'
|
||||||
|
x86_64: 'amd64'
|
||||||
|
aarch64: 'arm64'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
---
|
---
|
||||||
- name: systemd reload
|
- name: Reload systemd
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
daemon_reload: yes
|
daemon_reload: true
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
galaxy_info:
|
galaxy_info:
|
||||||
role_name: restic
|
role_name: restic
|
||||||
author: angristan
|
author: jakew
|
||||||
description: Ansible role for Restic
|
description: Ansible role for Restic - forked from angristan/restic
|
||||||
license: MIT
|
license: MIT
|
||||||
min_ansible_version: 2.4
|
min_ansible_version: "2.4"
|
||||||
|
|
||||||
platforms:
|
platforms:
|
||||||
- name: Debian
|
- name: Debian
|
||||||
|
|
|
@ -1,34 +1,35 @@
|
||||||
---
|
---
|
||||||
- name: Install fuse (to mount repositories)
|
- name: Install fuse (to mount repositories)
|
||||||
apt:
|
ansible.builtin.package:
|
||||||
name: fuse
|
name: fuse
|
||||||
|
|
||||||
- name: Install bzip2 (to install restic)
|
- name: Install bzip2 (to install restic)
|
||||||
apt:
|
ansible.builtin.package:
|
||||||
name: bzip2
|
name: bzip2
|
||||||
|
|
||||||
- name: Install pigz (to compress db dumps)
|
- name: Install pigz (to compress db dumps)
|
||||||
apt:
|
ansible.builtin.package:
|
||||||
name: pigz
|
name: pigz
|
||||||
|
|
||||||
- name: Download restic
|
- name: Download restic
|
||||||
ansible.builtin.get_url:
|
ansible.builtin.get_url:
|
||||||
url: "https://github.com/restic/restic/releases/download/v{{ restic_version }}/restic_{{ restic_version }}_linux_{{ ansible_architecture }}.bz2"
|
url: "https://github.com/restic/restic/releases/download/v{{ restic_version }}/restic_{{ restic_version }}_linux_{{ restic_arch_map[ansible_architecture] | default(ansible_architecture) }}.bz2"
|
||||||
dest: "/tmp/restic_{{ restic_version }}_linux_amd64.bz2"
|
dest: "/tmp/restic_{{ restic_version }}_linux_{{ restic_arch_map[ansible_architecture] | default(ansible_architecture) }}.bz2"
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
- name: Extract restic
|
- name: Extract restic
|
||||||
command: "bzip2 -d /tmp/restic_{{ restic_version }}_linux_amd64.bz2"
|
ansible.builtin.command: "bzip2 -d /tmp/restic_{{ restic_version }}_linux_{{ restic_arch_map[ansible_architecture] | default(ansible_architecture) }}.bz2"
|
||||||
args:
|
args:
|
||||||
creates: "/tmp/restic_{{ restic_version }}_linux_amd64"
|
creates: "/tmp/restic_{{ restic_version }}_linux_{{ restic_arch_map[ansible_architecture] | default(ansible_architecture) }}"
|
||||||
|
|
||||||
- name: Install restic
|
- name: Install restic
|
||||||
ansible.builtin.copy:
|
ansible.builtin.copy:
|
||||||
remote_src: true
|
remote_src: true
|
||||||
src: "/tmp/restic_{{ restic_version }}_linux_amd64"
|
src: "/tmp/restic_{{ restic_version }}_linux_{{ restic_arch_map[ansible_architecture] | default(ansible_architecture) }}"
|
||||||
dest: "{{ restic_path }}"
|
dest: "{{ restic_path }}"
|
||||||
mode: 0755
|
mode: "0755"
|
||||||
|
|
||||||
- name: Remove downloaded file
|
- name: Remove downloaded file
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "/tmp/restic_{{ restic_version }}_linux_amd64"
|
path: "/tmp/restic_{{ restic_version }}_linux_{{ restic_arch_map[ansible_architecture] | default(ansible_architecture) }}"
|
||||||
state: absent
|
state: absent
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
path: "{{ restic_path }}"
|
path: "{{ restic_path }}"
|
||||||
register: restic_binary
|
register: restic_binary
|
||||||
|
|
||||||
- include_tasks: install.yml
|
- name: Include install.yml if restic is not installed or restic_install is true
|
||||||
|
ansible.builtin.include_tasks: install.yml
|
||||||
when: not restic_binary.stat.exists or restic_install
|
when: not restic_binary.stat.exists or restic_install
|
||||||
|
|
||||||
- name: Overwrite SSH config for backup server
|
- name: Overwrite SSH config for backup server
|
||||||
|
@ -38,14 +39,22 @@
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
vars:
|
vars:
|
||||||
restic_folders_combined: "{{ restic_default_folders + restic_folders }}"
|
restic_folders_combined: "{{ restic_default_folders + restic_folders }}"
|
||||||
notify: systemd reload
|
notify: Reload systemd
|
||||||
|
|
||||||
|
- name: Add systemd service for restic failure
|
||||||
|
when: restic_failure_webhook_url is not none
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: restic-failure.service.j2
|
||||||
|
dest: /etc/systemd/system/restic-failure.service
|
||||||
|
mode: "0644"
|
||||||
|
notify: Reload systemd
|
||||||
|
|
||||||
- name: Add systemd timer for restic
|
- name: Add systemd timer for restic
|
||||||
ansible.builtin.template:
|
ansible.builtin.template:
|
||||||
src: restic-backup.timer.j2
|
src: restic-backup.timer.j2
|
||||||
dest: /etc/systemd/system/restic-backup.timer
|
dest: /etc/systemd/system/restic-backup.timer
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
notify: systemd reload
|
notify: Reload systemd
|
||||||
|
|
||||||
- name: Enable and start restic timer
|
- name: Enable and start restic timer
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Restic backup
|
Description=Restic backup
|
||||||
|
{% if restic_failure_webhook_url is not none %}
|
||||||
|
OnFailure=restic-failure.service
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
@ -19,6 +22,8 @@ Environment="AWS_ACCESS_KEY_ID={{ restic_aws_access_key_id}}"
|
||||||
Environment="AWS_SECRET_ACCESS_KEY={{ restic_aws_secret_access_key}}"
|
Environment="AWS_SECRET_ACCESS_KEY={{ restic_aws_secret_access_key}}"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
ExecStartPre=/bin/sh -c '{{ restic_path }} snapshots || {{ restic_path }} init'
|
||||||
|
|
||||||
{% if restic_check %}
|
{% if restic_check %}
|
||||||
ExecStartPre={{ restic_path }} check
|
ExecStartPre={{ restic_path }} check
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
@ -32,7 +37,7 @@ ExecStart=/bin/sh -c "{{ database.dump_command }} {{ '| pigz |' if restic_dump_c
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
|
|
||||||
{% if restic_forget %}
|
{% if restic_forget %}
|
||||||
ExecStartPost={{ restic_path }} forget --keep-within {{ restic_forget_keep_within }}
|
ExecStartPost={{ restic_path }} forget {{ restic_forget_args }}
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
{% if restic_prune %}
|
{% if restic_prune %}
|
||||||
|
|
7
templates/restic-failure.service.j2
Normal file
7
templates/restic-failure.service.j2
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Restic backup failure
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
User={{ restic_user }}
|
||||||
|
ExecStartPre=/bin/sh -c 'curl -X POST -H "Content-Type: application/json" -d "{\"text\": \"Restic backup service failed on {{ inventory_hostname }}!\"}" {{ restic_failure_webhook_url }}'
|
Loading…
Reference in a new issue