mirror of
https://github.com/roles-ansible/ansible_role_restic/
synced 2026-09-05 19:27:05 +02:00
Merge branch 'main' into extra-vars-in-backup
Signed-off-by: Sondre Batalden <151748642+nuz014@users.noreply.github.com>
This commit is contained in:
commit
9947e791e8
19 changed files with 79 additions and 42 deletions
4
.github/workflows/ansible-linting-check.yml
vendored
4
.github/workflows/ansible-linting-check.yml
vendored
|
|
@ -11,11 +11,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: 'checkout git repo'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run ansible-lint
|
||||
uses: ansible-actions/ansible-lint-action@v1.0.3
|
||||
uses: ansible-actions/ansible-lint-action@v1.1.0
|
||||
with:
|
||||
target: "./"
|
||||
|
|
|
|||
2
.github/workflows/galaxy.yml
vendored
2
.github/workflows/galaxy.yml
vendored
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: 'Checkout git repo'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
|
|
|||
2
.github/workflows/yamllint-check.yml
vendored
2
.github/workflows/yamllint-check.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: 'checkout git repo'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
|
|
|||
|
|
@ -74,14 +74,17 @@ ansible-galaxy install roles-ansible.restic
|
|||
| `restic_install_path` | `'/usr/local/bin'` | Install location for the restic binary |
|
||||
| `restic_script_dir` | `'/opt/restic'` | Location of the generated backup scripts |
|
||||
| `restic_backup_script_shell` | `sh` | Shell to use for run of backup script |
|
||||
| `restic_pid_dir` | `'/var/run/restic'` | Location of the PID files that lock each backup script to a single running instance |
|
||||
| `restic_log_dir` | `'{{ restic_script_dir }}/log'` | Location of the logs of the backup scripts |
|
||||
| `restic_repos` | `{}` | A dictionary of repositories where snapshots are stored. *(More Info: [Repos](#Repos))* |
|
||||
| `restic_backups` | `{}` (or `[]`) | A list of dictionaries specifying the files and directories to be backed up *(More Infos: [Backups](#Backups))* |
|
||||
| `restic_create_schedule` | `false` | Should we schedule each backup? Either via cronjob or via systemd timer. |
|
||||
| `restic_backup_now` | `false` | Whether or not the backup script should be run immediately |
|
||||
| `restic_schedule_type` | `systemd` | Here you can define if we create a ``cronjob`` or a ``systemd`` timer. If it fails to create a systemd timer, a cronjob will be created. |
|
||||
| `restic_dir_owner` | `'{{ansible_user}}'` | The owner of all created dirs |
|
||||
| `restic_dir_group` | `'{{ansible_user}}'` | The group of all created dirs |
|
||||
| `restic_user` | `'restic'` | System account that owns the restic files and runs scheduled tasks. |
|
||||
| `restic_create_user` | `"{{ restic_user != 'root' }}"` | Controls if the role should create `restic_user`. Useful to skip creation when an existing account or `root` is used. |
|
||||
| `restic_dir_owner` | `'{{ restic_user }}'` | The owner of all created dirs |
|
||||
| `restic_dir_group` | `'{{ restic_user }}'` | The group of all created dirs |
|
||||
| `restic_no_log` | `true` | Set to false to see hidden ansible logs |
|
||||
| `restic_do_not_cleanup_cron ` | `false` | We changed the cron location and clean up the old one. You can skip the cleanup here |
|
||||
| `restic__cache_config` | `false` | Configure custom cache directory |
|
||||
|
|
@ -177,6 +180,7 @@ Available variables:
|
|||
| `prune` | no (`false`) | If `true`, the `restic forget` command in the script has the [`--prune` option](https://restic.readthedocs.io/en/stable/060_forget.html#removing-backup-snapshots) appended. |
|
||||
| `forget_extra_args` | no | Extra arguments to pass to the `restic forget` command. |
|
||||
| `backup_extra_args` | no | Extra arguments to pass to the `restic backup` command (e.g. `--retry-lock 5m`). |
|
||||
| `skip_forget` | no | Skip restic forget, eg if you have a separate cleanup script. |
|
||||
| `scheduled` | no (`false`) | If `restic_create_schedule` is set to `true`, this backup is scheduled and tries to create a systemd timer unit. If it fails, it is creating a cronjob. |
|
||||
| `schedule_oncalendar` | ``'*-*-* 02:00:00'`` | The time for the systemd timer. Please notice the randomDelaySec option. By Default the backup is done every night at 2 am (+0-4h). But only if scheduled is true. |
|
||||
| `schedule_minute` | no (`0`) | Minute when the job is run. ( 0-59, *, */2, etc ) |
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ restic_download_path: '/opt/restic'
|
|||
restic_install_path: '/usr/local/bin'
|
||||
restic_script_dir: '/opt/restic'
|
||||
restic_backup_script_shell: sh
|
||||
restic_pid_dir: '/var/run/restic'
|
||||
restic_log_dir: '{{ restic_script_dir }}/log'
|
||||
restic_repos: {}
|
||||
restic_backups: []
|
||||
|
|
@ -15,6 +16,7 @@ restic_backup_now: false
|
|||
restic_no_log: true
|
||||
|
||||
restic_user: restic
|
||||
restic_create_user: "{{ restic_user != 'root' }}"
|
||||
restic_dir_owner: '{{ restic_user }}'
|
||||
restic_dir_group: '{{ restic_user }}'
|
||||
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@
|
|||
- restic_create_schedule
|
||||
- item.name is defined
|
||||
- item.scheduled | default(false)
|
||||
- ansible_service_mgr == 'systemd'
|
||||
- ansible_facts['service_mgr'] == 'systemd'
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
success_msg: "Congratulations. You are using ansible version {{ ansible_version.full }}"
|
||||
delegate_to: localhost
|
||||
when:
|
||||
- ansible_service_mgr != 'systemd' or restic_force_cron | default(false) or restic_schedule_type == "cronjob"
|
||||
- ansible_facts['service_mgr'] != 'systemd' or restic_force_cron | default(false) or restic_schedule_type == "cronjob"
|
||||
register: old_af
|
||||
failed_when: false
|
||||
ignore_errors: true
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
- name: Message
|
||||
ansible.builtin.fail:
|
||||
msg: 'Your {{ ansible_system }} is not yet supported'
|
||||
msg: 'Your {{ ansible_facts["system"] }} is not yet supported'
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
- name: Message
|
||||
ansible.builtin.debug:
|
||||
msg: 'Your {{ ansible_system }} is not supported'
|
||||
msg: 'Your {{ ansible_facts["system"] }} is not supported'
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
- name: Ensure restic binary has cap_dac_read_search capability
|
||||
community.general.capabilities:
|
||||
path: "/opt/restic/bin/restic-{{ restic_version }}"
|
||||
path: "{{ restic_download_path }}/bin/restic-{{ restic_version }}"
|
||||
capability: cap_dac_read_search=+ep
|
||||
state: present
|
||||
|
||||
|
|
|
|||
|
|
@ -24,18 +24,18 @@
|
|||
loop_control:
|
||||
loop_var: loop_distribution
|
||||
vars:
|
||||
distribution: '{{ ansible_distribution }}'
|
||||
distribution_version: '{{ ansible_distribution_version }}'
|
||||
distribution_major_version: '{{ ansible_distribution_major_version }}'
|
||||
distribution: '{{ ansible_facts["distribution"] }}'
|
||||
distribution_version: '{{ ansible_facts["distribution_version"] }}'
|
||||
distribution_major_version: '{{ ansible_facts["distribution_major_version"] }}'
|
||||
|
||||
- name: Schedule restic backup
|
||||
ansible.builtin.include_tasks: 'schedule.yml'
|
||||
loop_control:
|
||||
loop_var: loop_distribution
|
||||
vars:
|
||||
distribution: '{{ ansible_distribution }}'
|
||||
distribution_version: '{{ ansible_distribution_version }}'
|
||||
distribution_major_version: '{{ ansible_distribution_major_version }}'
|
||||
distribution: '{{ ansible_facts["distribution"] }}'
|
||||
distribution_version: '{{ ansible_facts["distribution_version"] }}'
|
||||
distribution_major_version: '{{ ansible_facts["distribution_major_version"] }}'
|
||||
|
||||
- name: Set user permissions on folders
|
||||
ansible.builtin.include_tasks: 'permissions.yml'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
---
|
||||
- name: Ensure pid folder exists and is writeable
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: "{{ restic_pid_dir }}"
|
||||
state: directory
|
||||
owner: "{{ restic_user }}"
|
||||
group: "{{ restic_user }}"
|
||||
mode: "0755"
|
||||
|
||||
- name: Ensure log folder exists and is writeable
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
|
|
@ -11,6 +20,7 @@
|
|||
become: true
|
||||
ansible.builtin.file:
|
||||
path: "{{ restic__cache_dir }}"
|
||||
state: directory
|
||||
owner: "{{ restic_user }}"
|
||||
group: "{{ restic_user }}"
|
||||
mode: "0750"
|
||||
|
|
@ -24,5 +34,6 @@
|
|||
group: "{{ restic_user }}"
|
||||
recurse: true
|
||||
with_items:
|
||||
- "{{ restic_pid_dir }}"
|
||||
- "{{ restic_log_dir }}"
|
||||
- "{{ restic__cache_dir }}"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: (SCHEDULE) (SYSTEMD) create systemd timer
|
||||
when:
|
||||
- ansible_service_mgr == 'systemd'
|
||||
- ansible_facts['service_mgr'] == 'systemd'
|
||||
- restic_schedule_type == "systemd"
|
||||
- restic_create_schedule | bool
|
||||
block:
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@
|
|||
- name: (SCHEDULE) create restic systemd timer
|
||||
ansible.builtin.include_tasks: restic_create_systemd.yml
|
||||
when:
|
||||
- ansible_service_mgr == 'systemd'
|
||||
- ansible_facts['service_mgr'] == 'systemd'
|
||||
- restic_schedule_type == "systemd"
|
||||
- restic_create_schedule | bool
|
||||
|
||||
- name: (SCHEDULE) delete systemd timers if available
|
||||
ansible.builtin.include_tasks: restic_delete_systemd.yml
|
||||
when:
|
||||
- ansible_service_mgr == 'systemd'
|
||||
- ansible_facts['service_mgr'] == 'systemd'
|
||||
- restic_schedule_type == "cronjob" or restic_force_cron | default(false)
|
||||
- restic_create_schedule | bool
|
||||
|
||||
|
|
@ -21,13 +21,13 @@
|
|||
ansible.builtin.include_tasks: restic_create_cron.yml
|
||||
when:
|
||||
- restic_create_schedule | bool
|
||||
- ansible_service_mgr != 'systemd' or restic_force_cron | default(false) or restic_schedule_type == "cronjob"
|
||||
- ansible_facts['service_mgr'] != 'systemd' or restic_force_cron | default(false) or restic_schedule_type == "cronjob"
|
||||
|
||||
- name: (SCHEDULE) remove restic cronjobs
|
||||
ansible.builtin.include_tasks: restic_delete_cron.yml
|
||||
when:
|
||||
- restic_create_schedule | bool
|
||||
- ansible_service_mgr == 'systemd'
|
||||
- ansible_facts['service_mgr'] == 'systemd'
|
||||
- not restic_force_cron | default(false)
|
||||
- restic_schedule_type != "cronjob"
|
||||
- not restic_do_not_cleanup_cron | bool
|
||||
|
|
|
|||
|
|
@ -5,3 +5,6 @@
|
|||
name: "{{ restic_user }}"
|
||||
shell: "/sbin/nologin"
|
||||
system: true
|
||||
when:
|
||||
- restic_create_user | bool
|
||||
- restic_user != 'root'
|
||||
|
|
|
|||
|
|
@ -42,3 +42,6 @@ BACKUP_NAME={{ item.name }}
|
|||
{% if item.src is defined %}
|
||||
BACKUP_SOURCE={{ item.src }}
|
||||
{% endif %}
|
||||
{% if restic__cache_config | bool -%}
|
||||
export RESTIC_CACHE_DIR={{ restic__cache_dir }}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -3,20 +3,28 @@
|
|||
# Backup script for {{ item.src|default('stdin') }}
|
||||
# Use this file to create a Backup and prune existing data with one execution.
|
||||
|
||||
pid="/var/run/restic_backup_{{ item.name | regex_replace('\'', '\'\\\'\'') }}.pid"
|
||||
pid="{{ restic_pid_dir }}/backup_{{ item.name | regex_replace('\'', '\'\\\'\'') }}.pid"
|
||||
trap "rm -f $pid" SIGSEGV
|
||||
trap "rm -f $pid" SIGINT
|
||||
|
||||
if [ -e $pid ]; then
|
||||
echo "Another version of this restic backup script is already running!"
|
||||
# Read the PID from the file
|
||||
OLD_PID=$(cat "$pid")
|
||||
|
||||
# Check if the process is actually running
|
||||
if ps -p "$OLD_PID" > /dev/null 2>&1; then
|
||||
echo "Another version of this restic backup script is already running! (PID: $OLD_PID)"
|
||||
{% if item.mail_on_error is defined and item.mail_on_error == true %}
|
||||
mail -s "starting restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< "Another restic backup process is already running. We canceled starting a new restic backup script running at {{ ansible_hostname }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
mail -s "starting restic backup failed on {{ ansible_facts['hostname'] }}" {{ item.mail_address }} <<< "Another restic backup process is already running. We canceled starting a new restic backup script running at {{ ansible_facts['hostname'] }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
{%- if item.src is defined -%}
|
||||
{{ ' ' }}We tried to backup '{{ item.src }}'.
|
||||
{%- endif -%}
|
||||
{{ ' ' }}Please repair the restic-{{ item.name | replace(' ', '') }} job."
|
||||
{% endif %}
|
||||
exit # pid file exists, another instance is running, so now we politely exit
|
||||
exit 1
|
||||
else
|
||||
echo "Warning: Stale PID file found. (process $OLD_PID is not running). Proceeding with execution" >&2
|
||||
fi
|
||||
else
|
||||
echo $$ > $pid # pid file doesn't exit, create one and go on
|
||||
fi
|
||||
|
|
@ -43,7 +51,7 @@ fi
|
|||
{% endif %}
|
||||
|
||||
{% if restic__cache_config | bool -%}
|
||||
export XDG_CACHE_HOME={{ restic__cache_dir }}
|
||||
export RESTIC_CACHE_DIR={{ restic__cache_dir }}
|
||||
{% endif %}
|
||||
|
||||
{% if restic__limit_cpu_usage | bool -%}
|
||||
|
|
@ -245,7 +253,7 @@ then
|
|||
else
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" {{ pre_backup_cmd_result_log }}
|
||||
{% if item.mail_on_error is defined and item.mail_on_error == true %}
|
||||
mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_hostname }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
mail -s "restic backup failed on {{ ansible_facts['hostname'] }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_facts['hostname'] }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
{%- if item.src is defined -%}
|
||||
{{ ' ' }}We tried to backup '{{ item.src }}'.
|
||||
{%- endif -%}
|
||||
|
|
@ -283,7 +291,8 @@ fi
|
|||
} \
|
||||
{% endif %} {{ backup_output_log }}
|
||||
|
||||
case $? in
|
||||
BACKUP_EXIT_CODE=$?
|
||||
case $BACKUP_EXIT_CODE in
|
||||
0)
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') OK" {{ backup_result_log }}
|
||||
;;
|
||||
|
|
@ -293,7 +302,7 @@ case $? in
|
|||
*)
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" {{ backup_result_log }}
|
||||
{% if item.mail_on_error is defined and item.mail_on_error == true %}
|
||||
mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_hostname }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
mail -s "restic backup failed on {{ ansible_facts['hostname'] }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_facts['hostname'] }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
{%- if item.src is defined -%}
|
||||
{{ ' ' }}We tried to backup '{{ item.src }}'.
|
||||
{%- endif -%}
|
||||
|
|
@ -314,12 +323,15 @@ if [[ $? -eq 0 ]]
|
|||
then
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') OK" {{ forget_result_log }}
|
||||
{% if item.monitoring_call is defined %}
|
||||
{{ item.monitoring_call }}
|
||||
# Only call monitoring if backup also succeeded (exit code 0 or 3)
|
||||
if [[ $BACKUP_EXIT_CODE -eq 0 ]]; then
|
||||
{{ item.monitoring_call }}
|
||||
fi
|
||||
{% endif %}
|
||||
else
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" {{ forget_result_log }}
|
||||
{% if item.mail_on_error is defined and item.mail_on_error == true %}
|
||||
mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_hostname }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
mail -s "restic backup failed on {{ ansible_facts['hostname'] }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_facts['hostname'] }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
{%- if item.src is defined -%}
|
||||
{{ ' ' }}We tried to backup '{{ item.src }}'.
|
||||
{%- endif -%}
|
||||
|
|
@ -334,15 +346,17 @@ fi
|
|||
#}
|
||||
{% if item.past_backup_cmd is defined %}
|
||||
{{ item.past_backup_cmd }} {{ post_backup_cmd_output_log }}
|
||||
{% if item.post_backup_cmd is defined %}
|
||||
{% elif item.post_backup_cmd is defined %}
|
||||
{{ item.post_backup_cmd }} {{ post_backup_cmd_output_log }}
|
||||
{% endif %}
|
||||
{% if item.past_backup_cmd is defined or item.post_backup_cmd is defined %}
|
||||
if [[ $? -eq 0 ]]
|
||||
then
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') OK" {{ post_backup_cmd_result_log }}
|
||||
else
|
||||
echo "$(date -u '+%Y-%m-%d %H:%M:%S') ERROR" {{ post_backup_cmd_result_log }}
|
||||
{% if item.mail_on_error is defined and item.mail_on_error == true %}
|
||||
mail -s "restic backup failed on {{ ansible_hostname }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_hostname }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
mail -s "restic backup failed on {{ ansible_facts['hostname'] }}" {{ item.mail_address }} <<< "Something went wrong while running restic backup script running at {{ ansible_facts['hostname'] }} at $(date -u '+%Y-%m-%d %H:%M:%S').
|
||||
{%- if item.src is defined -%}
|
||||
{{ ' ' }}We tried to backup '{{ item.src }}'.
|
||||
{%- endif -%}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ restic_create_paths:
|
|||
restic_bin_path: '{{ restic_download_path }}/bin/restic-{{ restic_version }}'
|
||||
|
||||
restic_url_r: 'https://github.com/restic/restic/releases/download/'
|
||||
arch: '{{ ansible_architecture }}'
|
||||
arch: '{{ ansible_facts["architecture"] }}'
|
||||
restic_platform: '{{ _platform_map[arch] | default(arch) }}'
|
||||
restic_system: '{{ ansible_system | lower }}'
|
||||
restic_system: '{{ ansible_facts["system"] | lower }}'
|
||||
restic_url_v: 'v{{ restic_version }}/restic_{{ restic_version }}_'
|
||||
restic_file: '{{ restic_system }}_{{ restic_platform }}.bz2'
|
||||
restic_url_default: '{{ restic_url_r }}{{ restic_url_v }}{{ restic_file }}'
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
---
|
||||
restic_os_variables:
|
||||
files:
|
||||
- '{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml'
|
||||
- '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml'
|
||||
- '{{ ansible_distribution }}.yml'
|
||||
- '{{ ansible_os_family }}.yml'
|
||||
- '{{ ansible_system }}.yml'
|
||||
- '{{ ansible_facts["distribution"] }}-{{ ansible_facts["distribution_version"] }}.yml'
|
||||
- '{{ ansible_facts["distribution"] }}-{{ ansible_facts["distribution_major_version"] }}.yml'
|
||||
- '{{ ansible_facts["distribution"] }}.yml'
|
||||
- '{{ ansible_facts["os_family"] }}.yml'
|
||||
- '{{ ansible_facts["system"] }}.yml'
|
||||
- 'defaults.yml'
|
||||
paths:
|
||||
- 'vars'
|
||||
|
||||
playbook_version_number: 30 # should be int
|
||||
playbook_version_number: 31 # should be int
|
||||
playbook_version_path: 'do1jlr.restic.version'
|
||||
|
|
|
|||
Loading…
Reference in a new issue