Security¶
The noise floor is absorbed before it reaches PHP¶
Vulnerability scanners, exploitation frameworks, credential-stuffing tools and header-injection probes (Shellshock-style payloads stuffed into the User-Agent header itself) are refused at nginx with a closed connection — a scanner costs microseconds instead of a PHP worker and a database round trip. Referrer-spam domains are blocked by default too.
AI-training crawlers (GPTBot, CCBot, ClaudeBot, Bytespider...) and SEO/backlink crawlers (AhrefsBot, SemrushBot, MJ12bot...) can be blocked with:
sudo ngxsetup config set block_scraper_bots true
sudo ngxsetup tune --apply
Off by default, since unlike the rest of this list nothing there is attacking the site; it's a content-policy choice about who gets to crawl it for free, not a security one.
Restricting admin access¶
sudo ngxsetup config set admin_allow_list 203.0.113.4,198.51.100.0/24
sudo ngxsetup config set block_xmlrpc true
sudo ngxsetup tune --apply
admin_allow_list restricts /wp-admin and /wp-login.php to those
addresses on every site — credential stuffing then never reaches
WordPress.
Site isolation¶
Each site runs as its own system user with no shell, in its own
PHP-FPM service, inside its own kernel-enforced mount namespace — a
compromised plugin on one site cannot read another site's
wp-config.php, because from inside its namespace the other site does
not exist. See Architecture → Site isolation
for the full mechanism and why it's namespaces rather than a chroot.
secure¶
sudo ngxsetup secure # firewall (ufw), fail2ban, automatic security updates
sudo ngxsetup secure --apply
Malware scanning¶
ngxsetup security scan example.com # one site
ngxsetup security scan # every WordPress site on the box
Four layers, each independent so the absence of one degrades rather than disables the scan:
- wp-cli checksum verification — an exact byte comparison of core and wordpress.org-hosted plugin files against the checksums wordpress.org itself publishes for that exact version. No signature database, no false positives. Plugins not hosted there (premium, custom) are reported as uncheckable, not silently treated as clean.
- ClamAV, if installed (
ngxsetup security install-clamav, orapt install clamav-daemon) — a real, actively maintained open-source malware signature database. This project vendors nothing here on purpose. - YARA, if installed (
apt install yara) — pattern-based detection against a bundled ruleset targeting common PHP webshell and obfuscation techniques. Point--yara-rules <dir>(orconfig set security_yara_rules_dir <dir>) at a larger, separately maintained ruleset to supplement the bundled one. - Built-in heuristics — always runs; the fallback when nothing
else is installed. Regex patterns for the well-documented shapes of
obfuscated PHP malware (
eval(base64_decode(...))chains, raw request input reachingeval/system/exec, the deprecatedpreg_replace/emodifier, known webshell self-identification strings, PHP files insidewp-content/uploads, disguised double file extensions).
The report also lists administrator accounts on each site, so an account nobody remembers creating is easy to spot — planting one is a common way a compromise persists that no file-integrity check would ever see.
wp-cli always runs as the target site's own system user
(runuser -u web-<slug>), never as root — the same isolation boundary
site creation already relies on, so auditing a site cannot itself
become a way to reach every other site on the box.
Patching¶
ngxsetup security patch example.com # one site, asks before applying
ngxsetup security patch --yes # every site, no confirmation (cron-friendly)
Shows exactly what would update — core, plugins, themes — before touching anything, and updates core first, then plugins, then themes. One item failing does not stop the rest of the plan from being attempted — an operator who approved five updates should get four applied, not zero because the first one failed.
phpMyAdmin¶
Disabled by default. It is an internet-facing application with full database access, so enabling it requires saying who may reach it — see Getting started → phpMyAdmin.
Backups as a security control¶
An off-box, encrypted backup is the thing standing between a compromise and total data loss. See Backups.