Ansible Guide: Create Ansible Playbook for LEMP Stack

ComputingPost
8 min readJan 12, 2023

--

Ansible is a simple automation tool that automates software application deployment, cloud provisioning, and configuration management. It’s a server orchestration tool that helps you to manage and control a large number of server nodes from single places called ‘Control Machines’. Ansible was created by Michael DeHaan in 2012 and is written in Python and Powershell.

In this tutorial, we’re going to show you how to create basic Ansible Playbook for provisioning the LEMP Stack on Ubuntu 18.04 Server. You will learn how to create basic Ansible Playbook that can be scaled for other PHP project applications such as WordPress, Nextcloud etc.

Prerequisite

  • 2 Ubuntu OS.
  • 10.5.5.20 ansible
  • 10.5.5.26 provision
  • Knowledge of basic usage Ansible
  • Root privileges

What we will do:

  1. Setup Ansible Playbook Project
  2. Generate Ansible Playbook Roles Directory Structure
  3. Setup hosts and site.yml
  4. Setup ‘common’ Roles — Basic setup
  5. Setup ‘web’ Roles — Nginx and PHP-FPM Configuration
  6. Setup ‘db’ Roles — MySQL Database Configuration
  7. Testing

Step 1 — Setup Ansible Playbook Project

Ansible Playbook is a set of instructions that you send to run on a single or group of server hosts. It represents the ansible-provisioning, where the automation is defined as tasks, and all jobs like installing packages, editing files, will be done by ansible modules.

The Ansible Playbook contains some basic configuration, including hosts and user information of the provision servers, a task list that will be implemented to the provision servers, template and custom configurations, and a group of variables part of templates and tasks.

Firstly, create the master project directory on the ‘ansible-control’ machine. The master project directory will be stored all our playbook directories, files, and configurations.

Create the Ansible project directory called ‘project-lemp’ and go into it.

mkdir project-lemp/

cd project-lemp

Now create new configuration file ‘hosts’ and ‘site.yml’, then create a new directory called ‘roles’.

touch hosts site.yml

mkdir -p roles/

Details about configurations:

hosts — It’s an inventory file that contains pieces of information about managed servers by ansible. It allows you to create a group of servers that make you more easier to manage and scale the inventory file itself. The inventory file can be created with many different formats, including the INI and YAML formats.

site.yml — The master playbook file that contains which group of hosts that will be managed using our available roles.

roles — it’s a group of Ansible playbooks that will be used to provision the server. The ansible roles have their own directory structures, each role will contain directories such as tasks, handlers, vars etc.

Step 2 — Generate Ansible Roles for the Directory Structure

In this step, we’re going to generate ansible roles directory using the ansible-galaxy command. We will generate two of roles called ‘common’ roles and the ‘web’ roles.

Inside the ‘project-lemp’ directory, go to the directory ‘roles’.

cd roles/

Generate roles structure directory and files for the ‘common’ and ‘web’ roles by running the ansible-galaxy command below.

ansible-galaxy init common

ansible-galaxy init web

ansible-galaxy init db

After that, check all available ansible roles directory structures using the following command.

tree .

You will be shown the result as below.

Step 3 — Setup hosts and site.yml

The ‘hosts’ file will contain list and group of the server managed by the Ansible. For this guide, we will create a group called ‘lemp’ with the member named ‘server01’ and the IP address 10.5.5.26.

Edit the ‘hosts’ file using vim editor.

vim hosts

Paste configuration below.

[lemp]

server01 ansible_host=10.5.5.26

Save and close.

Next, edit the site.yml configuration file.

vim site.yml

Paste configurations below.

---



- hosts: lemp

remote_user: hakase

become: yes



roles:

- common

- web

- db

Save and close.

Step 3 — Setup Common Roles

In this step, we’re going to set up the common roles. And in order to do that, we need to create a list of tasks that we’re going to do.

Below the list of tasks that we’re going to do on the ‘common’ roles.

  1. Change repository
  2. Update repository
  3. Upgrade packages to the latest version
  4. Setup the server timezone

Now go to the ‘common’ directory and edit the ‘tasks/main.yml’ configuration.

cd common/

vim tasks/main.yml

