Roots Trellis: The WordPress Stack That Treats Environments Like Code

Ansible, Lima VMs, Nginx, and zero-downtime deploys combine into one opinionated system that keeps local development, staging, and production aligned.

8 min read • View on GitHub • More from roots

A wide editorial scene showing a developer laptop on the left and a production server rack on the right, with the same set of playbooks threading between them like a ledger. The image explains Trellis as one contract that governs local, staging, and production environments together.
One control plane, three environments. Trellis uses the same Ansible family to keep the laptop and the server stack in sync.
Key Takeaways

Trellis is compelling because it solves a problem bigger than setup. It turns WordPress infrastructure into a shared operating model, so the machine on a laptop, the staging box, and the production server all obey the same playbook family. That is a different promise from "easy hosting." It is parity as the product.

That matters because WordPress teams have spent years absorbing drift as normal. A local environment one way, a staging server another, production a third way. Trellis attacks that split directly: same Ansible structure, same role order, same deployment logic, different variables.

Why the Bedrock constraint matters

Trellis can be this opinionated because it is not trying to support every possible WordPress layout. It assumes Bedrock, which means it can expect a cleaner project structure, a `web/` document root, and a deployment model that looks like a real application instead of a pile of theme files. That constraint buys clarity everywhere else.

Trellis has removed support for Vagrant, VirtualBox, and Parallels for local development. Going forward, Lima VMs are the only supported option for running Trellis locally.

The same playbook family provisions every environment, while variables and optional roles change the outcome.

How one playbook becomes a whole stack

The spine is `server.yml`. It does not just install packages. It imposes an order: security first, then the database layer, then PHP, then Nginx, then optional services if the site needs them. That sequence is the point. It keeps servers lean and predictable instead of turning every host into a kitchen sink.

# Simplified structure of the provisioning spine
- import_role: { name: common }
- import_role: { name: ferm }
- import_role: { name: fail2ban }
- import_role: { name: mariadb }
- import_role: { name: php }
- import_role: { name: nginx }
- import_role: { name: letsencrypt }
- import_role: { name: memcached }
  when: sites_using_memcached | count > 0

That conditional logic is easy to miss, but it is a major design choice. If no site needs Memcached, Trellis does not install or manage it. The stack stays close to the app, not the other way around.

The Nginx and PHP layers are where the opinion shows up

A close-up mechanical scene of stacked release folders, a hand moving a lever labeled current from one release to the next, and a rollback path waiting beside it. The illustration explains Trellis deployment as a safe pointer switch rather than a file copy.
Deploys in Trellis behave like releases. The server switches pointers, not whole directories.

Trellis does not just install Nginx. It templates it. That matters because the config becomes part of the codebase, not a hand-edited artifact on a server. The same is true for PHP-FPM management, where Trellis can swap versions cleanly and keep the runtime aligned with the rest of the stack.

LayerGeneric hosting scriptTrellis
NginxManual, one-off configTemplated, role-driven config
PHPInstalled as a packageManaged as part of an ordered runtime
SecurityAdded after the factBuilt into provisioning order
ParityBest effortDesign goal

The best part is that Trellis makes these choices visible. You can inspect the templates, the role tasks, and the environment vars. It behaves like software because it is software.

Deploys that look like releases, not rsync

The deployment model is closer to Capistrano than to a file sync tool. Trellis creates timestamped release directories, writes the new code there, then moves a `current` symlink to point at the fresh release. That gives you a clean rollback story, because going back means repointing the symlink, not reconstructing the server state from scratch.

This is a small architectural choice with a big effect on operations. It makes deploys legible, rollback-safe, and easy to reason about under pressure. The server always has a previous release sitting there, ready.

Deployment modelWhat changes on the serverRollback story
rsync to live filesThe active directory is edited in placeMessy and partial
Trellis release deployA new release is prepared, then current is switchedSimple pointer change
Manual shell scriptsDepends on the script authorUsually bespoke

What Trellis is better than, and what it is not

Trellis wins when the goal is repeatable infrastructure with strong parity. It is better than Docker-only local stacks when the same code needs to drive local, staging, and production. It is better than legacy Vagrant workflows because the local VM story is now lighter and more modern. And it is better than ad hoc shell scripts because the behavior is encoded, reviewed, and reused.

But Trellis is not the right answer for every team. If someone wants a throwaway local WordPress sandbox, this is too much system for the job. Trellis is for teams that care about the shape of the environment as much as the code running inside it.

AlternativeStrengthTrade-off
Docker-only WordPressFast start, lightweightLocal convenience can outrun production parity
Legacy Vagrant provisioningFamiliar full VM modelSlower and more cumbersome
Ad hoc shell scriptsFlexible and quick to writeHard to audit, hard to repeat
TrellisShared model across environmentsOpinionated and narrower by design

The project’s evolution says a lot about WordPress

Trellis also reads like a record of WordPress infrastructure maturing. The shift from Vagrant to Lima is not just a tooling swap. It shows the community moving toward faster local environments, tighter provisioning logic, and a more realistic deployment model. Add HTTP/3 support, runtime hardening, Redis sessions, and the stack starts to look like a serious platform rather than a historical artifact.

That is the deeper story here. Trellis is what happens when WordPress stops being treated as a special case and starts being treated as an application with real operational needs.