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.
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
- Nginx webserver with HTTP2/ and optional FastCGI micro-caching
- sSMTP (mail delivery)
- Fail2ban and ferm
- 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
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 https://roots.io/trellis/cli/get | sudo bash
If Shell completions aren’t working, install them manually with the command:
Step 1 – Create a WordPress Project
Creating a project with Trellis is simple. Use the command below and replace wordpress.example.com with your own project dame/domain
trellis new wordpress.example.com
Site domain [wordpress.example.com]: ? Select main site host: + Other ▸ wordpress.example.com [✓] Created virtualenv (/home/admin/wordpress.example.com/trellis/.trellis/virtualenv) [✓] Ensure pip is up to date [✓] Dependencies installed Starting galaxy role install process - downloading role 'composer', owned by geerlingguy - downloading role from https://github.com/geerlingguy/ansible-role-composer/archive/1.9.0.tar.gz - extracting composer to /home/admin/wordpress.example.com/trellis/vendor/roles/composer - composer (1.9.0) was installed successfully ..... wordpress.example.com 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 192.168.56.5.
Once that is configured, run the command below:
cd wordpress.example.com/trellis 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
There are two concepts here:
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:
Add the remote hosts to both group and type as below:
[production] 192.168.205.11 [web] 192.168.205.11
- For Staging
If you choose to proceed with the staging setup, edit the hosts here:
Add your hosts to both the group and type as you did for the production hosts.
[staging] 192.168.205.11 [web] 192.168.205.11
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/id_rsa.pub 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.
In the file, make the below settings. Remember to provide the remote user with sudo access under the admin_user.
# Documentation: https://roots.io/trellis/docs/ssh-keys/ 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: https://docs.roots.io/trellis/master/vault/ vault_mysql_root_password: RootDBPassw0rd vault_users: - name: ' admin_user ' password:
salt: r53NvbZaTcpFohekOetrDh9EXo14JdzJQaYOEsOQJfzbLgOcdeIgj4SJyHZF0dyr vault_wordpress_sites: wordpress.example.com: admin_password: Passw0rd env: 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 (wordpress.example.com) 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 wordpress_sites: wordpress.example.com: site_hosts: - canonical: wordpress.example.com redirects:  local_path: ../site branch: master repo: [email protected] repo_subtree_path: site multisite: enabled: false ssl: enabled: true provider: letsencrypt cache: enabled: false
- For staging(with self-signed certificates)
$ vim group_vars/staging/wordpress_sites.yml wordpress_sites: wordpress.example.com: site_hosts: - canonical: wordpress.example.com redirects:  local_path: ../site branch: master repo: [email protected]:computingpost.git repo_subtree_path: site multisite: enabled: false ssl: enabled: true provider: self-signed cache: 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
..... Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB) Using legacy 'setup.py install' for ansible, since package 'wheel' is not installed. Using legacy 'setup.py 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 setup.py install for ansible-base ... done Running setup.py 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/wordpress.example.com/current/web sudo chown -R $USER:$USER /srv/www/wordpress.example.com cd /srv/www/wordpress.example.com/current/web 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.
Provide the database details accordingly:
##For Production wordpress_example_com_staging /** 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 https://domain_name.com.
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.