Configuration management is the new shell scripting and Ansible is one of the easiest to use configuration management systems out there. With computers, if you have to do something more than once, you should automate it. Let the computer handle repeated mundane tasks so your mind frees up for challenges fit for the human brain.
One such mundane task is installing WordPress. You might need to install WordPress for testing, development and main production website, and instead of repeating the installation three times we will write one Ansible playbook which can be run from a different location to install WordPress on your target system(s).
Step 1: The Server(s) Setup
Ideally, we would want there to be a server set aside for running Ansible playbooks, we will call this our build-server. Here our Ansible playbooks would reside and then we would have target servers on which we would like to install WordPress. Sticking with the entire point of automation, it doesn’t matter if you want to run it on one server or several, but for the sake of simplicity, we will have only one target server which will be a clean Ubuntu 18.04 LTS server.
To allow Ansible to connect to our WordPress server, you would need to have a non-root user with sudo privileges. To allow this, create ssh keys on your build server.
$ ssh-keygen -b 4096
In doing so you will be prompted with several options, you can just pick the default option by hitting the return key, repeatedly. The result would be something like this:
In the user’s home directory, which is typically /home/username. The keys are created in .ssh folder.
To make the connection possible we will copy the contents of id_rsa.pub file (which is the public key) into the target WordPress server. Specifically, at the end of file /home/username/.ssh/authorized_keys
where username is the non-root user with sudo privileges, that we mentioned before.
Remember, copy the public key from build-server onto the authorized_keys file of your target server.
Once, that is done, you can restart the sshd service on your target server by running:
$ service sshd restart
The next task is to test whether the ssh connection works. From build-server run:
$ ssh [email protected]
If you are logged into it, that means it works! Now, CTRL-D out back to your build-server, leaving the target WordPress server alone from now on.
Step 2: Writing the Ansible Playbook
The playbook, in Ansible terminology, consists of a set of hosts on which the automation is to be performed, roles that are to be played out, for example, a server acting as database, another as front-end and so on.
In our case, the one single host is going to be responsible for all of these roles. All the configuration described below can be found in this GitHub repo.
Okay, first we need to create a directory where all of our configurations will be stored:
$ mkdir wordpress-playbook $ cd wordpress-playbook $ mkdir roles $ touch hosts $ touch playbook.yml
Here, we created a roles directory and, two empty files hosts and playbook. First thing to do now would be to open up hosts file and add a desired name (need not be the hostname of target server, just a reasonable label) along with the IP address(es) of the server(s) where WordPress will be installed. This is the format for that:
[wordpress] wp_server_ip
You can let the first line be the same and just modify the second line with an appropriate ip address. You can put multiple IPs under [wordpress] to install on multiple servers.
Once that is done, let’s define the different roles in the roles sub-directory:
$ cd roles $ ansible-galaxy init server $ ansible-galaxy init php $ ansible-galaxy init mysql $ ansible-galaxy init wordpress
This brings in template configurations for individual components from ansible-galaxy which is a repository for many standard ansible configurations. You will notice there are now 4 folders created inside wordpress-playbook/roles directory named MySQL, PHP, server and WordPress. Now we need to configure these.
Step 3: Creating Roles
Ansible instructions are written in .yml files which are quite human readable. We will be writing a few ourselves, for each individual roles of the LAMP stack and WordPress build on top of it.
1. Playbook.yml
First, we would write the following contents into the file wordpress-playbook/playbook.yml
- hosts: all gather_facts: False tasks: - name: install python 2 raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal) - hosts: wordpress roles: - server - php - mysql - wordpress
This installs Python 2.7 onto your all your target servers (which is an Ansible dependency) and then it goes on to assigning 4 roles to the hosts labelled WordPress.
2. Server Role
Using your favourite text editor (for example nano or vim), open the file wordpress-playbook/roles/server/tasks/main.yml and write the following contents into it.
--- # tasks file for server - name: Update apt cache apt: update_cache=yes cache_valid_time=3600 become: yes - name: Install required software apt: name={{ item }} state=present become: yes with_items: - apache2 - mysql-server - php7.2-mysql - php7.2 - libapache2-mod-php7.2 - python-mysqldb
Note: The first two lines would be there by default.
2. PHP
Next, we need to install additional PHP modules for that write the following contents to the file wordpress-playbook/roles/php/tasks/main.yml
--- # tasks file for php - name: Install php extensions apt: name={{ item }} state=present become: yes with_items: - php7.2-gd - php7.2-ssh2
4. MySQL
MySQL would need some extra information before it starts creating our database. In the file wordpress-playbook/roles/mysql/defaults/main.yml
--- # defaults file for mysql wp_mysql_db: wordpress wp_mysql_user: wordpress wp_mysql_password: randompassword
Obviously, we urge you to put a really strong password in place of “randompassword” in the last line.
After this, we configure our main MySQL task of creating a MySQL user, database and granting that user access to the newly created database. In the file, wordpress-playbook/roles/mysql/tasks/main.yml write the following:
--- - name: Create mysql database mysql_db: name={{ wp_mysql_db }} state=present become: yes - name: Create mysql user mysql_user: name={{ wp_mysql_user }} password={{ wp_mysql_password }} priv=*.*:ALL become: yes
5. WordPress
This is probably the most complex role in this configuration. You will have to get WordPress tar file from the official site, extract it and modify the wp-config.php with appropriate data. To do that, write the following contents into your wordpress-playbook/roles/wordpress/tasks/main.yml
--- - name: Download WordPress get_url: url=https://wordpress.org/latest.tar.gz dest=/tmp/wordpress.tar.gz validate_certs=no - name: Extract WordPress unarchive: src=/tmp/wordpress.tar.gz dest=/var/www/ copy=no become: yes - name: Update default Apache site become: yes lineinfile: dest=/etc/apache2/sites-enabled/000-default.conf regexp="(.)+DocumentRoot /var/www/html" line="DocumentRoot /var/www/wordpress" notify: - restart apache - name: Copy sample config file command: mv /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php creates=/var/www/wordpress/wp-config.php become: yes - name: Update WordPress config file lineinfile: dest=/var/www/wordpress/wp-config.php regexp="{{ item.regexp }}" line="{{ item.line }}" with_items: - {'regexp': "define\\('DB_NAME', '(.)+'\\);", 'line': "define('DB_NAME', '{{wp_mysql_db}}');"} - {'regexp': "define\\('DB_USER', '(.)+'\\);", 'line': "define('DB_USER', '{{wp_mysql_user}}');"} - {'regexp': "define\\('DB_PASSWORD', '(.)+'\\);", 'line': "define('DB_PASSWORD', '{{wp_mysql_password}}');"} become: yes
And finally, because we would need to restart Apache to see WordPress work, add the following snippet to your wordpress-playbook/roles/wordpress/handlers/main.yml
--- # handlers file for wordpress - name: restart apache service: name=apache2 state=restarted become: yes
Step 4: Running Ansible
Hopefully, you have executed the above steps correctly, if so then running the following command, from the directory wordpress-playbook, would install WordPress into your target host:
$ ansible-playbook playbook.yml -i hosts -u username -K
Where username is to be replaced by the literal username on the host system who has sudo privileges. If everything goes right, you would see an output like following:
Anytime, you need to install WordPress onto a server, add its IP under the wordpress-playbook/hosts file and then run the above command again. Upon visiting the IP address of your target server, using a web browser, you will be greeted by WordPress:
Conclusion
Hopefully, this introduction was motivating enough that you would try installing WordPress using Ansible and try to extent its capabilities. We urge you to look into how you would encrypt your database password instead of leaving it as plain text. Similarly, you might want to try having salted passwords for securing your installation for production.