Two files control more of your WordPress security than any single plugin does.
wp-config.php holds your database password and the security keys WordPress uses to trust a login. .htaccess decides what your server does with a request before WordPress even loads. Get either one wrong and an attacker either has your credentials or a wide open door, and that's how most WordPress compromises actually start.
Most hardening guides treat both files as an afterthought, a couple of lines lost inside a much longer checklist. We treat them differently. Locking down wp-config.php and .htaccess is one of the first things we do whenever we clean up a hacked site, right alongside removing the malware itself. In the worst case we've documented on this blog, the attacker's access sat unnoticed for over a year. Fresh security keys and a locked-down .htaccess file exist specifically to stop access like that from lingering that long.
This guide walks through both files properly: what to change, why it matters, and what to do when a standard snippet doesn't work on your host. Most guides assume you're on Apache. Plenty of WordPress sites aren't.
What each file actually controls
wp-config.php is WordPress's settings file. It stores your database name, username, and password, plus the security keys and salts that WordPress uses to verify a login session is real. Anyone who reads this file can talk to your database directly.
.htaccess works at a different layer entirely. It's a set of instructions Apache reads before WordPress ever runs, deciding which requests even reach your site's PHP code. A well-written .htaccess file can block an attack that never gets the chance to become a WordPress problem.
Check your server type first
Everything in this guide that touches .htaccess only works on Apache. If your host runs Nginx (many managed hosts do, including some of the biggest names in WordPress hosting), .htaccess does nothing. WordPress won't error out, the file just sits there ignored.
Check your hosting control panel or ask support which web server you're on before you paste anything. If you're on Nginx, the same rules exist, they just live in your server block or your host's dashboard instead, and your host can set them for you.
Before you touch either file
Don't edit wp-config.php or .htaccess through the WordPress dashboard's file editor. Use SFTP or your host's File Manager instead. If something goes wrong, you want to still be able to reach the file.
Download a working copy of both files before you change anything. That's your entire backup plan, and it takes thirty seconds.
A bad rule in .htaccess can take the whole site down with a 500 Internal Server Error. If that happens, rename .htaccess to something like .htaccess-broken, or upload the copy you just saved. The site comes back immediately.
Not every step below carries the same risk. We'll flag each one as we go and collect them into one table at the end.
Hardening wp-config.php
Move it above the web root
WordPress looks for wp-config.php in two places: your site's root folder, and one level above it. If your host's folder structure allows it, moving the file above the web root puts it outside the space a browser can reach at all.
Not every host supports this, especially shared hosting where you don't control the folder above your account root. If moving the file breaks your site, put it back. The .htaccess rule below covers the same risk anyway.
Refresh your security keys and salts
wp-config.php holds eight unique keys and salts that WordPress uses to sign login cookies. Generate a fresh set from WordPress's own secret key generator and paste them in over the old block.
This signs every logged-in user out, including you, and kills any stolen session cookie along with it. The only real cost is logging back in. Do it now, and again any time you suspect a compromise.
Turn off the file editor
php define('DISALLOW_FILE_EDIT', true);
This removes the Theme Editor and Plugin Editor from wp-admin. If an attacker ever gets into an account, even a low-privilege one, this is one less way to write PHP straight into your site through the dashboard.
Keep debug output off in production
php define('WP_DEBUG', false); define('WP_DEBUG_DISPLAY', false);
A live site with debug output on can print file paths and database errors to anyone looking, attacker included. If you need to debug something, log it to a file instead of displaying it.
Lock down file permissions
Set wp-config.php to 440 or 400, read-only rather than the 644 WordPress ships with by default.
Check with your host first. Some server setups need 644 for PHP to read the file at all, and going too strict breaks the site instead of protecting it.
Briefly: DISALLOW_FILE_MODS blocks installing, updating, or deleting any plugin or theme, even from wp-admin. Skip it if you or a client installs plugins directly, the friction usually isn't worth it. Changing your table prefix from wp_ on a site that's already live isn't worth the risk either.
Hardening .htaccess
Block direct access to wp-config.php
Apache 2.4+
<Files "wp-config.php"> Require all denied </Files>
Older hosts still on Apache 2.2 need the legacy form instead:
Apache 2.2 (legacy)
<Files wp-config.php> Order allow,deny Deny from all </Files>
Use the wrong one and you risk a 500 error instead of a working block. If you're unsure which version your host runs, try the modern syntax first, it's what nearly every current host uses.
Turn off directory browsing
```apache Options -Indexes ```
Without this, any folder with no index file lets someone browse its contents straight from the URL bar. One line closes it.
Stop PHP files from running inside uploads
/wp-content/uploads/ is meant for images and documents, but it has to stay writable for plugins to use it, which makes it a favorite drop spot for malware. Add a second .htaccess file inside that folder:
```apache <Files *.php> Require all denied </Files> ```
Now even if a malicious file lands there, the server refuses to run it.
Restrict xmlrpc.php
```apache <Files xmlrpc.php> Require all denied </Files> ```
Skip this if you rely on the WordPress mobile app or Jetpack. There's more nuance here than one snippet covers, we go through it properly in a separate guide, including when you actually still need it enabled.
```apache Header set X-Frame-Options "SAMEORIGIN" Header set X-Content-Type-Options "nosniff" ```
The first stops your site loading inside someone else's iframe. The second stops browsers guessing a file's type in a way that can be exploited. A full headers setup, Content-Security-Policy included, is its own topic. Start with these two.
Protect .htaccess itself
```apache <Files ".htaccess"> Require all denied </Files> ```
The same logic applies here. This file needs the same lockdown as wp-config.php.
These six cover the essentials. The same file can also block traffic by country or IP once the basics above are in place.
The risk-tier checklist
If this feels like too much to do by hand
That's fair. A security plugin can automate most of this: blocking PHP execution, restricting xmlrpc.php, managing permissions, without you touching a server file directly. It won't do everything here, moving wp-config.php and refreshing your keys stay manual either way, but it removes the syntax risk from the parts most likely to break something.
If you'd rather handle the rest yourself, we've also written up how to scan and clean a WordPress site by hand. And if you'd rather someone else lock this down and check whether anything's already gotten in, that's part of how we handle a cleanup, not an upsell tacked on after.
Frequently asked questions
Will hardening wp-config.php and .htaccess stop every attack? No. These two files close specific doors, credential exposure and server-level bypasses, but they don't replace updates, strong passwords, or a firewall.
Can editing .htaccess break my site? Yes, if the syntax doesn't match your Apache version. That's exactly why you keep a saved copy: a broken .htaccess is fixed by renaming or restoring it, usually in under a minute.
What if my host runs Nginx instead of Apache? Then .htaccess does nothing, WordPress won't complain, it just ignores the file silently. The wp-config.php steps still apply. Ask your host to set the equivalent rules at the server-block level.
Do I still need a security plugin after doing this manually? These two files cover part of the picture. A plugin adds ongoing scanning and login protection as new threats appear, something a static file can't do on its own.
How often should I refresh my WordPress security keys? Immediately if you suspect any compromise. Otherwise, once or twice a year is a reasonable habit. We've seen a compromised account sit undetected on a client site for over a year, and a stale key is exactly the kind of thing that lets access like that go unnoticed for so long.
Closing
Both files take under twenty minutes to harden, backup included. Start with wp-config.php since nothing there risks taking the site down, then move to .htaccess with your saved copy ready in case a rule doesn't agree with your server.
They're also the same two files we lock down early in every cleanup we run, right after confirming a hacked site is actually clean. Twenty minutes now is a lot cheaper than doing this after the fact.