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.
Requirements.
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 https://roots.io/trellis/cli/get | 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 wordpress.example.com with your own project dame/domain
trellis new wordpress.example.com
Sample Output:
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 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.
cd wordpress.example.com/trellis
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:
[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:
vim hosts/staging
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.
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: 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: <Enter the sudo user password Here>
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]:neveropen.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
Sample Output:
.....
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.
vim wp-config.php
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.
Related posts:
How to upgrade Ansible AWX running in Kubernetes
How To Manage PostgreSQL Database with Ansible
Install LAMP Stack on Ubuntu / Debian with Ansible