How to Harden a WordPress Site: A Practical Security Checklist
A hands-on WordPress hardening workflow covering accounts, wp-config.php, file permissions, salt rotation, plugin hygiene and monitoring, grounded in official documentation.
Security is risk reduction, not a checkbox
The official WordPress hardening guide opens with a point that is worth internalizing before you touch a single setting: security is about risk reduction, not risk elimination. There is no plugin that makes a site “safe”, and a stack of security tools cannot compensate for an unpatched core, a reused admin password, or a hosting stack nobody has looked at in two years. What you can do is raise the cost of attacking your site, layer defenses so that one failure does not become a full compromise, and keep the ability to recover when something does go wrong.
This article walks through the hardening measures that matter on a typical self-hosted WordPress site, roughly in the order we apply them when we take over maintenance for a client. Every recommendation traces back to the official documentation linked above, so you can verify the details against the source rather than trusting a random tutorial from 2019.
Start with accounts, not plugins
Most successful WordPress compromises start with a credential, not with an exotic exploit. Before you install anything, fix the account layer:
- No generic usernames. The official guide calls out
adminandwebmasterby name. If an account with an obvious username exists on your site, create a new administrator with a non-obvious name, log in as that user, and delete the old one after reassigning its content. - Long, generated passwords. Use the password generator and the built-in strength meter. Dictionary words, birthdays and company names are out. Store credentials in a password manager, not in a text file or a browser-synced note.
- Two-step authentication. Enable it for every account that can log in to wp-admin, not just your own. An editor account is a perfectly good foothold for an attacker.
- The fewest accounts that work. Editors who left two years ago, administrator accounts created “temporarily” for a freelancer, unused author profiles — audit them and remove what you do not need. Delete rather than deactivate whenever the account has no content attached to it.
- Least privilege. Give each person the lowest role that lets them do their job. Most content contributors never need anything beyond Author or Editor.
One point from the official documentation that is easy to overlook: your own computer is part of the attack surface. A keylogger on the laptop you administer from defeats every server-side measure on this page, so keep your operating system and browser patched too.
Make wp-admin a harder door
The login screen is public by design, so treat it as a door you harden rather than hide. The official guide suggests adding a second authentication layer in front of wp-admin, such as HTTP Basic Auth at the web server level. One caveat it also mentions: naive Basic Auth rules can break admin-ajax.php, which front-end plugins and themes use for anonymous requests. If you go this route, exclude admin-ajax.php from the protection or test your checkout and forms carefully afterwards.
Two further measures that cost almost nothing:
- Serve the admin over HTTPS. Administration credentials and session cookies should never travel over plain HTTP. If the whole site is not on HTTPS yet, at minimum force SSL for logins and the admin area.
- Use SFTP, not FTP. Plain FTP sends credentials across the network unencrypted. Most hosts offer SFTP on the same account; there is rarely a reason to keep the old protocol enabled.
Tighten wp-config.php
wp-config.php holds your database credentials and authentication keys, which makes it the single most sensitive file in the installation. Three measures from the official documentation:
Disable the file editors. Add this line to wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );
The “Editing wp-config.php” documentation explains that this disables the plugin and theme file editors in the admin dashboard. The point is containment: if an attacker compromises an administrator account, they can no longer use the built-in editor to write PHP directly into your theme files. The same documentation raises one caveat — some plugins check whether the current user can edit plugins and may behave unexpectedly when the editor is disabled, so test your essential plugins after adding the constant. There is also DISALLOW_FILE_MODS, which is broader: it also blocks plugin and theme installation and updates from the admin. That suits tightly controlled environments where deployments happen through WP-CLI or a pipeline, which is the approach we describe in our guide to updating WordPress safely with WP-CLI.
Restrict its permissions. The “Changing File Permissions” article recommends 440 or 400 on wp-config.php specifically, “to prevent other users on the server from reading it”. On a shared host, this matters: a world-readable config file hands your database credentials to every other tenant on the machine.
chmod 400 wp-config.php
Consider moving or blocking it. WordPress looks for wp-config.php in the install directory and, failing that, one directory above it, so you can relocate the file outside the web root where the web server cannot serve it as text. Alternatively, deny direct access in Apache:
<Files wp-config.php>
Require all denied
</Files>
A related item from the official guide: the default wp_ table prefix is well known, and changing it blunts a class of SQL injection payloads. On an existing site, however, changing the prefix means renaming every table and fixing serialized references — a migration project, not a config tweak. Do it at install time if you do it at all, and never on a production site without a rehearsal.
Get file permissions right once
The file permissions article gives defaults that work on the majority of shared hosting setups (where PHP runs as the file owner): 755 or 750 for directories, 644 or 640 for files, and never 777 for anything — including upload directories. A directory that is 777 lets any process on the server write executable code into your site.
find /var/www/example -type d -exec chmod 755 {} +
find /var/www/example -type f -exec chmod 644 {} +
chmod 400 wp-config.php
The exceptions the documentation lists are worth knowing before something breaks:
.htaccessmust stay writable if WordPress manages your rewrite rules;/wp-content/may need write access for some plugins — they will tell you at installation time;/wp-content/uploads/and cache directories typically need write access for the web server user.
The article’s broader advice is the right posture: start restrictive and loosen a specific path only when a concrete feature demands it. If you find yourself reaching for 777, the real problem is usually ownership — fixing the file owner beats opening permissions to the world.
Rotate salts deliberately
The authentication salts and keys in wp-config.php strengthen the hashing of passwords and cookies. If a copy of your database ever leaks, unique salts make the stored hashes dramatically harder to attack. Rotating them invalidates every logged-in session, because the cookies no longer match.
With WP-CLI this is a one-liner. The official command reference for wp config shuffle-salts describes exactly what it does: it refreshes the salt keys defined in wp-config.php, running before WordPress loads.
wp config shuffle-salts
You can also shuffle a single key (the docs give wp config shuffle-salts WP_CACHE_KEY_SALT --force as an example of adding or refreshing a cache key salt). When should you rotate? Two sensible triggers: after any suspected credential or database exposure, and periodically on high-value sites as cheap insurance. Pick a quiet window — every editor will be logged out — and tell the team beforehand.
Keep the software current
Since WordPress 3.7, minor core updates install automatically in the background, which quietly protects a large number of sites. Automatic updates do not cover everything, though: major core versions, and most plugin and theme updates, still need someone to act. Keep a routine — weekly for anything business-critical — and treat “we’ll update eventually” as a security decision, because it is one. Our WP-CLI update workflow shows how to run updates in a controlled, repeatable way with backups in the loop.
Vet what you install
The official hardening guide is blunt on this point: only install plugins and themes from WordPress.org or reputable vendors. Beyond the source, two habits matter:
- Delete unused plugins and themes rather than merely deactivating them. Deactivated code still sits on disk, still gets scanned by attackers, and still shows up in vulnerability feeds.
- Avoid plugins that execute arbitrary code (snippet runners, “custom PHP” widgets) where a custom page template or a small mu-plugin in version control would do the same job.
For an additional layer, the guide points at firewalls — security plugins such as Wordfence or iThemes Security, a ModSecurity web application firewall, or a reverse-proxy service like Cloudflare or Sucuri. These are genuinely useful, but they are layers on top of the fundamentals above, never a replacement for them.
Prepare for the day something goes wrong
Hardening reduces the chance of an incident; preparation limits the damage. The official guide groups this under backups, logging and monitoring:
- Backups with integrity. Regular full-site and database snapshots, stored somewhere an attacker who compromises the site cannot also wipe — with encryption and checksums so you can prove a restore is complete and untampered.
- Read your logs. Access and error logs show the traces of XSS attempts, remote file inclusion and brute-force campaigns long before anyone reports a problem. The same logs are your first stop when diagnosing a WordPress 500 error, so the tooling you set up for troubleshooting pays off for security too.
- Watch the files. File integrity monitoring — anything from
diffagainst a known-good copy, to Git, to tools like OSSEC — tells you when a file changes that you did not change. The guide recommends filtering to executable file types first, because that is where the actual risk lives.
The checklist
If you only take one thing from this article, take the list:
- Remove generic admin usernames; enforce generated passwords and two-step authentication.
- Add a second layer in front of wp-admin (mind
admin-ajax.php), serve the admin over HTTPS, use SFTP. - Set
DISALLOW_FILE_EDIT, lock wp-config.php to 400/440, block or relocate it. - Normalize file permissions: 755 directories, 644 files, never 777.
- Rotate salts after any suspected exposure:
wp config shuffle-salts. - Keep core, plugins and themes current; delete what you no longer use.
- Install only from WordPress.org or reputable vendors; avoid arbitrary-code plugins.
- Back up off-site with integrity checks, and actually read your logs.
None of these steps is exotic, and that is the point. The sites that get compromised are rarely defeated by advanced techniques — they are defeated by an open door someone forgot about. If you would rather have a team that runs this checklist for you as part of ongoing WordPress development and maintenance, or you are weighing WordPress against other platforms before investing further, our WordPress platform overview and our analysis of website total cost of ownership cover those decisions in more depth.
Official sources.
Use these references to verify platform-specific behavior and version details.
Continue with the surrounding work.
How to Troubleshoot a WordPress 500 Internal Server Error
How to Fix the WordPress Media Upload HTTP Error for Good
How to Fix WordPress Emails That Are Not Being Sent
Broader context from the YCTheme blog.
Total Cost of Ownership: What a Business Website Actually Costs to Run
A three-year cost framework for WordPress, Joomla, TYPO3 and Shopify websites, covering hosting, upgrades, security, extensions and the labor nobody budgets for.
Backup and Recovery Strategy: The Website Insurance Policy Nobody Tests
A practical backup and recovery framework for WordPress, Joomla, TYPO3 and Shopify sites — what to back up, how often, and why an untested restore is not a backup at all.