wp-config.php: what’s in it, where it is, and how to secure it.
wp-config.php is WordPress’s configuration file. It holds the database name, user and password, the eight security keys and salts, the table prefix, and any settings you add. The WordPress download doesn’t include it — it ships wp-config-sample.php, and the installer writes wp-config.php from that.
Where is wp-config.php?
In the WordPress root folder, beside wp-admin, wp-content and wp-includes — for example /var/www/example.com/public_html/wp-config.php. It is not inside wp-admin.
WordPress also looks one folder above its root, as long as that folder isn’t itself a WordPress install (it checks that there is no wp-settings.php there). That is why some sites seem to have none: it was moved up on purpose. To find it:
wp config path # with WP-CLI, from the site folder
find /var/www /home -name wp-config.php 2>/dev/null
What’s inside
The current sample file, with its comments trimmed:
<?php
// ** Database settings - You can get this info from your web host ** //
define( 'DB_NAME', 'database_name_here' );
define( 'DB_USER', 'username_here' );
define( 'DB_PASSWORD', 'password_here' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
$table_prefix = 'wp_';
define( 'WP_DEBUG', false );
/* Add any custom values between this line and the "stop editing" line. */
/* That's all, stop editing! Happy publishing. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
- Database settings.
DB_HOSTis usuallylocalhost, but can behost:portor a socket path. These four values are full access to the site’s content and users. - Keys and salts. Eight random strings that sign login cookies. Generate them with the WPSalt salts generator, or replace them with
wp config shuffle-salts; changing them signs everyone out. $table_prefix— the prefix of every table in the database.- Your own settings go between the “Add any custom values” and “stop editing” lines. Anything defined after
wp-settings.phpis loaded comes too late to have an effect.
Settings worth knowing
| Constant | What it does |
|---|---|
WP_DEBUG | Turns on PHP error reporting. Keep it false on a live site. |
WP_DEBUG_LOG | Writes errors to wp-content/debug.log — a file anyone can download unless you block it. Give it a path outside the web root instead. |
WP_DEBUG_DISPLAY | Whether errors are printed into pages. Set it to false whenever debugging on a live site. |
DISALLOW_FILE_EDIT | Removes the theme and plugin file editor from the dashboard, so a stolen admin login can’t edit PHP from there. |
DISALLOW_FILE_MODS | Also blocks installing and updating plugins and themes from the dashboard — only if you update another way. |
FORCE_SSL_ADMIN | Forces HTTPS for logins and the dashboard. |
WP_ENVIRONMENT_TYPE | production, staging, development or local; plugins can read it to behave differently. |
WP_MEMORY_LIMIT | The PHP memory WordPress asks for, such as '256M'. |
WP_HOME, WP_SITEURL | Fix the site address in the file, overriding the values in the database. |
/* Add any custom values between this line and the "stop editing" line. */
define( 'WP_DEBUG', false );
define( 'DISALLOW_FILE_EDIT', true );
define( 'FORCE_SSL_ADMIN', true );
define( 'WP_ENVIRONMENT_TYPE', 'production' );
Editing it safely
- Back it up outside the web root, for example
cp wp-config.php ~/wp-config.php.$(date +%F). Awp-config.php.bakleft beside the original is sent as plain text to anyone — see wp-config.php backup exposed. - Check the syntax before you leave:
php -l wp-config.php. One missing quote takes the whole site down. - Or let WP-CLI edit it:
wp config set DISALLOW_FILE_EDIT true --raw,wp config get DB_NAME.wp config listprints the database password, so don’t run it where others can see your screen or logs.
How to keep wp-config.php secure
- It is safe while PHP runs it. A request for
/wp-config.phpshould come back empty, because PHP runs the file and it prints nothing. If PHP stops handling.phpfiles — after an upgrade or a server move — the web server sends the source instead: what to do if that happens. - Refuse it in the web server anyway, with a rule that covers every copy too: nginx and Apache rules.
- Tighten permissions. If PHP runs as the site’s own user,
440or400, as WordPress’s hardening guide recommends. - Move it one folder up, out of the web root, if your host allows it.
- Use unique keys and salts, and if the file was ever exposed, change the database password and the salts — the backup-exposed guide walks through both.
Check it from the outside
curl -s -o /dev/null -w '%{http_code} %{size_download}\n' https://example.com/wp-config.php
200 0 (PHP ran it, nothing came back) or a 403 is what you want. A response with a size means something was sent — look at it. DotenvScan checks /wp-config.php and /wp-config.php.bak and tells the two cases apart for you. For the rest of the site, WP Server Guard’s WordPress security audit checklist goes further.