wp-config.php Explained: Location, Constants and Hardening
One file holds the database credentials, the salts and every constant that changes how WordPress behaves. Know where it lives, what belongs in it, and how to keep it unreadable.
What it is: the configuration file WordPress reads before anything else. It holds database credentials, security keys, and constants that switch features on and off. It is not in the WordPress repository, it is not overwritten by updates, and it is the first file to back up before editing.
Where to find it
The default location is the WordPress root, alongside wp-admin and wp-includes. Depending on the host that is public_html, www, httpdocs or htdocs.
WordPress also checks one level above the root, and some setups use that deliberately so the file sits outside the web-server document root. If it is not where you expect, look there before assuming it is missing.
If the file does not exist at all, WordPress shows the installation screen. wp-config-sample.php is the template: copy it, fill in the database details, and save it as wp-config.php.
What each block does
<?php
// Database connection.
define('DB_NAME', 'database_name');
define('DB_USER', 'database_user');
define('DB_PASSWORD', 'database_password');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8mb4');
// Authentication keys and salts — unique per site.
define('AUTH_KEY', '...');
define('SECURE_AUTH_KEY', '...');
// ... six more
// Table prefix.
$table_prefix = 'wp_';
// Debugging.
define('WP_DEBUG', false);
/* That's all, stop editing! Happy publishing. */
Everything you add belongs above the "stop editing" line. Below it, WordPress has already bootstrapped and the constant arrives too late.
Generate salts from the official secret-key service rather than inventing them. They must be long and random; their only job is to make stolen cookies useless.
Constants worth knowing
| Constant | Purpose |
|---|---|
WP_DEBUG |
Turns on error reporting — see debug mode |
WP_DEBUG_LOG |
Writes errors to wp-content/debug.log |
WP_DEBUG_DISPLAY |
Whether errors are printed on screen |
WP_MEMORY_LIMIT |
PHP memory for the front end — see memory limit |
WP_MAX_MEMORY_LIMIT |
Memory for admin-side tasks such as image processing |
WP_HOME / WP_SITEURL |
Overrides the URLs stored in the database |
DISALLOW_FILE_EDIT |
Removes the built-in theme and plugin editors |
DISABLE_WP_CRON |
Stops cron firing on page loads — see admin speed |
WP_POST_REVISIONS |
Caps stored revisions per post |
EMPTY_TRASH_DAYS |
How long trashed content is kept |
WP_ENVIRONMENT_TYPE |
Marks the install as production, staging or local |
WP_ALLOW_REPAIR |
Exposes the database repair page — remove after use |
A practical production block:
<?php
define('WP_ENVIRONMENT_TYPE', 'production');
define('WP_DEBUG', false);
define('DISALLOW_FILE_EDIT', true);
define('WP_POST_REVISIONS', 5);
define('EMPTY_TRASH_DAYS', 14);
define('WP_MEMORY_LIMIT', '256M');
And a staging block:
<?php
define('WP_ENVIRONMENT_TYPE', 'staging');
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 0);
Never leave WP_DEBUG_DISPLAY on in production. Error output leaks paths and, occasionally, credentials.
Fixing URLs when you cannot log in
If a domain change locked you out of the admin, set the URLs here. These override the database values and take effect immediately:
<?php
define('WP_HOME', 'https://example.com');
define('WP_SITEURL', 'https://example.com');
Useful during a migration, but treat it as temporary — the database should hold the correct values eventually, per how to migrate a WordPress site.
Keep the file unreadable
wp-config.php contains your database password. Protect it accordingly.
File permissions. 640 or 600 is appropriate, owned by the account the web server runs as. Never 777.
Block direct access on Apache or LiteSpeed, in the root .htaccess:
<Files wp-config.php>
Require all denied
</Files>
On Nginx, in the server configuration:
location = /wp-config.php {
deny all;
}
Never leave backups next to it. Files named wp-config.php.bak, wp-config.old or wp-config.php.txt are served as plain text by most servers, and automated scanners look for exactly those names. If you need a copy before editing, download it and delete the server-side copy.
Keep it out of version control. If the site is in Git, wp-config.php belongs in .gitignore, with credentials supplied by environment variables or an untracked include.
Editing it safely
- Download a copy first — this file breaks the entire site when it is wrong.
- Edit in a plain-text editor, not a word processor.
- Save as UTF-8 without a byte-order mark. A BOM produces "headers already sent" errors and a blank page.
- Leave no blank lines or spaces after the closing
?>, or omit the closing tag entirely, which is safer. - Upload and load the site immediately, so a mistake is caught while you still remember what you changed.
A syntax error here produces a white screen with no admin access. Recovery is to restore the copy you downloaded — the reason step one exists. If it happens and you have no copy, the symptoms and rescue routes are in the white screen guide.
Frequently asked
- In the WordPress root, next to wp-admin and wp-includes — usually public_html, www or httpdocs. WordPress also looks one directory above the root, which some setups use to keep it outside the web root.
- Every existing login cookie becomes invalid and all users are logged out. Nothing else breaks, which is why rotating salts is a standard step after a security incident.
- Everything below it sets up WordPress itself. Custom constants must go above that line, or they are defined too late to affect anything.