Highlights
- Complete WordPress 7.x core. New and restored WordPress sites get a complete core, checked with
wp core verify-checksums, and existing WordPress 7.x sites with truncated core files are repaired on upgrade (site-type-wp#241, site-command#504). - Failed Let's Encrypt alias changes roll back. When a certificate can't be issued for new alias domains, the aliases, certificate and redirect files stay as they were and the command exits with an error, instead of reporting success and revoking the certificate still in use (site-command#505).
ee site ssl-verifyno longer breaks the proxy. A request on an already-finalized order could deploy a certificate next to a new key that didn't match it, which stopped nginx-proxy reloads for all sites. The previous key is now kept when a request fails, and a certificate that doesn't match its key is never deployed (site-command#506).- More reliable SSL handling. Custom certificates are validated and installed on
ee site update --ssl=custom, stale ACME orders are rebuilt on retry, concurrent SSL commands no longer race, and warnings now show the actual Let's Encrypt error (site-command#489, site-command#492, site-command#493, site-command#498, site-command#486). - Safer site creation. In the rare case where two site names map to the same database name or volume prefix, a failed create no longer removes the other site's database, user or volumes (site-command#503, site-type-wp#240, site-type-php#115).
- IP whitelist and cron fixes. An invalid CIDR prefix in
ee auth --ipis rejected instead of stopping proxy reloads (auth-command#59), and the cron scheduler no longer restarts in a loop when there are no cron jobs (cron-command#60). - Updated images: PHP 8.3.35, Redis 8.10.2, postfix on Debian 13.7 and newrelic-daemon on Alpine 3.24.2.
Upgrade notes
Cron jobs saved with ee cron update run on their intended schedule
ee cron update stored a five-field schedule without the seconds field, so it was read as a six-field one: * * * * * ran every second instead of once a minute. The scheduler config is regenerated on upgrade, so these jobs now fire on their intended schedule (cron-command#60).
IP whitelist entries are checked and cleaned up
ee auth create --ip lists are now split on any whitespace or comma, and a repeated IP is stored once. Entries with an invalid CIDR prefix (such as 192.0.2.1/abc, /99 or an IPv6 prefix over 128) are refused. On upgrade, a migration removes invalid entries from existing whitelist files and normalizes the ones nginx accepts (such as 10.0.0.0/08). The database rows are kept; an invalid one is skipped with a warning that names the command to remove it (auth-command#59).
WordPress 7.x sites with truncated core files are repaired
On upgrade, a migration runs wp core verify-checksums on each WordPress site that has wp-includes/php-ai-client/, and repairs the truncated core files in place. Content and database are not touched. Disabled or stopped sites, and sites that can't be checked, get a warning with the command to check them later (site-type-wp#241).
Colliding site names
Existing sites, including pairs that already share a database name or volume prefix, are left as they are. New creates that would collide are refused: a site whose volume prefix or compose project another site uses, or a --dbname/--dbuser that is already taken. A default database name that is already taken gets a _2 (then _3, …) suffix (site-command#503).
Let's Encrypt needs a valid le-mail
Issuing or renewing a Let's Encrypt certificate now stops with a clear error when le-mail is empty or not a valid address, including the nightly ssl-renew --all. Check it with ee config get le-mail and set it with ee config set le-mail <email> if needed (site-command#496).
WordPress and PHP sites get new images
Every WordPress and PHP site is recreated on the new postfix image during the upgrade, and sites on PHP 8.3 also move to PHP 8.3.35. Expect a short interruption per site.
Fixes
SSL and Let's Encrypt
- A failed Let's Encrypt alias change restores the certificate, ACME and redirect files, keeps the aliases unchanged and exits non-zero. Only certificates that an alias change actually replaced are revoked (site-command#505).
ee site update --ssl=lefails when no certificate was issued, andee site ssl-renew <site>exits non-zero when the renewal fails. A failure inee site update --ssl=…puts the site back to HTTP-only before anything is saved (site-command#505).- A site's certificate and ACME files, including those of its aliases, are removed on
ee site deleteand--ssl=off, also for wildcard sites.--ssl=offis refused while other sites inherit the certificate, works on sites stored as wildcard, and a self-signed site can turn SSL back on afterwards (site-command#505). - Certificates without a subject CN are parsed, and ACME challenge types EasyEngine can't solve no longer break certificate orders (site-command#505).
- When a first certificate request fails, the previous key is restored, and a 403 from Let's Encrypt gives a warning with its reason instead of a PHP fatal error. Certificate keys are no longer written to
ee.logwhen a request fails (site-command#506). ee site update --ssl=customnow copies the certificate and key; before, it turned on HTTPS without them (site-command#489).- Custom certificates are checked before install: an invalid PEM file, a broken chain or a key that doesn't match the certificate is refused, and an expired certificate or one expiring within 30 days gives a warning (site-command#492).
ee site ssl-verifyis refused on sites without Let's Encrypt SSL, so it can no longer replace a custom certificate. On a site without SSL it points toee site update <site> --ssl=le(site-command#487).ee site ssl-verifyrebuilds a stored ACME order that has expired or failed, instead of failing on every retry (site-command#493).- Certificates are copied to nginx-proxy through temporary files, so a failed copy no longer leaves a mismatched key and certificate. The file permissions are kept on renewal (site-command#491).
- SSL commands wait for each other: a second one waits up to 120 seconds (600 for
ssl-renew) and then stops with a clear message (site-command#498). le-mailis validated before registering with Let's Encrypt, and renewals use the currentle-mail(site-command#496, site-command#497).- SSL warnings include the Let's Encrypt error, and the misleading "Challenge Authorization failed" line is gone from renewal failures (site-command#486). The renewal message now says "less than 35 days", matching the actual threshold (site-command#485).
ssl-renew --allpauses 1–5 seconds between due renewals, reports Let's Encrypt rate limits as such, and carries on with the next site when one is rate-limited (site-command#499).- A warning is shown when the Let's Encrypt account key is missing while certificates issued under it still exist, instead of silently creating a new account (site-command#500).
- Self-signed certificate generation quotes the site name and file paths it passes to
openssl(site-command#495). - The SSL flag migration no longer marks sites with custom, self-signed or inherited SSL as Let's Encrypt, on installs that still have to run it (site-command#490).
Proxy
- A proxy cache update that fails keeps a valid nginx-proxy config: the files it wrote are restored, and the config test is retried once (site-command#505).
- Alias changes reload nginx-proxy instead of restarting it, and sites without SSL stay HTTP-only when their aliases change (site-command#505).
- After a site is deleted, nginx-proxy is reloaded, so its
www.redirect stops working right away (site-command#505).
Sites and data safety
- A failed
ee site createremoves only the database and user it created itself (site-command#503, site-type-wp#240, site-type-php#115). - An interrupted create (for example Ctrl+C) removes the database, user and webroot it had just created, and an early failure keeps a site directory that already existed (site-type-wp#240, site-type-php#115).
ee site deletekeeps a database or user that another site still uses (site-command#503).- A new site's database user is granted only its own database. Existing sites keep their current grants (site-command#503).
- Database names and passwords with quotes,
$or backticks work (site-command#503). - When
eeruns on PHP 8.5, a site create that stops with a PHP fatal error is rolled back again; before, it left its containers, database and files behind (site-command#507).
WordPress core download
ee site create --type=wpdownloads WordPress core without truncated file names and checks it withwp core verify-checksums. A failed download now stops the create and cleans up, instead of carrying on without core (site-type-wp#241).ee site restorerestores WordPress core the same way, and keeps the old core if the new one can't be extracted (site-command#504).
Auth whitelist
- The whole whitelist entry is validated, including its CIDR prefix, and the error names the bad entry. Before, an invalid prefix was written to the whitelist file and stopped every later nginx-proxy reload (auth-command#59).
- A repeated IP in one
--iplist no longer fails with a database error (auth-command#59).
Cron
- With no cron jobs, the scheduler stays running instead of restarting in a loop, and
ee cron deleteno longer removes the cron container when the last job is deleted (cron-command#60). - Schedules are validated the same way on create and update, and
ee cron updaterejects unknown ids and checks--sitelike create (cron-command#60). - Host cron jobs no longer get a user, which stopped the scheduler.
--useris refused for host jobs, andee cron list hostandee cron list --alllist host jobs without a user instead of failing (cron-command#60). - A stored job the scheduler can't read is left out of its config with a warning, instead of stopping every job (cron-command#60).
Core
eeno longer hangs when a command it runs writes a lot of output to stderr (easyengine#1939).
Docker image updates
All new images are tagged v4.13.1 (dockerfiles v4.13.1, matching the core version).
| Image | 4.13.0 tag | 4.13.1 tag | Upstream change | PR |
|---|---|---|---|---|
| easyengine/php8.3 | v4.13.0 | v4.13.1 | PHP 8.3.33 → 8.3.35 | #361 |
| easyengine/redis | v4.13.0 | v4.13.1 | Redis 8.10.1 → 8.10.2 | #358 |
| easyengine/postfix | v4.13.0 | v4.13.1 | Debian 13.6 → 13.7 (slim) | #357 |
| easyengine/newrelic-daemon | v4.11.1 | v4.13.1 | Alpine 3.24.1 → 3.24.2 | #359 |
Unchanged in this release: nginx-proxy v4.13.0, nginx v4.11.0, cron v4.11.0, mariadb v4.9.1, mailhog v4.6.5, php8.1/8.2/8.4/8.5 v4.13.0, php7.4/8.0 v4.13.0, php5.6–7.3 v4.7.4, php (stable) v4.6.6.
Package versions
All tagged. Semver follows the Conventional Commit types of the merged PRs.
| Component | 4.13.0 | 4.13.1 | Why |
|---|---|---|---|
| easyengine (core) | 4.13.0 | 4.13.1 | fixes in bundled packages and images, and the process fix (easyengine#1939) |
| dockerfiles | v4.13.0 | v4.13.1 (tagged) | base image bumps (PHP 8.3, redis, postfix, newrelic-daemon) |
| site-command | v3.8.0 | v3.8.1 (tagged) | fixes: 14 SSL and Let's Encrypt PRs (site-command#485–#500) and site-command#503–#507 |
| site-type-wp | v1.11.0 | v1.12.0 (tagged) | fix(create) (site-type-wp#240) + fix(core) (site-type-wp#241); minor bump because it now requires site-command v3.8.1
|
| site-type-php | v1.11.0 | v1.12.0 (tagged) | fix(create) (site-type-php#115); minor bump because it now requires site-command v3.8.1
|
| auth-command | v1.3.1 | v1.3.2 (tagged) | fix(auth) (auth-command#59)
|
| cron-command | v2.1.0 | v2.1.1 (tagged) | fix(cron) (cron-command#60)
|
| admin-tools, config, dash, log, mailhog, service, shell | unchanged | unchanged | no changes since their pinned tags |
Contributors
What's Changed
easyengine
- build(composer): ignore the flysystem 1.x path-normalizer advisory #1941 @mrrobot47
- chore(release): prepare v4.13.1 #1940 @mrrobot47
- fix(process): read stdout and stderr together so large output can't deadlock #1939 @mrrobot47
site-command
- fix(ssl): keep the served key when a first certificate request fails EasyEngine/site-command#506 @mrrobot47
- fix(site): keep proxy and SSL state consistent when an update fails EasyEngine/site-command#505 @mrrobot47
- fix(site): keep the fatal-error rollback working on PHP 8.5 EasyEngine/site-command#507 @mrrobot47
- fix(restore): restore WordPress core without truncated files EasyEngine/site-command#504 @mrrobot47
- fix(site): never drop another site's database, user or volumes on a failed create EasyEngine/site-command#503 @mrrobot47
- fix(ssl): warn when the letsencrypt account key is missing but cert state exists EasyEngine/site-command#500 @mrrobot47
- feat(ssl): add inter-site jitter and clear rate-limit messaging to ssl-renew EasyEngine/site-command#499 @mrrobot47
- fix(ssl): serialize ssl operations with a process-wide file lock EasyEngine/site-command#498 @mrrobot47
- fix(ssl): honor updated le-mail on certificate renewal EasyEngine/site-command#497 @mrrobot47
- fix(ssl): validate le-mail before letsencrypt registration EasyEngine/site-command#496 @mrrobot47
- fix(ssl): prevent shell injection via site name in self-signed cert generation EasyEngine/site-command#495 @mrrobot47
- fix(ssl): detect and rebuild stale ACME orders on verify/retry EasyEngine/site-command#493 @mrrobot47
- fix(ssl): deploy nginx-proxy certs atomically with checked copies EasyEngine/site-command#491 @mrrobot47
- fix(migration): don't reclassify custom ssl sites as letsencrypt EasyEngine/site-command#490 @mrrobot47
- fix(ssl): copy and validate custom certs on site update EasyEngine/site-command#489 @mrrobot47
- fix(ssl): validate custom certificate and key before install EasyEngine/site-command#492 @mrrobot47
- fix(ssl): block ssl-verify on non-letsencrypt sites EasyEngine/site-command#487 @mrrobot47
- fix(ssl): include ACME error message in operator-facing warnings EasyEngine/site-command#486 @mrrobot47
- fix(ssl): correct misleading renewal-threshold log message EasyEngine/site-command#485 @mrrobot47
site-type-wp
- fix(core): download WordPress core without truncated file names EasyEngine/site-type-wp#241 @mrrobot47
- fix(create): roll back only the database and user this create made EasyEngine/site-type-wp#240 @mrrobot47
site-type-php
- fix(create): roll back only the database and user this create made EasyEngine/site-type-php#115 @mrrobot47
auth-command
- fix(auth): validate the whole whitelist entry, including its CIDR prefix EasyEngine/auth-command#59 @mrrobot47
cron-command
- fix(cron): keep the scheduler running and validate cron jobs EasyEngine/cron-command#60 @mrrobot47
dockerfiles
- chore(deps): bump php to 8.3.35 in /php/8.3 EasyEngine/dockerfiles#361 @mrrobot47
- chore(deps): bump alpine from 3.24.1 to 3.24.2 in /newrelic-daemon EasyEngine/dockerfiles#359 @dependabot
- chore(deps): bump debian from 13.6-slim to 13.7-slim in /postfix EasyEngine/dockerfiles#357 @dependabot
- chore(deps): bump redis from 8.10.1 to 8.10.2 in /redis EasyEngine/dockerfiles#358 @dependabot