WordPress
WordPress is a site type, not a plugin. The database, the salts, the admin user, permalinks, HTTPS and a real cron entry are all part of creating one.
Installing
klyrn site create example.com --type wordpress \
--title "Example" --admin-user editor --admin-email you@example.com
Creating it does all of this in one job:
- The database and its own user, granted on that database only, from localhost.
wp-config.phpwith fresh salts and awp_table prefix.- The admin user. Credentials are stored encrypted; revealing them is audited.
- Permalinks and the HTTPS site address.
DISABLE_WP_CRON, replaced by a real cron entry running every five minutes as the account user. WP-Cron that only fires when somebody visits is not a scheduler.FS_METHODset todirect, so WordPress never asks for FTP credentials to update itself.- A Let's Encrypt certificate, if DNS points here.
Everything WordPress-facing runs through WP-CLI 2.12.0, pinned by SHA-512 and executed as
the site's Unix user, never as root, and never by splicing PHP into
wp-config.php.
Health signals
klyrn wp health example.com
Ten deterministic signals, each either fine or specific. There is no score out of a
hundred: a number that mixes an outdated plugin with a world-readable
wp-config.php is a number that hides the second one.
| Signal | What it means | Named fix |
|---|---|---|
| core | WordPress version. A pending minor update is critical; a major one is attention. | None |
| database | The database answers and belongs to this site. | None |
| addresses | Site address, home address and the certificate that covers them. | None |
| php | PHP branch against its security-support end date. Past it is critical; under 180 days is attention. | None |
| debug | Debug output reaching visitors. | disable-debug |
| cron | Scheduled events, counting those more than ten minutes overdue. | None |
| wp-config | Permissions on the file that holds the database password. World-readable or group-writable is critical. | fix-wp-config-permissions |
| files | Files under the document root that anyone can write to. | repair-file-permissions |
| file-editor | The dashboard's plugin and theme editor, which turns a stolen password into code execution. | disable-file-editor |
| checksums | Core files against WordPress's published checksums. | None |
The report reads exactly six constants out of wp-config.php. The rest of that
file is the database password and eight authentication salts, and there is no reason for
them to be in this process's memory.
Hardening
klyrn wp harden example.com disable-file-editor
klyrn wp harden example.com disable-debug
klyrn wp harden example.com fix-wp-config-permissions
klyrn wp harden example.com repair-file-permissions
Four actions, and nothing else is accepted. Each is narrow enough to describe in one sentence:
disable-file-editor- Sets
DISALLOW_FILE_EDIT. disable-debug- Sets
WP_DEBUG,WP_DEBUG_DISPLAYandWP_DEBUG_LOGto false. An existingdebug.logis left where it is: deleting a customer's file is not hardening. fix-wp-config-permissions- Mode 0640, owned by the account, and inherited POSIX ACL entries stripped. Reports that nothing changed when nothing needed to.
repair-file-permissions- Clears the other-write bit under the document root. Nothing becomes more readable and no owner changes.
Updates and the policy
klyrn site wp example.com status
klyrn site wp example.com update all # backs up first
klyrn site wp example.com update core --no-backup
klyrn wp policy example.com --core minor --plugins all --themes manual
klyrn wp policy example.com --plugins selected --select-plugins woocommerce,akismet
klyrn wp policy run example.com
Core takes manual, minor or all. Plugins and themes
take manual, selected or all; selected
with an empty list is refused. The default for a new site is core minor,
plugins and themes manual.
The automatic pass runs at most once every 24 hours per site, and only between 02:00 and 06:00 server local time. It backs the site up first unless you turn that off, applies what is due, then fetches the site through nginx and reads the status code: anything that is not a 2xx or 3xx fails the job.
KLYRN does not roll a WordPress update back. A plugin update that broke the site cannot be undone by reversing a version number: the database may already have been migrated. When the verify step fails, the message names the pre-update backup, or says plainly that none was taken, if you turned it off.
Cloning and search-replace
klyrn wp clone example.com copy.example.com
klyrn wp clone example.com copy.example.com --account otheraccount
A clone is an independent site: its own files, its own database with its own user and its own password, its own certificate, and no relationship to the original. It remembers nothing and there is no path to push it back: that is staging, which is a different thing.
Cloning across accounts is done by root with an explicit ownership change, because
/home/<account> is 0710 and hosting accounts share no
group. The isolation is not relaxed to make the copy easier.
klyrn wp replace example.com http://old.example.com https://example.com
klyrn wp replace example.com http://old.example.com https://example.com --apply
Search and replace is a dry run by default and reports what would change.
Applying requires typing the site's own domain to confirm. It runs through WP-CLI with
--precise and --all-tables, so serialised PHP survives, and it
skips post GUIDs unless you pass --include-guids: rewriting those makes
every feed reader treat every post as new.
The search term must be at least 3 and at most 2000 characters, may not equal the
replacement, and may not start with -, which WP-CLI would read as one of its
own options.