WP Engine is our third WordPress hosting provider, alongside SpinupWP, Pressable, Kinsta, and Cloudways. Like Pressable and Kinsta, WP Engine has no server concept — every operation is addressed by an “install” name, not a server_id. Unlike Pressable, WP Engine does expose a real per-install SSH gateway, which this module uses for command execution and Companion installs. See Concepts → Server, Site, Care plan, Hosting tier for how the server-vs-no-server split reshapes the Server/Site relationship, and why CAP_SSH is still false for WP Engine despite that real SSH access existing.
[!TIP] Looking for Testers! Have a live WP Engine account? You can help test this integration! Follow our Contributing & Module Testing Guide to plug in credentials, verify endpoints, vibe code any fixes with Claude, and open a PR back.
Honesty about what’s confirmed here
This module has not yet been exercised against a live WP Engine account. Every endpoint path and response shape in WPEngineClient is built from WP Engine’s published API reference, not a real response. Two things in particular are flagged as genuine unknowns rather than confirmed behavior:
backups()’s response envelope — WP Engine’s docs describe a/installs/{id}/backupsresource, but whether results are flat or wrapped the same{previous, next, count, results}shapeinstalls()/domains()use is unconfirmed.- SSL certificates — no dedicated SSL endpoint appears in WP Engine’s published API reference at all.
sslCertificates()/requestSslCertificate()are this module’s best guess at where such a resource would live if/when exposed.WPEngineCheckdeliberately does not call these methods for its diagnostic probe, andWPEngineHostingProvider::supports(CAP_CERT_SYNC)currently returnstrueon the strength of the domains endpoint alone — treat cert-sync fidelity for WP Engine as unverified until this is checked against a real account.
Confirm both against a real install before leaning on them in production.
Setup
-
Mint an API User ID / Password pair at
my.wpengine.com/api_access— not the portal login, and not the per-install SSH keypair (see below). -
Generate (or reuse) an SSH keypair authorized against the install(s) you want command execution/Companion install for.
-
Set in
.env:CLOCKWORK_WPENGINE_API_USER_ID=... CLOCKWORK_WPENGINE_API_PASSWORD=... # Safe-by-default: Set to false only when you are ready to enable writes and Companion deployment CLOCKWORK_WPENGINE_VIEW_ONLY=true CLOCKWORK_WPENGINE_SSH_PRIVATE_KEY=... CLOCKWORK_WPENGINE_SSH_PRIVATE_KEY_PASSPHRASE=... # optional -
Test:
php artisan clockwork:wpengine-test
# Or using the standardized alias:
php artisan clockwork:test-wpengine
Displays operating mode (Full Access or View Only) and reports total accessible installs.
View-Only (Read-Only) Mode
WP Engine defaults to View-Only Mode (CLOCKWORK_WPENGINE_VIEW_ONLY=true) to safeguard unverified accounts and client-owned installs:
- Zero API Mutations: Any call to
POST,PUT, orDELETEthrows aWPEngineReadOnlyExceptionbefore sending HTTP requests. - Zero Remote Writes:
commandRunner()andcompanionInstaller()returnnull, preventing SSH command execution and Clockwork Companion mu-plugin deployment. - Gated Capabilities:
CAP_COMPANIONreportsfalse. Read-only install discovery, domain mapping, and cert monitoring operate normally. - Diagnostic Reporting: Diagnostics at
/settings/diagnosticsappend· Mode: View Only.
To enable write actions and Companion deployment on verified accounts, set:
CLOCKWORK_WPENGINE_VIEW_ONLY=false
Auth
Two independent credentials, not one:
- REST API: HTTP Basic, using the API User ID/Password pair above.
- SSH: key-based only (no password fallback) against
{install}@{install}.ssh.wpengine.net:22, viaModules\Core\Support\SshConnector— the same generic,Server-independent SSH primitive Kinsta’s module uses, built specifically because WP Engine/Kinsta sites have noServerrow forApp\Services\Ssh\SshClientto hang off of (confirmed by reading that class’sconnect(Server $server)signature).
Endpoints we call
Base URL https://api.wpengine.com/v1.
| Method | Path | Purpose |
|---|---|---|
| GET | /installs |
Paginated install listing. WPEngineCheck’s probe (limit=1). |
| GET | /installs/{id} |
Single install detail. |
| GET | /installs/{id}/domains |
Domains attached to an install. |
| GET | /installs/{id}/backups |
Backup history — envelope shape unconfirmed, see above. Not wired into any report command yet. |
| GET | /installs/{id}/ssl_certificates |
Best-guess path — no confirmed SSL endpoint exists in WP Engine’s docs. |
| POST | /installs/{id}/ssl_certificates |
Request a Let’s Encrypt cert — same caveat. |
| POST | /ssh_keys |
Register an SSH public key account-wide. Not called automatically by anything in this module — implemented for future/manual use only. |
Files
modules/WPEngine/src/WPEngineClient.php— the REST client (Basic Auth, install listing/detail/domains/backups/SSL).modules/WPEngine/src/WPEngineReadOnlyException.php— thrown when mutating operations are attempted in View-Only mode.modules/WPEngine/src/Commands/WPEngineTest.php(app/Console/Commands/WPEngineTest.php) — verification CLI command (clockwork:wpengine-test/clockwork:test-wpengine).modules/WPEngine/src/WPEngineSshCommandRunner.php—Modules\Core\Contracts\SiteCommandRunneradapter over real per-install SSH viaSshConnector. Key-based auth only; throws ifwpengine_install_nameis empty or no private key is configured.modules/WPEngine/src/WPEngineCompanionInstaller.php— installs the Companion mu-plugin over that same SSH transport: tarball extract,wp-cliDB-query upsert of the shared secret, cache flush — mirroringApp\Services\Companion\CompanionInstaller’s approach but without the sudo/site_userwrapping SpinupWP needs. Assumes the WP root issites/{install}relative to the SSH landing directory — flagged as needing live confirmation.modules/WPEngine/src/WPEngineHostingProvider.php— theHostingProvideradapter: capabilities (CAP_SSHandCAP_SERVER_LINKAGEbothfalse— see Concepts for why that holds even though real SSH exists), credential fields, diagnostics check.panelUrl()returnsnull(no confirmed My WP Engine deep-link pattern).modules/WPEngine/src/WPEngineCheck.php— diagnostics probe (GET /installs,limit=1).modules/WPEngine/src/WPEngineServiceProvider.php— registers the client/SSH-runner/Companion-installer bindings, manifest,HostingProvider, and diagnostics check.- Config:
config/clockwork.php→wpenginekey. - Site identifier:
sites.wpengine_install_name(unique, nullable) — see the2026_09_03_014554_add_wpengine_kinsta_cloudways_fields_to_sitesmigration.
