Skip to content
Snippets Groups Projects
Commit 377933b6 authored by nimrod's avatar nimrod
Browse files

- Added pre-commit hook to lint backup shell script.

- Backup is now done by the OS user nobody and MySQL user backup.
- Backup script now outputs start, finish and error to stdout.
- Removed dependency on ca-store Ansible role.
- The MySQL user is added to the ssl group only if the group exists.
- Backup provisioninig is now optional depending on if the mysql_backup_password
  variables is defined.
- Moved most configuration to templates inside conf.d.
- Remote admin account is now optional depending on if the mysql_admin_password
  is defined.
- The mysql-server packges is reconfigured to reset root password if it's
  needed.
parent df47d29b
No related branches found
No related tags found
No related merge requests found
...@@ -10,3 +10,8 @@ ...@@ -10,3 +10,8 @@
sha: 94b506c144d4e22ebc1deef637a818db13bcaca5 sha: 94b506c144d4e22ebc1deef637a818db13bcaca5
hooks: hooks:
- id: ansible-pre-commit - id: ansible-pre-commit
- repo: https://www.shore.co.il/git/shell-pre-commit/
sha: 604fe77b53d3514d5ad0f66764c7783850bb6e98
hooks:
- id: shell-lint
files: files/backup.sh
...@@ -52,3 +52,9 @@ Nimrod Adar, `contact me <nimrod@shore.co.il>`_ or visit my `website ...@@ -52,3 +52,9 @@ Nimrod Adar, `contact me <nimrod@shore.co.il>`_ or visit my `website
<https://www.shore.co.il/>`_. Patches are welcome via `git send-email <https://www.shore.co.il/>`_. Patches are welcome via `git send-email
<http://git-scm.com/book/en/v2/Git-Commands-Email>`_. The repository is located <http://git-scm.com/book/en/v2/Git-Commands-Email>`_. The repository is located
at: https://www.shore.co.il/git/. at: https://www.shore.co.il/git/.
TODO
----
- Backup script.
- Testing.
...@@ -2,3 +2,7 @@ ...@@ -2,3 +2,7 @@
# defaults file for ansible-role-mysql # defaults file for ansible-role-mysql
mysql_admin_password: mysql_admin_password:
mysql_tls_key: /etc/ssl/private/ssl-cert-snakeoil.key
mysql_tls_cert: /etc/ssl/certs/ssl-cert-snakeoil.pem
mysql_mail_alias: root
mysql_serverid: '{{ ansible_default_ipv4["address"]|ipaddr("int") }}'
files/backup.sh 100644 → 100755
#!/bin/sh -e #!/bin/sh
# Back up all databases, each to a seperate file. set -eu
backup() { echo "MySQL backup: Starting at $(date -u)."
mysqldump --defaults-file=/etc/mysql/debian.cnf \
--single-transaction \
--force \
--result-file=/var/backups/mysql_$1.sql $1
}
# TODO: Find a way to remove table formatting from this command. # Grep filter to remove heading and internal MySQL databases.
#alias show='mysqlshow --defaults-file=/etc/mysql/debian.cnf' filter='Database\|information_schema\|performance_schema\|mysql'
alias show="mysql --defaults-file=/etc/mysql/debian.cnf -e 'show databases;'"
# The reason for dropping the first 4 lines is that the first line is the if databases="$(mysql --defaults-file=/etc/mysql/mysqldump.cnf \
# heading and 3 following lines are databases internal to MySQL and thus their --execute 'show databases;' | grep -vx $filter)"
# backup is not needed. then
for database in $(show | tail -n+5) mysqldump --defaults-file=/etc/mysql/mysqldump.cnf
do --databases $databases || \
backup $database echo "MySQL backup: Failed to backup."
done else
echo "MySQL backup: No databases to backup."
fi
echo "MySQL backup: Finished at $(date -u)."
...@@ -14,7 +14,4 @@ galaxy_info: ...@@ -14,7 +14,4 @@ galaxy_info:
versions: versions:
- precise - precise
- trusty - trusty
dependencies: dependencies: []
- src: https://www.shore.co.il/git/ansible-role-ca-store
scm: git
name: ca-store
...@@ -13,10 +13,10 @@ vagrant: ...@@ -13,10 +13,10 @@ vagrant:
- name: virtualbox - name: virtualbox
type: virtualbox type: virtualbox
platforms: platforms:
- name: openbsd - name: debian
box: kaorimatz/openbsd-5.9-amd64 box: debian/jessie64
instances: instances:
- name: ansible-role-example - name: ansible-role-mysql
options: options:
append_platform_to_hostname: yes append_platform_to_hostname: yes
raw_config_args: raw_config_args:
......
---
- name: APT install cron
apt:
name: cron
state: present
update_cache: yes
cache_valid_time: 3600
- name: Add backup account
mysql_user:
login_password: '{{ mysql_root_password|default(omit) }}'
name: backup
host: '%'
password: '{{ mysql_backup_password }}'
priv: '*.*:SELECT,FILE,RELOAD,REPLICATION CLIENT'
state: present
- name: Create backup directory
file:
path: /var/backups/mysql
owner: nobody
group: nogroup
mode: 0o0700
state: directory
- name: Copy backup configuration
template:
src: mysqldump.cnf
dest: /etc/mysql/mysqldump.cnf
owner: nobody
group: nogroup
mode: 0o0400
- name: Copy backup job
copy:
src: backup.sh
dest: /usr/local/sbin/mysql-backup
owner: root
group: root
mode: 0o0755
- name: Add daily backup job
cron:
user: nobody
name: MySQL backup
job: '/usr/local/sbin/mysql-backup | logger'
special_time: daily
state: present
...@@ -2,91 +2,87 @@ ...@@ -2,91 +2,87 @@
# tasks file for ansible-role-mysql # tasks file for ansible-role-mysql
- assert: - assert:
that: that:
- ansible_os_family == 'OpenBSD' - ansible_os_family == 'Debian'
- ansible_distribution_release == '5.9' - ansible_distribution_release in ['wheezy', 'jessie', 'stretch', 'precise', 'trusty', 'xenial']
- name: apt install - name: Get groups
getent:
database: group
- name: Preseed root password
when: mysql_root_password is defined
with_items:
- root_password
- root_password_again
debconf:
name: '{{ mysql_server_package }}'
question: 'mysql-server/{{ item }}'
vtype: password
value: '{{ mysql_root_password }}'
changed_when: False # Can't verify previous password therefore there's always
# a change, explicitly disable that.
- name: APT install
with_items:
- mysql-server
- mysql-client
- python-mysqldb
apt: apt:
name: '{{ item }}' name: '{{ item }}'
state: present state: present
update_cache: yes update_cache: yes
cache_valid_time: 3600 cache_valid_time: 3600
with_items:
- mysql-server - name: Reconfigure package in case root password was changed
- mysql-client changed_when: False
- python-mysqldb command: 'dpkg-reconfigure --frontend noninteractive {{ mysql_server_package }}'
- cron
- name: Allow MySQL access to the TLS cert and key - name: Allow MySQL access to the TLS cert and key
when: "'ssl-cert' in getent_group"
user: user:
append: yes append: yes
groups: ssl-cert groups: ssl-cert
name: mysql name: mysql
notify: notify:
- Restart MySQL - Restart MySQL
- name: Configure
with_dict:
'ssl-ca': /etc/ssl/certs/ca-certificates.crt
'ssl-cert': '{{ tls_cert_path }}'
'ssl-key': '{{ tls_key_path }}'
'bind-address': '0.0.0.0'
ini_file:
dest: /etc/mysql/my.cnf
owner: root
group: root
mode: '0644'
section: mysqld
option: '{{ item.key }}'
value: '{{ item.value }}'
notify:
- Restart MySQL
- name: Log to syslog - name: Alias mail
when: mysql_mail_alias is defined
lineinfile: lineinfile:
dest: /etc/mysql/my.cnf dest: /etc/aliases
owner: root create: True
group: root line: 'mysql: {{ mysql_mail_alias }}'
mode: '0644' regexp: 'mysql:'
line: 'syslog' state: present
insertafter: '[mysqld_safe]'
notify:
- Restart MySQL
- name: Add admin account - name: Add admin account
when: mysql_admin_password is defined
mysql_user: mysql_user:
name: admin name: admin
host: '%' host: '%'
password: '{{ mysql_admin_password }}' password: '{{ mysql_admin_password }}'
priv: '*.*:ALL,GRANT' priv: '*.*:ALL,GRANT,REQUIRESSL'
login_password: '{{ mysql_root_password|default(omit) }}'
state: present state: present
- name: Require SSL for admin account - name: Copy configuration templates
mysql_user: with_fileglob:
name: admin - templates/mysql/conf.d/*.cnf
host: '%' - '{{ playbook_dir }}/templates/mysql/conf.d/*.cnf'
append_privs: True template:
priv: '*.*:REQUIRESSL' src: '{{ item }}'
state: present dest: /etc/mysql/conf.d
owner: root
- name: Allow MySQL in firewall group: root
ufw: mode: 0o0644
rule: allow notify:
port: 3306 - Restart MySQL
proto: tcp
- name: Add daily backup job
copy:
src: backup.sh
dest: /etc/cron.daily/mysql
owner: root
group: root
mode: '0755'
- meta: flush_handlers - meta: flush_handlers
- name: Wait for service to come online - name: Wait for service to come online
wait_for: wait_for:
host: '{{ ansible_default_ipv4["address"] }}'
port: 3306 port: 3306
state: started
- include: backup.yml
when: mysql_backup_password is defined
[mysqld]
bind-address = 0.0.0.0
[mysqld]
binlog-ignore-db = information_schema, performance_schema, mysql
replicate-ignore-db = information_schema, performance_schema, mysql
[mysqld]
server-id = {{ mysql_serverid }}
[mysqld]
ssl-ca = /etc/ssl/certs/ca-certificates.crt
{% if mysql_tls_cert is defined and mysql_tls_key is defined %}
ssl-cert = {{ mysql_tls_cert }}
ssl-key = {{ mysql_tls_key }}
{% endif %}
[mysqld_safe]
syslog
[mysqldump]
single-transaction
master-data = 2
force
result-file = /var/backups/mysql/mysql.sql
dump-date
tz-utc
[client]
host = localhost
user = backup
password = {{ mysql_backup_password }}
socket = /var/run/mysqld/mysqld.sock
--- ---
- hosts: all - hosts: all
gather_facts: false vars:
mysql_root_password: qwer12345
mysql_backup_password: backup
mysql_admin_password: admin
roles: roles:
- role: ansible-role-example - role: ansible-role-mysql
--- ---
# vars file for ansible-role-mysql # vars file for ansible-role-mysql
mysql_version:
precise: 5.5
trusty: 5.5
xenial: 5.7
wheezy: 5.5
jessie: 5.5
stretch: 5.6
mysql_server_package: 'mysql-server-{{ mysql_version[ansible_distribution_release] }}'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment