From a8eedf8ed3a57c71c869770c99021a39a9f20447 Mon Sep 17 00:00:00 2001
From: Robin Sonnabend <robin@fsmpi.rwth-aachen.de>
Date: Mon, 9 Mar 2020 19:14:26 +0100
Subject: [PATCH] Make backups of mysql databases with rsnapshot

---
 mysql/defaults/main.yml        |  3 ++
 mysql/files/crontab            |  4 ++
 mysql/files/rsnapshot.conf     | 18 ++++++++
 mysql/tasks/main.yml           | 78 +++++++++++++++++++++++-----------
 mysql/templates/my.cnf         |  4 ++
 mysql/templates/mysqlbackup.sh |  6 +++
 6 files changed, 89 insertions(+), 24 deletions(-)
 create mode 100644 mysql/files/crontab
 create mode 100644 mysql/files/rsnapshot.conf
 create mode 100644 mysql/templates/my.cnf
 create mode 100644 mysql/templates/mysqlbackup.sh

diff --git a/mysql/defaults/main.yml b/mysql/defaults/main.yml
index 9622f41..1894025 100644
--- a/mysql/defaults/main.yml
+++ b/mysql/defaults/main.yml
@@ -2,3 +2,6 @@
 
 # yamllint disable-line rule:line-length
 mysql_root_password: "{{ lookup('passwordstore', 'db/{{ ansible_hostname }}-mysql create=true length=20') }}"
+
+mysql_backup_user: "backup"
+mysql_backup_password: "{{ lookup('passwordstore', 'db/{{ ansible_hostname }}-mysql-backup create=true length=20') }}"
diff --git a/mysql/files/crontab b/mysql/files/crontab
new file mode 100644
index 0000000..901e206
--- /dev/null
+++ b/mysql/files/crontab
@@ -0,0 +1,4 @@
+3 * * * * root /usr/bin/rsnapshot -c /etc/rsnapshot.d/mysql.conf hourly
+55 23 * * * root /usr/bin/rsnapshot -c /etc/rsnapshot.d/mysql.conf daily
+45 23 * * 6 root /usr/bin/rsnapshot -c /etc/rsnapshot.d/mysql.conf weekly
+35 23 3 * * root /usr/bin/rsnapshot -c /etc/rsnapshot.d/mysql.conf monthly
diff --git a/mysql/files/rsnapshot.conf b/mysql/files/rsnapshot.conf
new file mode 100644
index 0000000..bba263a
--- /dev/null
+++ b/mysql/files/rsnapshot.conf
@@ -0,0 +1,18 @@
+config_version	1.2
+snapshot_root	/var/backups/
+cmd_cp	/bin/cp
+cmd_rm	/bin/rm
+cmd_rsync	/usr/bin/rsync
+cmd_logger	/usr/bin/logger
+cmd_du	/usr/bin/du
+
+retain	hourly	6
+retain	daily	7
+retain	weekly	4
+retain	monthly	6
+
+verbose	2
+loglevel	3
+lockfile	/var/run/rsnapshot-mysql.pid
+
+backup_script	/usr/local/bin/mysqlbackup.sh	mysql/
diff --git a/mysql/tasks/main.yml b/mysql/tasks/main.yml
index df998bb..820e52e 100644
--- a/mysql/tasks/main.yml
+++ b/mysql/tasks/main.yml
@@ -1,26 +1,12 @@
 ---
 # file: roles/mysql/tasks/main.yml
 
-- name: ensure mysql packages are installed for jessie
-  apt:
-    name:
-      - mysql-server
-      - python-mysqldb
-    state: present
-  when:
-    - debian_version == "jessie"
-  tags:
-    - packages
-    - mysql
-
-- name: ensure mysql packages are installed for stretch
+- name: ensure mysql packages are installed
   apt:
     name:
       - mariadb-server
       - python-mysqldb
     state: present
-  when:
-    - debian_version != "jessie"
   tags:
     - packages
     - mysql
@@ -30,9 +16,6 @@
     name: mysql
     state: started
     enabled: true
-  tags:
-    - service
-    - mysql
 
 - name: ensure the mysql root user exists and has the correct password
   mysql_user:
@@ -43,9 +26,6 @@
   register: mysql_root_creation_result
   no_log: true
   ignore_errors: true
-  tags:
-    - mysql
-    - config
 
 - name: initialize the mysql root user
   mysql_user:
@@ -53,6 +33,56 @@
     password: "{{ mysql_root_password }}"
   no_log: true
   when: mysql_root_creation_result is failed
-  tags:
-    - mysql
-    - config
+
+- name: ensure a read-only mysql user for backups exists
+  mysql_user:
+    name: "{{ mysql_backup_user }}"
+    password: "{{ mysql_backup_password }}"
+    login_user: root
+    login_password: "{{ mysql_root_password }}"
+    priv: "*.*:SELECT,LOCK TABLES"
+
+- name: ensure the backup procedure can access the backup password
+  template:
+    src: my.cnf
+    dest: "/root/.mysql-{{mysql_backup_user}}.cnf"
+    owner: root
+    group: root
+    mode: '0600'
+
+- name: deploy the mysql backup script
+  template:
+    src: mysqlbackup.sh
+    dest: /usr/local/bin/
+    owner: root
+    group: root
+    mode: '0755'
+
+- name: ensure we have rsnapshot
+  apt:
+    name: rsnapshot
+    state: present
+
+- name: ensure we have a directory for rsnapshot configuration
+  file:
+    path: /etc/rsnapshot.d
+    state: directory
+    owner: root
+    group: root
+    mode: '0755'
+
+- name: ensure we backup all the mysql databases with rsnapshot
+  copy:
+    src: rsnapshot.conf
+    dest: /etc/rsnapshot.d/mysql.conf
+    owner: root
+    group: root
+    mode: '0644'
+
+- name: make rsnapshot run regularly
+  copy:
+    src: crontab
+    dest: /etc/cron.d/mysql-snapshot
+    owner: root
+    group: root
+    mode: '0644'
diff --git a/mysql/templates/my.cnf b/mysql/templates/my.cnf
new file mode 100644
index 0000000..697c3c1
--- /dev/null
+++ b/mysql/templates/my.cnf
@@ -0,0 +1,4 @@
+[client]
+user = {{ mysql_backup_user }}
+password = {{mysql_backup_password }}
+host = localhost
diff --git a/mysql/templates/mysqlbackup.sh b/mysql/templates/mysqlbackup.sh
new file mode 100644
index 0000000..a422dc3
--- /dev/null
+++ b/mysql/templates/mysqlbackup.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+umask 0077
+/usr/bin/mysqldump --defaults-extra-file=/root/.mysql-{{mysql_backup_user}}.cnf --all-databases | gzip -c -- > mysqldump_all_databases.sql.gz
+
+/bin/chmod 600 mysqldump_all_databases.sql.gz
-- 
GitLab