How To Setup LEMP stack for WordPress using Ansible

Posted on 140 views

Welcome to this guide on how to set up the LEMP stack for WordPress using Ansible. Trellis is an ansible-powered tool used to deploy WordPress sites. It lets you create and manage production-ready servers with optimized performance.

Trellis offers the following features:

  • Local development – Trellis comes with Vagrant (opens new window)support for local development environments that run on isolated virtual machines. You can as well use the local dev tools as well.
  • Customizable – it gives you all the requirements for a standard WordPress server but is still customizable.
  • Portable without vendor-lock-in – It can be run on any hosting platform; traditional dedicated server hosting or cloud platforms.
  • Community backed – Trellis is an open-source tool with a large community that continuously improves the defaults over time
  • CLI – It comes with a CLI which makes management of local/remote servers easy.
  • Zero-downtime deploys – It has atomic, zero-downtime deploys built-in that is completely configurable with a powerful hook system. It is possible to deploy and roll back with a single CLI command.

Provisioned Software

Trellis, provisions a server with Ubuntu 20.04 base and provisions the following software:

  • PHP 8.0+
  • MariaDB database server
  • SSL support (scores an A+ on the Qualys SSL Server Test
  • Let’s Encrypt SSL certificates
  • WP-CLI
  • Composer
  • Nginx webserver with HTTP2/ and optional FastCGI micro-caching
  • sSMTP (mail delivery)
  • Fail2ban and ferm
  • Memcached
  • Other services like NTP and sshd

In this guide, we will use systematically walk through how to set up the LEMP stack for WordPress using Ansible.


For this guide, you need the below packages:

  • Python 3
  • trellis-cli

Install Python and other dependencies on your system using the command:

##On Ubuntu / Debian
sudo apt update
sudo apt install ansible python3 python3-pip python3-venv vim curl -y

##On CentOS / Rocky Linux / AlmaLinux
sudo yum -y install epel-release
sudo yum install ansible python3 python3-pip python3-virtualenv vim curl -y

Proceed and install the trellis-cli as below:

curl -sL | sudo bash

If Shell completions aren’t working, install them manually with the command:

trellis --autocomplete-install

Step 1 – Create a WordPress Project

Creating a project with Trellis is simple. Use the command below and replace with your own project dame/domain

trellis new

Sample Output:

Site domain []: 

? Select main site host: 
+   Other

[✓] Created virtualenv (/home/admin/
[✓] Ensure pip is up to date
[✓] Dependencies installed
Starting galaxy role install process
- downloading role 'composer', owned by geerlingguy
- downloading role from
- extracting composer to /home/admin/
- composer (1.9.0) was installed successfully
..... project created with versions:
  Trellis v1.14.0
  Bedrock v1.19.3

Trellis has two playbooks, the dev.yml and server.yml. Based on the two playbooks, there are two approaches:

  • Local development:

Trellis uses the Vagrantfile that uses the ansible provisioner to run the playbook, dev.yaml. This will get a new Vagrant virtual machine running the WordPress site.

You can as well edit the IP address in the vagrant.default.yml to allow running multiple boxes concurrently. The default IP is

Once that is configured, run the command below:

trellis up
  • Remote server setup (staging/production)

This is similar to local deployment only that local development automatically creates a virtual machine and provisions it.

Remember that a base Ubuntu 18.04|20.04 is required for the remote server. Here, the configuration used is server.yml.

There are two concepts here:

  • Provision
  • Deploy

Provisioning set up the server with the required software and configuration required for the WordPress site. In this stage, MariaDB and Nginx e.t.c are installed and configured.

Step 2 – Provision the Project

For this guide, we will a provision remote server using the steps below:

2.1 – Set up target hosts

We will begin by configuring the ansible hosts defined in the /hosts/env file.


Here, we have production and staging hosts. Choose one environment that best works for you. This guide aims to demonstrate how to provision production(with Let’s Encrypt SSL) and staging(with self-signed certificates).

  • For Production

Open the below file for editing:

vim hosts/production

Add the remote hosts to both group and type as below:


  • For Staging

If you choose to proceed with the staging setup, edit the hosts here:

vim hosts/staging

Add your hosts to both the group and type as you did for the production hosts.



Once the above configurations have been made, generate and copy SSH keys to the remote system.

ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/ username@remote_IP

2.2 – Defining Users.

The users are defined by the users.yaml file. Here, you need to you can also add the GitHub’ (SSH) keys by editing the file as below.

vim group_vars/all/users.yml

In the file, make the below settings. Remember to provide the remote user with sudo access under the admin_user.

# Documentation:
admin_user: ubuntu

In our example, ubuntu is the remote server username.

2.3 – Configure Ansible vault password

The password variables are declared in the env/vault.yml files. Here, provide the sudo password, MySQL root password, database password e.t.c

##For Production
vim group_vars/production/vault.yml

##For Staging
vim group_vars/staging/vault.yml

Enter the password for the remote user, MySQL database and root passwords.

# Documentation:
vault_mysql_root_password: RootDBPassw0rd
- name: ' admin_user '
  salt: r53NvbZaTcpFohekOetrDh9EXo14JdzJQaYOEsOQJfzbLgOcdeIgj4SJyHZF0dyr
    admin_password: Passw0rd
      db_password: Passw0rd

2.4 – Configure the Site Meta

This is where the essential site information is stored. This includes:

  • set the canonical site URL ( for the site
  • defined the URL for the repository
  • the git repo branch that gets deployed.
  • enabled SSL (set to true), which will also install an SSL certificate when the box provisions

Edit the files as below:

  • For Production(with Let’s Encrypt SSL)
$ vim group_vars/production/wordpress_sites.yml
    - canonical:
      redirects: []
    local_path: ../site
    branch: master
    repo: [email protected]
    repo_subtree_path: site
      enabled: false
      enabled: true
      provider: letsencrypt
      enabled: false
  • For staging(with self-signed certificates)
$ vim group_vars/staging/wordpress_sites.yml
    - canonical:
      redirects: []
    local_path: ../site
    branch: master
    repo: [email protected]:computingpost.git
    repo_subtree_path: site
      enabled: false
      enabled: true
      provider: self-signed
      enabled: false

Step 3 – Set Up LEMP stack for WordPress using Ansible.

Install the requirements using the requirements.txt file:

sudo pip3 install -U pip setuptools 
pip3 install -r requirements.txt 

Sample Output:

  Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Using legacy ' install' for ansible, since package 'wheel' is not installed.
Using legacy ' install' for ansible-base, since package 'wheel' is not installed.
Installing collected packages: pycparser, pyparsing, MarkupSafe, cffi, PyYAML, packaging, jinja2, cryptography, ansible-base, passlib, ansible
    Running install for ansible-base ... done
    Running install for ansible ... done
Successfully installed MarkupSafe-2.0.1 PyYAML-6.0 ansible-2.10.7 ansible-base-2.10.16 cffi-1.15.0 cryptography-37.0.0 jinja2-3.0.3 packaging-21.3 passlib-1.7.4 pycparser-2.21 pyparsing-3.0.8

After the command, you will have Ansible set with all the requirements installed. Proceed and install the LEMP stack on the remote system.

##For Production
ansible-playbook server.yml -e env=production

##For Staging
ansible-playbook server.yml -e env=staging

If everything goes well, you should see this.


That is it! You have the LEMP stack set up on the remote system. MySQL has been installed and the database details created depending on your domain name. For this case, we have:

##For Production
Database: wordpress_example_com_production
User: wordpress_example_com

##For Staging
Database: wordpress_example_com_production
User: wordpress_example_com

The password used to connect to the database is defined in the vault.yml file. Now proceed and set up WordPress.

Step 4 – Set Up WordPress on the Remote Host.

Now download WordPress using the wp command in the directory below.

sudo mkdir -p /srv/www/
sudo chown -R $USER:$USER /srv/www/
cd /srv/www/
wp core download

Create the wp-config.php file.

cp wp-config-sample.php wp-config.php

Edit the config file and add the database credentials.

vim wp-config.php

Provide the database details accordingly:

##For Production
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress_example_com_production' );

/** Database username */
define( 'DB_USER', 'wordpress_example_com' );

/** Database password */
define( 'DB_PASSWORD', 'Passw0rd!' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

##For Staging
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress_example_com_staging' );

/** Database username */
define( 'DB_USER', 'wordpress_example_com' );

/** Database password */
define( 'DB_PASSWORD', 'Passw0rd!' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

Step 5 – Access WordPress.

Proceed and access WordPress using the URL


Provide the site information and create the admin user.


The admin account will be created as above. Login to the admin dashboard.


On the admin dashboard, you can create new posts and makes customizations to WordPress.


That is it!

We have successfully walked through how to set up the LEMP stack for WordPress using Ansible. We have also deployed the WordPress instance successfully. I hope this was significant.


Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.