Create a task for changing the repository, and we will be using the ‘copy’ module that will copy the base ‘sources.list’ on the ‘files’ directory to the remote host ‘/etc/apt/’.

- name: Change repository Ubuntu 18.04Step 4 - Setup 'web' Roles

copy:

src: sources.list

dest: /etc/apt/

backup: yes

Create a task for updating the repository and upgrade all packages to latest version using the ‘apt’ module.

- name: Update repository and Upgrade packages

apt:

upgrade: dist

update_cache: yes

Now create the task for configuring the system timezone using the ansible timezone module.

- name: Setup timezone to Asia/Jakarta

timezone:

name: Asia/Jakarta

state: latest

Save and close.



After that, create a new repository configuration ‘sources.list’ inside the ‘files’ directory.

vim files/sources.list

Choose the nearest repository of your server location, below is mine.

deb http://buaya.klas.or.id/ubuntu/ bionic main restricted

deb http://buaya.klas.or.id/ubuntu/ bionic-updates main restricted

deb http://buaya.klas.or.id/ubuntu/ bionic universe

deb http://buaya.klas.or.id/ubuntu/ bionic-updates universe

deb http://buaya.klas.or.id/ubuntu/ bionic multiverse

deb http://buaya.klas.or.id/ubuntu/ bionic-updates multiverse

deb http://buaya.klas.or.id/ubuntu/ bionic-backports main restricted universe multiverse

deb http://buaya.klas.or.id/ubuntu/ bionic-security main restricted

deb http://buaya.klas.or.id/ubuntu/ bionic-security universe

deb http://buaya.klas.or.id/ubuntu/ bionic-security multiverse

Save and close.

lastly, the ‘common’ roles configuration has been completed.

Step 4 — Setup ‘web’ Roles

In this step, we’re going to set up the ‘web’ roles. It will do some tasks including install the Nginx web server, PHP-FPM with some basic extentions, and configuring the PHP-FPM with Nginx.

Below are details tasks that we will do on the ‘web’ roles:

  1. Install Nginx
  2. Install PHP-FPM
  3. Configure php.ini
  4. Create a virtual host
  5. Add file phpinfo

Goto the ‘web’ directory and edit the ‘tasks/main.yml’ file.

cd web/

vim tasks/main.yml

Create the first task for nginx installation using the apt module.

- name: Install Nginx

apt:

name: nginx

state: latest

Now create the task for installing PHP-FPM with some basic extensions. And for the multiple packages installation, we can use python ‘list’ format such as below.

- name: Instal PHP-FPM

apt:

name: ['php','php-fpm','php-common','php-cli','php-curl']

state: latest

Next, we will add new lines to the php.ini configuration using the ‘blockinfile’ module. And at the end of the line, we will notify the ansible to restart the php-fpm service after configuring the php.ini file.

- name: Configure php.ini

blockinfile:

dest: /etc/php/ php_version /fpm/php.ini

block: |

date.time = Asia/Jakarta

cgi-fix_pathinfo = 0

backup: yes

notify: restart php-fpm

Now we will copy the nginx virtual host configuration using the ‘template’ module. The template module will copy the configuration from the ‘templates’ directory to the remote server. We’re going to copy the jinja2 virtual host template ‘vhost.j2’ to the ‘/etc/nginx/sites-enabled/’ directory, and the last we will notify the ansible to restart the nginx service.

- name: Create Nginx virtual host

template:

src: vhost.j2

dest: /etc/nginx/sites-enabled/vhost- domain_name

notify: restart nginx

After that, we will create new tasks for creating the web-root directory using the ‘file’ module and copy the index.php template into it.

- name: Create web-root directory

file:

path: /var/www/ domain_name

state: directory



- name: Upload index.html and info.php files

template:

src: index.php.j2

dest: /var/www/ domain_name /index.php

Save and close.

Now we’re going to configure the handlers for restarting the nginx and php-fpm service. Edit the ‘handlers/main.yml’ configuration using vim editor.

vim handlers/main.yml

Paste configurations below.

- name: restart nginx

service:

name: nginx

state: restarted

enabled: yes



- name: restart php-fpm

service:

name: php php_version -fpm

state: restarted

