From 828539dcebfe8b261f7e5c8d54ca1cce52795efa Mon Sep 17 00:00:00 2001 From: Kris Lamoureux Date: Thu, 3 Jun 2021 20:38:56 -0400 Subject: [PATCH] Implement rsnapshot backups on infrastructure --- dev/host_vars/rsnapshot.yml | 42 ++++++++ dev/rsnapshot.yml | 11 ++ roles/.gitignore | 1 + roles/rsnapshot/defaults/main.yml | 3 + roles/rsnapshot/tasks/main.yml | 53 ++++++++++ roles/rsnapshot/templates/rsnapshot.conf.j2 | 110 ++++++++++++++++++++ 6 files changed, 220 insertions(+) create mode 100644 dev/host_vars/rsnapshot.yml create mode 100644 dev/rsnapshot.yml create mode 100644 roles/rsnapshot/defaults/main.yml create mode 100644 roles/rsnapshot/tasks/main.yml create mode 100644 roles/rsnapshot/templates/rsnapshot.conf.j2 diff --git a/dev/host_vars/rsnapshot.yml b/dev/host_vars/rsnapshot.yml new file mode 100644 index 0000000..55a37aa --- /dev/null +++ b/dev/host_vars/rsnapshot.yml @@ -0,0 +1,42 @@ +# base +allow_reboot: false +manage_network: false + +# docker +docker_users: + - vagrant + +# traefik +traefik_version: latest +traefik_dashboard: true +traefik_domain: traefik.vm.krislamo.org +traefik_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin +#traefik_acme_email: realemail@example.com # Let's Encrypt settings +#traefik_production: true + +# nginx +nginx_domain: nginx.vm.krislamo.org +nginx_name: staticsite +nginx_repo_url: https://git.krislamo.org/kris/example-website/ +nginx_auth: admin:$apr1$T1l.BCFz$Jyg8msXYEAUi3LLH39I9d1 # admin:admin +nginx_version: latest + +# rsnapshot +rsnapshot: + - name: webserver + intervals: + hourly: 6 + daily: 4 + cron: + - interval: hourly + minute: "*/2" # every even minute + #minute: 0 + - interval: daily + minute: "1-59/2" # every odd minute + #minute: 0 + #hourly: 0 + backups: + - name: staticsite + source: "/opt/nginx/{{ nginx_name }}/" + - name: logs + source: /var/log/ diff --git a/dev/rsnapshot.yml b/dev/rsnapshot.yml new file mode 100644 index 0000000..b7b65d4 --- /dev/null +++ b/dev/rsnapshot.yml @@ -0,0 +1,11 @@ +- name: Install rsnapshot backup server + hosts: all + become: true + vars_files: + - host_vars/rsnapshot.yml + roles: + - base + - docker + - traefik + - nginx + - rsnapshot diff --git a/roles/.gitignore b/roles/.gitignore index 9ecd153..792c0f3 100644 --- a/roles/.gitignore +++ b/roles/.gitignore @@ -11,6 +11,7 @@ !nextcloud*/ !nginx*/ !prometheus*/ +!rsnapshot*/ !traefik*/ !unifi*/ !wordpress*/ diff --git a/roles/rsnapshot/defaults/main.yml b/roles/rsnapshot/defaults/main.yml new file mode 100644 index 0000000..d31cb77 --- /dev/null +++ b/roles/rsnapshot/defaults/main.yml @@ -0,0 +1,3 @@ +rsnapshot_confdir: /etc/rsnapshot.d +rsnapshot_logdir: /var/log/rsnapshot +rsnapshot_root: /srv/backups/{{ item.name }} diff --git a/roles/rsnapshot/tasks/main.yml b/roles/rsnapshot/tasks/main.yml new file mode 100644 index 0000000..e6658e0 --- /dev/null +++ b/roles/rsnapshot/tasks/main.yml @@ -0,0 +1,53 @@ +# Copyright (C) 2021 Kris Lamoureux +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +- name: Install rsnapshot + apt: + name: rsnapshot + state: present + +- name: Create rsnapshot system directories + file: + path: "{{ item }}" + state: directory + loop: + - "{{ rsnapshot_confdir }}" + - "{{ rsnapshot_logdir }}" + +- name: Create snapshot_root directories + file: + path: "{{ item.root | default(rsnapshot_root) }}" + state: directory + loop: "{{ rsnapshot }}" + +- name: Install rsnapshot configuration + template: + src: rsnapshot.conf.j2 + dest: "{{ rsnapshot_confdir }}/{{ item.name }}.conf" + loop: "{{ rsnapshot }}" + +- name: Install rsnapshot crons + cron: + name: "{{ item.1.interval }} rsnapshot of {{ item.0.name }}" + job: "/usr/bin/rsnapshot -c {{ rsnapshot_confdir }}/{{ item.0.name }}.conf {{ item.1.interval }}" + user: "root" + minute: "{{ item.1.minute | default('*') }}" + hour: "{{ item.1.hourly | default('*') }}" + day: "{{ item.1.day | default('*') }}" + weekday: "{{ item.1.weekday | default('*') }}" + month: "{{ item.1.month | default('*') }}" + cron_file: "rsnapshot-{{ item.0.name }}" + with_subelements: + - "{{ rsnapshot }}" + - cron diff --git a/roles/rsnapshot/templates/rsnapshot.conf.j2 b/roles/rsnapshot/templates/rsnapshot.conf.j2 new file mode 100644 index 0000000..4480f05 --- /dev/null +++ b/roles/rsnapshot/templates/rsnapshot.conf.j2 @@ -0,0 +1,110 @@ +# {{ ansible_managed }} +# rsnapshot.conf - rsnapshot configuration file +# This file requires tabs between elements + +####################### +# CONFIG FILE VERSION # +####################### + +config_version 1.2 + +########################### +# SNAPSHOT ROOT DIRECTORY # +########################### + +# All snapshots will be stored under this root directory. +{% if item.root is defined %} +snapshot_root {{ item.root }} +{% else %} +snapshot_root {{ rsnapshot_root }} +{% endif %} + +# if no_create_root is enabled, rsnapshot will not automatically create the +# snapshot_root directory. this is particularly useful if you are backing +# up to removable media, such as a firewire or usb drive. +{% if item.nocreateroot is defined and not item.nocreateroot %} +no_create_root 0 +{% else %} +no_create_root 1 +{% endif %} + +################################# +# external program dependencies # +################################# + +cmd_cp /bin/cp +cmd_rm /bin/rm +cmd_rsync /usr/bin/rsync +cmd_ssh /usr/bin/ssh +cmd_logger /usr/bin/logger +cmd_du /usr/bin/du +cmd_rsnapshot_diff /usr/bin/rsnapshot-diff + +#################### +# backup intervals # +#################### + +{% for backup in item.intervals %} +retain {{ backup }} {{ item.intervals[backup] }} +{% endfor %} + +############################################ +# global options # +# all are optional, with sensible defaults # +############################################ + +# verbose level, 1 through 5. +# 1 quiet print fatal errors only +# 2 default print errors and warnings only +# 3 verbose show equivalent shell commands being executed +# 4 extra verbose show extra verbose information +# 5 debug mode everything +{% if item.verbose is defined %} +verbose {{ item.verbose }} +{% else %} +verbose 3 +{% endif %} + +# same as "verbose" above, but controls the amount of data sent to the +# logfile, if one is being used. the default is 3. +# if you want the rsync output, you have to set it to 4 +{% if item.loglevel is defined %} +loglevel {{ item.loglevel }} +{% else %} +loglevel 3 +{% endif %} + +# If you enable this, data will be written to the file you specify. The +# amount of data written is controlled by the "loglevel" parameter. +logfile /var/log/rsnapshot/{{ item.name }}.log + +# If enabled, rsnapshot will write a lockfile to prevent two instances +# from running simultaneously (and messing up the snapshot_root). +# If you enable this, make sure the lockfile directory is not world +# writable. Otherwise anyone can prevent the program from running. +lockfile /var/run/rsnapshot-{{ item.name }}.pid + +# When sync_first is enabled, it changes the default behaviour of rsnapshot. +# Normally, when rsnapshot is called with its lowest interval +# (i.e.: "rsnapshot alpha"), it will sync files AND rotate the lowest +# intervals. With sync_first enabled, "rsnapshot sync" handles the file sync, +# and all interval calls simply rotate files. +{% if item.syncfirst is defined and item.syncfirst %} +sync_first 1 +{% else %} +sync_first 0 +{% endif %} + +# Number of rsync re-tries. If you experience any network problems or +# network card issues that tend to cause ssh to fail with errors like +# "Corrupted MAC on input", for example, set this to a non-zero value +# to have the rsync operation re-tried. +rsync_numtries 3 + +############################### +### BACKUP POINTS / SCRIPTS ### +############################### + +{% for backup in item.backups %} +backup {{ backup.source }} {{ backup.name }}/ +{% endfor %}