├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── tasks └── main.yml ├── templates ├── .my.cnf.j2 ├── my.cnf.Debian.j2 ├── my.cnf.RedHat.j2 └── mysql.cnf.j2 └── vars ├── Debian.yml ├── RedHat.yml └── main.yml /README.md: -------------------------------------------------------------------------------- 1 | MySQL Server 2 | ============ 3 | 4 | This roles helps to install MySQL Server across RHEL and Ubuntu variants. 5 | Apart from installing the MySQL Server, it applies basic hardening, like 6 | securing the root account with password, and removing test databases. The role 7 | can also be used to add databases to the MySQL server and create users in the 8 | database. It also supports configuring the databases for replication--both 9 | master and slave can be configured via this role. 10 | 11 | Requirements 12 | ------------ 13 | 14 | This role requires Ansible 1.4 or higher, and platform requirements are listed 15 | in the metadata file. 16 | 17 | Role Variables 18 | -------------- 19 | 20 | The variables that can be passed to this role and a brief description about 21 | them are as follows: 22 | 23 | mysql_port: 3306 # The port for mysql server to listen 24 | mysql_bind_address: "0.0.0.0" # The bind address for mysql server 25 | mysql_root_db_pass: foobar # The root DB password 26 | 27 | # A list that has all the databases to be 28 | # created and their replication status: 29 | mysql_db: 30 | - name: foo 31 | replicate: yes 32 | - name: bar 33 | replicate: no 34 | 35 | # A list of the mysql users to be created 36 | # and their password and privileges: 37 | mysql_users: 38 | - name: benz 39 | pass: foobar 40 | priv: "*.*:ALL" 41 | 42 | # If the database is replicated the users 43 | # to be used for replication: 44 | mysql_repl_user: 45 | - name: repl 46 | pass: foobar 47 | 48 | # The role of this server in replication: 49 | mysql_repl_role: master 50 | 51 | # A unique id for the mysql server (used in replication): 52 | mysql_db_id: 7 53 | 54 | Examples 55 | -------- 56 | 57 | 1) Install MySQL Server and set the root password, but don't create any 58 | database or users. 59 | 60 | - hosts: all 61 | roles: 62 | - {role: mysql, mysql_root_db_pass: foobar, mysql_db: none, mysql_users: none } 63 | 64 | 2) Install MySQL Server and create 2 databases and 2 users. 65 | 66 | - hosts: all 67 | roles: 68 | - {role: mysql, mysql_db: [{name: benz}, 69 | {name: benz2}], 70 | mysql_users: [{name: ben3, pass: foobar, priv: "*.*:ALL"}, 71 | {name: ben2, pass: foo}] } 72 | 73 | Note: If users are specified and password/privileges are not specified, then 74 | default values are set. 75 | 76 | 3) Install MySQL Server and create 2 databases and 2 users and configure the 77 | database as replication master with one database configured for replication. 78 | 79 | - hosts: all 80 | roles: 81 | - {role: mysql, mysql_db: [{name: benz, replicate: yes }, 82 | { name: benz2, replicate: no}], 83 | mysql_users: [{name: ben3, pass: foobar, priv: "*.*:ALL"}, 84 | {name: ben2, pass: foo}], 85 | mysql_repl_user: [{name: repl, pass: foobar}] } 86 | 87 | 4) A fully installed/configured MySQL Server with master and slave 88 | replication. 89 | 90 | - hosts: master 91 | roles: 92 | - {role: mysql, mysql_db: [{name: benz}, {name: benz2}], 93 | mysql_users: [{name: ben3, pass: foobar, priv: "*.*:ALL"}, 94 | {name: ben2, pass: foo}], 95 | mysql_db_id: 8 } 96 | 97 | - hosts: slave 98 | roles: 99 | - {role: mysql, mysql_db: none, mysql_users: none, 100 | mysql_repl_role: slave, mysql_repl_master: vm2, 101 | mysql_db_id: 9, mysql_repl_user: [{name: repl, pass: foobar}] } 102 | 103 | Note: When configuring the full replication please make sure the master is 104 | configured via this role and the master is available in inventory and facts 105 | have been gathered for master. The replication tasks assume the database is 106 | new and has no data. 107 | 108 | 109 | Dependencies 110 | ------------ 111 | 112 | None 113 | 114 | License 115 | ------- 116 | 117 | BSD 118 | 119 | Author Information 120 | ------------------ 121 | 122 | Benno Joy 123 | 124 | 125 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | mysql_port: 3306 4 | mysql_bind_address: "0.0.0.0" 5 | mysql_root_db_pass: foobar 6 | 7 | mysql_db: 8 | - name: foo 9 | replicate: yes 10 | - name: bar 11 | replicate: no 12 | 13 | mysql_users: 14 | - name: benz 15 | pass: foobar 16 | priv: "*.*:ALL" 17 | 18 | mysql_repl_user: 19 | - name: repl 20 | pass: foobar 21 | 22 | mysql_repl_role: master 23 | mysql_db_id: 7 24 | 25 | mysql_sql_mode: STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart mysql 3 | service: name={{ mysql_service }} state=restarted 4 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: "Benno Joy" 4 | company: AnsibleWorks 5 | license: license (BSD) 6 | min_ansible_version: 1.4 7 | platforms: 8 | - name: EL 9 | versions: 10 | - 5 11 | - 6 12 | - name: Fedora 13 | versions: 14 | - 16 15 | - 17 16 | - 18 17 | - name: Ubuntu 18 | versions: 19 | - precise 20 | - quantal 21 | - raring 22 | - saucy 23 | categories: 24 | - database:sql 25 | dependencies: [] 26 | 27 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add the OS specific variables 3 | include_vars: "{{ ansible_os_family }}.yml" 4 | 5 | - name: Install the mysql packages in Redhat derivatives 6 | yum: name={{ item }} state=installed 7 | with_items: 8 | - "{{ mysql_pkgs }}" 9 | when: ansible_os_family == 'RedHat' 10 | 11 | - name: Install the mysql packages in Debian derivatives 12 | apt: name={{ item }} state=installed update_cache=yes 13 | with_items: 14 | - "{{ mysql_pkgs }}" 15 | environment: "{{ env }}" 16 | when: ansible_os_family == 'Debian' 17 | 18 | - name: Copy the my.cnf file 19 | template: src=my.cnf.{{ ansible_os_family }}.j2 dest={{ mysql_conf_dir }}/my.cnf 20 | notify: 21 | - restart mysql 22 | 23 | - name: Create the directory /etc/mysql/conf.d 24 | file: path=/etc/mysql/conf.d state=directory 25 | notify: 26 | - restart mysql 27 | 28 | - name: Deploy mysql config to conf.d 29 | template: src=mysql.cnf.j2 dest=/etc/mysql/conf.d/mysql.cnf 30 | notify: 31 | - restart mysql 32 | 33 | - name: Start the mysql services 34 | service: name={{ mysql_service }} state=started enabled=yes 35 | 36 | - name: update mysql root password for all root accounts 37 | mysql_user: name=root host={{ item }} password={{ mysql_root_db_pass }} 38 | with_items: 39 | - "{{ ansible_hostname }}" 40 | - 127.0.0.1 41 | - ::1 42 | - localhost 43 | when: ansible_hostname != 'localhost' 44 | 45 | - name: update mysql root password for all root accounts 46 | mysql_user: name=root host={{ item }} password={{ mysql_root_db_pass }} 47 | with_items: 48 | - 127.0.0.1 49 | - ::1 50 | - localhost 51 | when: ansible_hostname == 'localhost' 52 | 53 | - name: copy .my.cnf file with root password credentials 54 | template: src=.my.cnf.j2 dest=~/.my.cnf mode=0600 55 | 56 | - name: ensure anonymous users are not in the database 57 | mysql_user: name='' host={{ item }} state=absent 58 | with_items: 59 | - localhost 60 | - "{{ ansible_hostname }}" 61 | 62 | - name: remove the test database 63 | mysql_db: name=test state=absent 64 | 65 | - name: Create the database's 66 | mysql_db: name={{ item.name }} state=present 67 | with_items: 68 | - "{{ mysql_db }}" 69 | when: mysql_db|lower() != 'none' 70 | 71 | - name: Create the database users 72 | mysql_user: name={{ item.name }} password={{ item.pass|default("foobar") }} 73 | priv={{ item.priv|default("*.*:ALL") }} state=present host={{ item.host | default("localhost") }} 74 | with_items: 75 | - "{{ mysql_users }}" 76 | when: mysql_users|lower() != 'none' 77 | 78 | - name: Create the replication users 79 | mysql_user: name={{ item.name }} host="%" password={{ item.pass|default("foobar") }} 80 | priv="*.*:REPLICATION SLAVE" state=present 81 | with_items: 82 | - "{{ mysql_repl_user }}" 83 | when: mysql_repl_role == 'master' 84 | 85 | - name: Check if slave is already configured for replication 86 | mysql_replication: mode=getslave 87 | ignore_errors: true 88 | register: slave 89 | when: mysql_repl_role == 'slave' 90 | 91 | - name: Ensure the hostname entry for master is available for the client. 92 | lineinfile: dest=/etc/hosts regexp="{{ mysql_repl_master }}" line="{{ hostvars[mysql_repl_master].ansible_default_ipv4.address + " " + mysql_repl_master }}" state=present 93 | when: slave|failed and mysql_repl_role == 'slave' and mysql_repl_master is defined 94 | 95 | - name: Get the current master servers replication status 96 | mysql_replication: mode=getmaster 97 | delegate_to: "{{ mysql_repl_master }}" 98 | register: repl_stat 99 | when: slave|failed and mysql_repl_role == 'slave' and mysql_repl_master is defined 100 | 101 | - name: Change the master in slave to start the replication 102 | mysql_replication: mode=changemaster master_host={{ mysql_repl_master }} master_log_file={{ repl_stat.File }} master_log_pos={{ repl_stat.Position }} master_user={{ mysql_repl_user[0].name }} master_password={{ mysql_repl_user[0].pass }} 103 | when: slave|failed and mysql_repl_role == 'slave' and mysql_repl_master is defined 104 | 105 | 106 | -------------------------------------------------------------------------------- /templates/.my.cnf.j2: -------------------------------------------------------------------------------- 1 | [client] 2 | user=root 3 | password={{ mysql_root_db_pass }} 4 | -------------------------------------------------------------------------------- /templates/my.cnf.Debian.j2: -------------------------------------------------------------------------------- 1 | # 2 | # The MySQL database server configuration file. 3 | # 4 | [client] 5 | port = {{ mysql_port }} 6 | socket = /var/run/mysqld/mysqld.sock 7 | 8 | # This was formally known as [safe_mysqld]. Both versions are currently parsed. 9 | [mysqld_safe] 10 | socket = /var/run/mysqld/mysqld.sock 11 | nice = 0 12 | 13 | [mysqld] 14 | user = mysql 15 | pid-file = /var/run/mysqld/mysqld.pid 16 | socket = /var/run/mysqld/mysqld.sock 17 | port = {{ mysql_port }} 18 | basedir = /usr 19 | datadir = /var/lib/mysql 20 | tmpdir = /tmp 21 | lc-messages-dir = /usr/share/mysql 22 | skip-external-locking 23 | 24 | bind-address = {{ mysql_bind_address }} 25 | 26 | #key_buffer = 16M 27 | max_allowed_packet = 16M 28 | thread_stack = 192K 29 | thread_cache_size = 8 30 | 31 | query_cache_limit = 1M 32 | query_cache_size = 16M 33 | log_error = /var/log/mysql/error.log 34 | server-id = {{ mysql_db_id }} 35 | 36 | {% if mysql_repl_role == 'master' %} 37 | log_bin = mysql-bin 38 | expire_logs_days = 10 39 | max_binlog_size = 100M 40 | 41 | {% if mysql_db is iterable and mysql_db is not string %} 42 | {% for i in mysql_db %} 43 | {% if i.replicate|default(1) %} 44 | binlog_do_db = {{ i.name }} 45 | {% endif %} 46 | {% endfor %} 47 | 48 | {% for i in mysql_db %} 49 | {% if not i.replicate|default(1) %} 50 | binlog_ignore_db = {{ i.name }} 51 | {% endif %} 52 | {% endfor %} 53 | {% endif %} 54 | {% endif %} 55 | 56 | !includedir /etc/mysql/conf.d/ 57 | -------------------------------------------------------------------------------- /templates/my.cnf.RedHat.j2: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | datadir=/var/lib/mysql 3 | socket=/var/lib/mysql/mysql.sock 4 | user=mysql 5 | # Disabling symbolic-links is recommended to prevent assorted security risks 6 | symbolic-links=0 7 | port={{ mysql_port }} 8 | bind-address={{ mysql_bind_address }} 9 | server-id = {{ mysql_db_id }} 10 | 11 | {% if mysql_repl_role == 'master' %} 12 | log_bin = mysql-bin 13 | expire_logs_days = 10 14 | max_binlog_size = 100M 15 | 16 | {% for i in mysql_db %} 17 | {% if i.replicate|default(1) %} 18 | binlog_do_db = {{ i.name }} 19 | {% endif %} 20 | {% endfor %} 21 | 22 | {% for i in mysql_db %} 23 | {% if not i.replicate|default(1) %} 24 | binlog_ignore_db = {{ i.name }} 25 | {% endif %} 26 | {% endfor %} 27 | {% endif %} 28 | 29 | [mysqld_safe] 30 | log-error=/var/log/mysqld.log 31 | pid-file=/var/run/mysqld/mysqld.pid 32 | 33 | !includedir /etc/mysql/conf.d/ 34 | -------------------------------------------------------------------------------- /templates/mysql.cnf.j2: -------------------------------------------------------------------------------- 1 | [mysqld] 2 | sql_mode={{ mysql_sql_mode }} -------------------------------------------------------------------------------- /vars/Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | mysql_pkgs: 4 | - python-selinux 5 | - mysql-server 6 | - python-mysqldb 7 | 8 | mysql_service: mysql 9 | mysql_conf_dir: "/etc/mysql/" 10 | -------------------------------------------------------------------------------- /vars/RedHat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | mysql_pkgs: 3 | - libselinux-python 4 | - mysql-server 5 | - MySQL-python 6 | 7 | mysql_service: mysqld 8 | 9 | mysql_conf_dir: "/etc/" 10 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | env: 3 | RUNLEVEL: 1 4 | 5 | --------------------------------------------------------------------------------