WordPress LEMP Stack Management with Trellis

A few months ago – 8 months already yikes! – I wrote a great post on Bedrock Modern WordPress Stack and as is it became a rather long post I decided to indicate I would write on Bedrock Ansible – now Trellis a little later on. Well time has come and gone and the only item I wrote about was dealing with Trellis errors. Also got a lot of hits, but this follow up blog post was still missing. So I finally decided to give it a shot again. WordPress LEMP Stack management with Trellis here we go!


I wrote a little about Trellis in that mentioned post and to quote myself here Trellis is:

Trellis is basically an extension of Bedrock and helps you with easing the deployment of sites and management of sites locally, on staging and production environments.

Again, just like I love Bedrock Modern WordPress stack I am infatuated with Trellis for local development, provisioning and deployment of WordPress sites. It is an awesome tool built on the shoulders of giants like mainly Ansible for using its playbooks and Vagrant to do several things:

  • local environment creation with Vagrant, VirtualBox and Ansible
  • Staging setup using Ansible for staging on subdomain or other local domain
  • Deployment of site to final destination or production

Trellis Specs 02-2016

And as these awesome guys at Roots keep on developing and updating all tools we can now use HTTPS, HTTP2 and PHP 7 . How awesome is that! Here the latest specs you get setting up a local server (Vagrant Box) or a remote server:

  • Ubuntu 14.04 Trusty LTS
  • Nginx (with optional FastCGI micro-caching)
  • PHP 7.0
  • MariaDB as a drop-in MySQL replacement (but better)
  • SSL support (A+ on https://www.ssllabs.com/ssltest/)
  • HTTP/2 support (requires SSL)
  • Composer
  • WP-CLI
  • sSMTP (mail delivery)
  • Memcached
  • Fail2ban
  • ferm


I assume you noticed NGINX. A lot of devs out there are still using Apache and I am still too, but Nginx is awesome and really is the future for dealing with more traffic and is being used more and more so this should not slow you down one bit.

Setting up Trellis

Basically the whole setup has been explained on the Trellis repo and I think it is pretty clear. It has been written with using Bedrock in mind. But if you do not want to use the neat Bedrock file structure you do not have. The same things goes for Trellis. If you want Sage and Bedrock only or just Sage you are free to do so.


Most local boxes do not have Ansible installed nor all the Vagrant tools for that matter. So double check what you have before you start of with Trellis. These tools are needed. Git is also needed. This for keeping track of changes in the main repo, your local installation and on staging as well as the pleasure of simply cloning the Trellis repo.

Local Setup

After you made sure you installed VirtualBox, Vagrant and needed plugins as well as Ansible it is time to clone Trellis and get started setting up the local Vagrant box.

git clone https://github.com/roots/trellis.git

cloning Trellis

Then you need to install all Ansible roles and packages:

cd trellis
ansible-galaxy install -r requirements.yml

Ansible roles and packages


Well and then you have the opportunity to add Bedrock to the mix if you want to and then I would refer to the earlier article. If you are doing a new site setup from scratch I would. If not I would clone the whole package once the server has been set up locally and or remotely. But really even then you could do the Bedrock setup and import the database and needed files for your app.

Here are the command to set up Bedrock inside folder demo.dev (changed to site later as this makes more sense workflow wise)

cd ..
git clone https://github.com/roots/bedrock.git site
cd site
composer install

Installing Bedrock

Project Structure

You should now have your project folder with inside the folder / directory trellis and the directory with the name of you site. I chose demo.dev in some of the screenshots, but for you it would make more sense to use  use site as the config files have been setup that way and as the root folder already could or should have the name of your project, namely the production site domain name.

project structure

Configuration – Local, Staging and Production

What is next is configuring all the necessary files to make the local, staging and production setup correct with correct domain names, admin user and password, MySQL password and so on. We will configure the files for development for now. The process is almost the same for staging and production. The main files to configure  are located in project-name > trellis > group_vars > and then for the purposes of this blog post development:


group_vars - development

The two files we will adjust here are wordpress_sites.yml and vault.yml . Here we indicate the site domain name locally and what MySQL password and WordPress user and password we want to be created.


The file wordpress_sites.yml is the main file where you pick the basic elements for you development environment. In this case the local environment. Here below you see I have the name test1.com as main domain, test1.dev for development and local path site (unchanged). I also added the home url and site url as well as database user and name.

# Documentation: https://roots.io/trellis/docs/local-development-setup/
 - test1.dev
 local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
 site_install: true
 site_title: test1 Site
 admin_user: admin
 # admin_password: (defined in group_vars/development/vault.yml)
 admin_email: admin@test1.dev
 initial_permalink_structure: /%postname%/ # applied only at time of WP install and when `site_install: true`
 enabled: false
 subdomains: false
 enabled: false
 enabled: false
 duration: 30s
 disable_wp_cron: true
 wp_home: http://test1.dev
 wp_siteurl: http://test1.dev/wp
 wp_env: development
 db_name: test1_dev
 db_user: test1_dbuser
 # db_password: (defined in group_vars/development/vault.yml)


vault.yml content for local development is not adjusted much as all is for local development. I kept the MySQL password as is and only adjusted the domain name and admin password.

# Documentation: https://roots.io/trellis/docs/vault/
vault_mysql_root_password: devpw
# Documentation: https://roots.io/trellis/docs/security/
 admin: $6$rounds=100000$JUkj1d3hCa6uFp6R$3rZ8jImyCpTP40e4I5APx7SbBvDCM8fB6GP/IGOrsk/GEUTUhl1i/Q2JNOpj9ashLpkgaCxqMqbFKdZdmAh26/
# Variables to accompany `group_vars/development/wordpress_sites.yml`
 admin_password: admin
 db_password: admin

Creating the Vagrant Box

with that done we can start generating our own local development environment by starting up our Vagrant box. This will contain all specified by Trellis and have a WordPress site with Bedrock’s structure up and running. Go to the trellis folder and fire of:

vagrant up

Vagrant Provisioning snapshot:

Vagrant Provisioning

Once that is done the site will be up and running in your browser. In my case a test1.dev and you will see something like:

local test.dev site



So there you go. The magical has happened. A local LEMP stack has been setup by Trellis with a secure site structure using Bedrock and a WordPress site up and running. Isn’t this awesome! You can start working on your theme now or plugins and when you are ready to move to staging you can configure all the other files. That should be a breeze.

As this post is again really long I will add deployment to production to another post. I might even split this one into two posts again some time later on. Stay tuned!

WPML – Two Languages – Two Domains – One CMS

Some of you may know that Imagewize Webdesign, run by me, is a site that runs on two languages from two different domains – Dutch and English. This is done using the nifty plugin WPML. With it you can manage your content in multiple languages. You can also run all content from one location and still serve it on separate (sub) domains! To make this work you do need to set things up properly in the backend and server wise. Here is how.

WPML – Intro

WPML is the best multilingual Content Management Plugin out there for WordPress. I do use qTranslate X, but it simply cannot compete with the options WPML offers and certainly cannot offer the stability WPML has to offer. qTranslate has gone through several reincarnations over the past couple of years and has been buggy at times. WPML works well out of the box, deals with:

  • permalinks,
  • string translations,
  • menu translation management,
  • theme translation management,
  • language switcher
  • media translation

It does it all and no extra plugins are needed. Nice!

Now let’s get back to the cool feature of WPML – Two Languages – Two Domains – One CMS

Server Side

On the Apache webserver – NGinx not covered – you need to make sure that all traffic going to the domain that is not running the content is redirected to the main domain location or vhost. This can be done using a ServerAlias. WPML Example here below:

<VirtualHost *>
  DocumentRoot /your_wp_install_directory/wordpress
  ServerName www.english-domain.com
  ServerAlias www.french-domain.fr

  ... your other stuff here ...

So for Imagewize we needed:

<VirtualHost xxx.xxx.xxx.xx:80>
ServerAdmin webmaster@imagewize.nl
DocumentRoot /home/wp_zzsk4g/imagewize.com
ServerName www.imagewize.nl
ServerAlias imagewize.nl

As you see Dreamhost added the ip address and port. Inside that vHost the DocumentRoot was added with a ServerName and ServerAlias imagewize.nl to redirect all traffic from that domain to imagewize.com.

The basic Domain name mirroring that is supposed to work as a ServerAlias with Dreamhost just did not do the trick. I assume it was only adding a ServerAlias and not a DocumentRoot to load data from one location. But I am glad Dreamhost helped me out in the end and set this up on my Dreamhost Managed VPS!

Client side

Client side you need to configure WPML – dashboard > WPML > languages > language url format – to load the content of the main language from domain a and for the secondary language from domain b.

WPML - Two Languages - Two Domains - One CMS

WPML will validate the domains added to make sure they are correct and all works.

Any question, comments? Please let me know in the comments!



Dreamhost VPS no longer allows adjusting httpd.conf or adding vhosts – no sudo access anymore. The mirroring of the domain nor the chaning the DocumentRoot to make imagewize.nl load data from imagewize.com for WordPress with WPML worked as a new solution. So I had to use the second language in a subdirectory and redirect the second domain traffic there using a redirect in the .htaccess:

<IfModule mod_rewrite.c> 
RewriteEngine on 
RewriteCond %{HTTP_HOST} ^imagewize.nl$ [OR]
#RewriteCond %{HTTP_HOST} ^imagewize.com.com$
RewriteRule (.*)$ https://wpvilla.in/nl/$1 [R=301,L]

The only other solution would be to move to a dedicated or cloud environment. Looking into these options, but will stick to this VPS for now though I have issues with spikes in RAM due to scripts I am running every now and then for security and backups.