Security
Lumber Mill ships a set of must-use plugins that harden WordPress out of the box.
They live in web/app/mu-plugins as instance-* files, load on every request, and cannot be deactivated from the admin.
Each of them is a plain file with hooks in it — read it, change it, delete it. The pages below explain what each one does and why, so you can tell whether a rule belongs on your project.
What Is Included
Section titled “What Is Included”| Plugin | Does | Documented in |
|---|---|---|
instance-login-limiter | Locks out repeated failed logins per address, released only over WP-CLI | Login Limiter |
instance-security-hardening | Blocks user enumeration, stops the login form naming which half of the credentials was wrong | Hardening |
instance-security-headers | Sends a baseline set of security headers on every response | Hardening |
instance-disable-rest-api | Unregisters the core REST namespaces and their discovery links | Hardening |
instance-force-active-plugins | Keeps security critical plugins active and undeactivatable | Two Factor |
instance-wp-2fa-key-guard | Refuses to run WP 2FA unless its encryption key comes from the environment | Two Factor |
instance-audit-log | Writes security relevant actions to the PHP error log or syslog as JSON lines | Audit Log |
instance-simple-history-config | Retention and capability defaults for the in-admin activity log | Audit Log |
Environments
Section titled “Environments”Two of these behave differently per environment, so local work does not need a second factor or a password reset after three typos.
| Feature | development | staging | production |
|---|---|---|---|
| Login limiter | ❌ | ✅ | ✅ |
| Forced 2FA | ❌ | ✅ | ✅ |
| Hardening, headers, REST, audit log | ✅ | ✅ | ✅ |
Both read WP_ENV, which is set from .env.
The exempt list is a filter in each plugin, so add local to it if that environment is in use on your project.
Where Things Are Configured
Section titled “Where Things Are Configured”-
.env— secrets and per-server values:WP2FA_ENCRYPT_KEY,INSTANCE_LOGIN_LIMITER_ALLOWLIST. -
config/application.php— turns those variables into constants. -
Filters in your theme — behaviour: thresholds, header values, which REST namespaces stay registered. Every plugin exposes filters rather than settings screens, so the configuration lives in version control.

