Simplifying Trellis

It’s easy to get comfortable using a project. Especially one that you’ve worked on and helped to create. Which is why it’s even easier to lose the perspective of a new user.

Here’s what the default config looked like for a WordPress site in Trellis as of ~3 days ago:

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

That’s a lot of settings. There’s nested settings. There’s settings that aren’t even in this file and comments pointing you somewhere else. And there’s some not-so great comments trying to explain settings.

What’s even worse is only a few of those settings are even required for a new user. All of this led me to re-evaluate our site config and make sure it was as simple as possible.

Slimmer config

Here’s what the new default (development) config looks like now:

wordpress_sites:
  example.com:
    site_hosts:
      - example.dev
    local_path: ../site # path targeting local Bedrock site directory (relative to Ansible root)
    admin_email: admin@example.dev
    multisite:
      enabled: false
    ssl:
      enabled: false
      provider: self-signed
    cache:
      enabled: false

A lot of hard work went into this. Making things simpler is often hard. A few of these settings were just removed since we already had defaults. But most of them required thought (and code) to intelligently set proper defaults.

Examples

Let’s use site_hosts, wp_home, and wp_siteurl as an example with our own site https://roots.io in the old-style config:

wordpress_sites:
  roots.io:
    site_hosts:
      - roots.io
    multisite:
      enabled: false
    ssl:
      enabled: true
      provider: letsencrypt
    cache:
      enabled: false
    env:
      wp_home: https://roots.io
      wp_siteurl: https://roots.io/wp

When configuring this site, you’d need to set site_hosts first. Then you’d have to remember to also update wp_home and wp_siteurl while remembering 1) the correct protocol, 2) the correct URLs and which one is which with /wp. And you’d have to ensure all of these 3 are consistent.

We eliminated the need for this by setting a good-enough default:

wp_home: "{{ item.value.ssl.enabled | default(false) | ternary('https', 'http') }}://${HTTP_HOST}"
wp_siteurl: "${WP_HOME}/wp"

Trellis automatically detects if you have SSL enabled or not and sets the correct protocol based on that. Then we take advantage of PHP’s HTTP_HOST constant and re-use wp_home in the wp_siteurl definition.

Another example is db_name and db_user. We always documented and recommended the use of the site name for these values. So if your site is named roots.io then it makes sense to have a database called roots_io_production and a user called roots_io (MySQL doesn’t like dots).

A new user had to name their site and then remember to also consistently set those two options which had a few problems:

  1. Unnecessary work
  2. Possible typos/inconsistencies
  3. Skipping this configuration leading to generic database/user names
  4. Bugs we hadn’t accounted for

The solution is the same as before: provide a smart default. We already know the site name, so we use that to define these values:

db_name: "{{ item.key | underscore }}_{{ env }}"
db_user: "{{ item.key | underscore }}"

Note: item.key in this case is just roots.io

Details

If you’re interested in some of the work that went into this, there’s 3 main Pull Requests:

Defaults

Remember that these are defaults. They can always be defined by the end-user which will override the default. This also makes the upgrade path seamless because existing Trellis users will still have the values defined in their configs. In this case, the defaults are skipped and don’t apply.

Documentation

In addition to simplifying Trellis itself, our documentation has gotten a lot of improvements. Trellis is built around the concept of "WordPress Sites" and now all those settings are documented on their own page.

Previously they were mixed together in the Local Development Setup docs which was confusing. Now "Local Development Setup" is simpler and separated.

The Remote Server Setup has also been cleaned up and improved by explaining the concepts of Provision and Deploy which are the key to understanding Trellis (and Ansible).

Hopefully all of this leads to a much better experience for new users coming to Trellis.

Read the discussion on our Discourse

Get our latest updates & occasional tips on building better WordPress sites

Follow @rootswp on Twitter