enabled: yes

Save and close.



Next, we will edit the ‘vars/main.yml’ configuration. At the top of configurations you will notice the variable configurations ‘ php_version ‘ and ‘ domain_name ‘. Those variables represent our environment setup for the php version and the domain name that will be used. The variable makes ansible more reusable because we just need to edit the variable configuration ‘vars/main.yml’ and not editing the base configuration.

Edit the variables configuration ‘vars/main.yml’ using vim editor.

vim vars/main.yml

Paste configurations below.

php_version: 7.2

domain_name: hakase-labs.io

Save and close.

Now we will create jinja2 template configurations ‘index.php.j2’ and ‘vhost.j2’ on the ‘templates/’ directory.

vim templates/index.php.j2

Paste configuration below.

index.html for domain domain_name

phpinfo();

?>







Save and close.



After that, create the template for nginx virtual host configuration 'vhost.j2'.
vim templates/vhost.j2Paste configurations below.server

listen 80;

listen [::]:80;



root /var/www/ domain_name ;

index index.php index.html index.htm index.nginx-debian.html;



server_name domain_name ;



location /

try_files $uri $uri/ =404;





# pass PHP scripts to FastCGI server

#

location ~ \.php$

try_files $uri =404;

fastcgi_split_path_info ^(.+\.php)(/.+)$;

fastcgi_pass unix:/var/run/php/php php_version -fpm.sock;

fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

include fastcgi_params;
Save and close the configuration, and we're finished the web roles configuration.

Step 5 — Setup ‘db’ Roles

At this step, we're going to configure the 'db' roles for the MySQL database installation and configuration.



Below are details tasks that will do on the 'db' roles.
  1. install mysql
  2. Create MySQL database
  3. Create MySQL user
  4. restart mysql
Goto the 'db' directory and edit the 'tasks/main.yml' configuration.cd db/

vim tasks/main.yml
Now install the MySQL packages using the 'apt' module and python 'list' format for multiple packages installation.- name: Install MySQL

apt:

name: ['mysql-server','mysql-client','python-mysqldb']

state: latest

notify: restart mysql
Then create new tasks for creating the MySQL database and user, then grant all privileges of the user to the database.- name: Create database

mysql_db:

name: ' db_name '

state: present



- name: Create user for the database

mysql_user:

name: ' db_user '

password: ' db_pass '

encrypted: yes

priv: ' db_name .*:ALL'

state: present
Save and close.







Next, edit the 'handlers/main.yml' configuration.
vim handlers/main.ymlPaste the configuration of the task for restarting the MySQL service.- name: restart mysql

service:

name: mysql

state: restarted

enabled: yes
Save and close.



After that, edit the vars variable configuration 'vars/main.yml'.
vim vars/main.ymlPaste these variables for MySQL database and user configuration below.db_name: hakase-db

db_user: hakase

db_pass: '*C960D382DB42E57D3BAC33891CF87900DCB1A869'
Save and close.



The 'db_pass' variable has the MySQL encrypted password, and you can generate an encrypted MySQL password using online tools.

Step 6 — Run the Ansible Playbook

Goto the Ansible project directory.cd project-lemp/Run the ansible-playbook command below.ansible-playbook -i hosts site.ymlNow the ansible will run all roles that we assign to the host. When it's complete, you will be shown the result as below.







Make sure you get no error.

Step 7 — Testing

Open your web browser and type the domain name on the address bar http://hakase-labs.io.



And you will be shown the index page with phpinfo as below.







The PHP-FPM and Nginx are working.



Next, back to the server terminal and log in to the MySQL server using the user and password that we've created on the 'mysql' roles variable.
mysql -u hakase -p

PASSWORD: hakasepass
check the list of database owned by the user.show databases;And you will be logged to the MySQL shell and will be shown the database named 'hakase-db' on the list.







Finally, the Ansible Playbook for the LEMP Stack installation and configuration has been created and tested successfully.

https://www.computingpost.com/ansible-guide-create-ansible-playbook-for-lemp-stack/?feed_id=25815&_unique_id=63c05e2313172

--

--

ComputingPost

ComputingPost — Linux Howtos, Tutorials, Guides, News, Tips and Tricks.