# What's New in Trellis: March 2026

Two new Trellis releases have shipped: [v1.28.0](https://github.com/roots/trellis/releases/tag/v1.28.0) and [v1.29.0](https://github.com/roots/trellis/releases/tag/v1.29.0). These releases focus on security hardening and performance.

## HTTP/3 support

Trellis now supports HTTP/3 out of the box. When enabled, nginx listens on UDP/443 for QUIC alongside the existing TCP/443 for HTTP/1 and HTTP/2, and sends the required `Alt-Svc` header to advertise HTTP/3 availability to browsers.

The OS firewall (ferm) is automatically configured to allow inbound UDP/443. If you're behind a cloud firewall (DigitalOcean, Hetzner, etc.), you'll need to allow UDP/443 there as well.

HTTP/3 is [supported by all major browsers](https://caniuse.com/http3) and offers reduced connection latency thanks to QUIC's built-in TLS 1.3 handshake.

## WordPress runtime hardening

A new opt-in hardening mode lets you run PHP-FPM under a separate runtime identity from the deploy user. When `wordpress_runtime_hardened` is enabled, PHP-FPM runs as a configurable user/group and only explicitly allowlisted paths are writable.

```
wordpress_runtime_hardened: true
wordpress_runtime_user: php-app
wordpress_runtime_group: php-app
wordpress_runtime_writable_paths:
  - shared/uploads
  - current/web/app/cache

```

Per-site overrides are supported via `wordpress_sites.<site>.runtime_writable_paths`. The runtime user/group must exist on the target host — define them in your users config and Trellis will validate with `getent` checks during provisioning.

Existing behavior is completely unchanged by default.

## Redis PHP session storage

Building on existing Memcached session support, Trellis now supports storing PHP sessions in Redis. Sessions use Redis database 1 by default to stay separate from the object cache on database 0.

## Ansible 2.19 support

Trellis is now compatible with Ansible 2.19, including fixes for implicit boolean conversions in templates, `become` inheritance in handlers, and updated handling of undefined values.

## Security and plugin hardening

Two security-focused changes landed in v1.28.0:

- **HTTP response splitting fix**: The multisite subdirectory rewrite rule now uses `$request_uri` instead of `$uri` to prevent CRLF injection in `Location` headers.
- **Plugin file access denied**: `.txt` and `.md` files inside plugin directories are now blocked by nginx. These files (like `README.txt` and `CHANGELOG.md`) expose version information that attackers use to identify known vulnerabilities.

## FastCGI cache fixes

Two fixes address longstanding caching issues:

- **Redirect caching**: `fastcgi_cache_valid` is now scoped to `200` responses only, preventing nginx from caching 301/302 redirects that caused redirect loops.
- **Stale content on unpublish**: The default `fastcgi_cache_use_stale` no longer includes `updating`, so nginx serves fresh responses instead of stale cached content when pages are unpublished. To restore the previous stale-while-revalidate behavior, set `nginx_cache_use_stale: updating error timeout invalid_header http_500`.

## Other changes

- Default git branch for WordPress sites is now `main` instead of `master`.
- `sudo` is now used as the default become method.
- `cli_ask_pass` default is now set in the Users role.
- Fixed Redis object cache password not being passed to the WordPress environment.