wp-config.php in WordPress

wp-config.php is one of the most important files in WordPress - it's the basic configuration file. It is located in the root directory (usually alongside other engine files and folders).

This file contains the settings (configurations) of WordPress.

IMPORTANT! If you define a constant at the very end of the wp-config.php file, it will not work! All constants need to be defined before the following line:

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

How to create a wp-config.php

When you have just downloaded WordPress, this file isn't in the folder, but there is wp-config-sample.php - this is an example of what the wp-config.php should look like.

You can create a wp-config.php file in different ways:

  • Manually. To do this, edit the wp-config-sample.php file and save it as wp-config.php.

  • Through WP CLI. For this, use the command wp config create.

  • Automatically. When installing WP through the browser.

    If there isn't a wp-config.php file in the root of the site and you navigate to the site in the browser, you will see this message:

    The message about the absence of the wp-config.php file

    Clicking on the Create Configuration File button, you will see a form where WP will ask you to enter data to generate the wp-config.php file. Specifically, WordPress asks to enter information to connect to the database:

    wp-config.php file creation

    All the data entered into this form will be written in the wp-config.php file in these lines:

    define('DB_NAME', 'database_name_here');
    define('DB_USER', 'username_here');
    define('DB_PASSWORD', 'password_here');
    define('DB_HOST', 'localhost');
    
    $table_prefix  = 'wp_';

I suppose it is clear now how to create and where to save the wp-config.php file. Now, let's move on to the specific constants and variables that need or can be specified in wp-config.php.

Database

You receive database connection settings when you create a database in the server control panel, or they are given to you by server administrators if they create the database for you.

Opening wp-config.php in any text editor (I recommend sublime text), you will see a detailed description for each constant:

/** MySQL settings: This information can be obtained from your hosting provider */
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** MySQL user name */
define( 'DB_USER', 'username_here' );

/** MySQL database password */
define( 'DB_PASSWORD', 'password_here' );

/** MySQL hostname */
define( 'DB_HOST', 'localhost' );

/** The database character set for creating tables. */
define( 'DB_CHARSET', 'utf8' );

/** The collation scheme. Do not change if not sure. */
define( 'DB_COLLATE', '' );

DB_NAME

Contains the name of your database.

define( 'DB_NAME', 'my_database' );

DB_USER

Contains the username for your database.

define( 'DB_USER', 'my_db_user' );

DB_PASSWORD

Contains the password for your database user.

define( 'DB_USER', 'my_db_user_password' );

DB_HOST

Contains the domain to connect to the database.

Different hosting companies use different connection settings. Most often this constant is equal to localhost:

define( 'DB_HOST', 'localhost' );

MySQL connection port

If your host utilizes a non-standard port to connect to the database, the port can be specified like this.

For localhost:

define( 'DB_HOST', '127.0.0.1:3307' );
// or
define( 'DB_HOST', 'localhost:3307' );

For a specific server:

define( 'DB_HOST', 'mysql.example.com:3307' );

MySQL Socket or Pipe connection

define( 'DB_HOST', '127.0.0.1:/var/run/mysqld/mysqld.sock' );
// or
define( 'DB_HOST', 'localhost:/var/run/mysqld/mysqld.sock' );
// or
define( 'DB_HOST', 'example.tld:/var/run/mysqld/mysqld.sock' );

DB_CHARSET

Default: utf8 (Unicode UTF-8).

Contains the name of the character set used for creating database tables.

define( 'DB_CHARSET', 'utf8' );

Almost always, utf8 is the best choice. UTF-8 supports any language. Usually, this setting is left untouched, and sometimes the DB_COLLATE value is changed, which is more suitable for your language.

The value utf8 will be automatically changed to utf8mb4 for the wpdb::$charset property if the utf8mb4 character set is supported by the server.

See also: maybe_convert_table_to_utf8mb4()

There is usually no reason to change the default DB_CHARSET value. If your blog requires a different character set, read Character Sets Supported by MySQL to get information on available DB_CHARSET values.

WARNING: Adding DB_CHARSET and DB_COLLATE to the wp-config.php file for an existing site can cause issues.

If DB_CHARSET and DB_COLLATE are not specified in wp-config.php, and you're not sure what should be specified, then DO NOT set them (leave as is).

DB_COLLATE

Default: ''.

Contains the name of the collation (comparison) for the created database tables.

define( 'DB_COLLATE', '' );

The DB_COLLATE value was added so that you could specify the database collation (sorting order of the character set).

In most cases, this value should be left blank (''). In this case, MySQL will determine the necessary collate when creating a table based on the character set specified by DB_CHARSET.

Sometimes it is necessary to set the DB_COLLATE value to one of the UTF-8 values. This is necessary when, for example, for a Western European language, a different character is displayed from what was entered. (Also see the section Unicode Character Sets in the SQL manual).

Examples:

// UTF-8 Unicode General collation
define( 'DB_COLLATE', 'utf8_general_ci' );

// UTF-8 Unicode Turkish collation
define( 'DB_COLLATE', 'utf8_turkish_ci' );

WARNING: Adding DB_COLLATE to the wp-config.php file for an existing blog can lead to serious problems. Because before changing this option, you must first convert all database tables to a suitable collation.

If DB_COLLATE is not specified in wp-config.php, and you're not sure what to specify, then DO NOT specify anything (leave as is).

$table_prefix

Default: wp_

The variable $table_prefix contains the base prefix for all database tables.

$table_prefix = 'wp_';

With the prefix wp_, the full table names look like: wp_posts, wp_terms, etc.

The value only allows a-z0-9_: Latin letters (in lowercase), numbers, and the underscore _:

This value is changed:

  • When setting up multiple WordPress sites using a single database. This is not recommended for security reasons.

  • When wanting to increase security by changing the default table names. I don't think this will actually enhance the security of the site.

Never change this prefix on a working site! Because after such replacement, you will have to rename all tables and some option names in the wp_options table, for example, the option wp_capabilities - {$table_prefix}capabilities.

WP_DEBUG

Default: false

Enables debug mode.

define( 'WP_DEBUG', true );

Read more about debugging mode and other constants for debugging here:

WP_ENVIRONMENT_TYPE

Default: not set (corresponds to the production type)

Defines the environment type for the site. Possible values:

  • local
  • development
  • staging
  • production

Example: Let's set up a local development environment:

define( 'WP_ENVIRONMENT_TYPE', 'local' );

Then, to check the current development environment, use the function wp_get_environment_type().

If an incorrect value is entered (not from the list of possible values), then wp_get_environment_type() will return the default value: production.

NOTE: When setting the environment type to development, the debug mode is automatically enabled - WP_DEBUG = true. If the WP_DEBUG constant is not set. See wp_initial_constants().

Security Keys

Secret keys protect your site from hacking attacks by complicating passwords and other sensitive data.

Four keys are mandatory and necessary to enhance security. Four salts are recommended but not required as WordPress will generate them if they are not provided. It's worth specifying them in wp-config.php for convenience, so they don't keep changing.

The keys should be long, random, and complex. To avoid typing them manually, use the online generator: https://api.wordpress.org/secret-key/1.1/salt/.

The keys can be changed at any time to invalidate all existing cookies. After changing the keys, all users will have to log in again.

Example:

define( 'AUTH_KEY',         'rC$  `h-7|=FDvevE,tesQ4h< Ic2eB(e5n]y|wY*VN6pYAXo$qT#8Zj<R5-jzUK' );
define( 'SECURE_AUTH_KEY',  'iA8r9WU-.K<8jok|pnmPopVDN?-,=M&WfXK M+MB04M/qs<C`p0Ex}->{Ey|fhq8' );
define( 'LOGGED_IN_KEY',    ',HP.N3pL}D7M_b~1G6B|R:5Y=XgD(x oA|>:7Ex-q(y.m8!~,/&(wV.bF+3p_Hp+' );
define( 'NONCE_KEY',        'Ffv*n?P2J~8r0_)dHhK-n&oL1FKR;9t5sDL$|@#,HfwjMq~U{+d!;o58^~VxlbY!' );
define( 'AUTH_SALT',        'lrs5bgbq~7i3u1-ytlcnp6AqoFfoC20{kehs/]Np0OcV^%@Fm2,aL/@/c ]V^H92' );
define( 'SECURE_AUTH_SALT', '}[h&,wa,#YMk<$|j[pmUp`f5{A _|R?c]ewc-{a1_Xym9])y:G:.d;xkxUt0CBSI' );
define( 'LOGGED_IN_SALT',   '#r]cdwnTHqkM8+_;_]$pEabgA5CzmtEWoLz1XN~.[zOObbA58k-wIpcagvRh<D?-' );
define( 'NONCE_SALT',       '0?ToX=[EP%,p_5+xO=/K,|R)SCrD*LOf^%G(</%V>A@YFF6)N+[a&7-u+e92):cs' );

For more detailed information on the technical side and analysis of secret keys and secure passwords:

Notes

  • The wp-config.php file can be moved one directory up. That is, if the file is located in the directory /public_html/wordpress/wp-config.php it can be moved to the directory /public_html/wp-config.php and everything will continue to work as it did.

Other Settings

WP_SITEURL and WP_HOME

WP_SITEURL and WP_HOME override the siteurl and home option values in the wp_options table, respectively. But they do not change these values in the database.

  • siteurl - is the URL where the WordPress core is located.
  • home - is the URL of the site (front-end).

Both constants should start with http:// and should NOT have a slash / at the end.

define( 'WP_SITEURL', 'http://example.com' );
define( 'WP_HOME', 'http://example.com' );

Setting the WP_SITEURL constant overrides the use of the siteurl option from the wp_options table. However, this will not lead to a change in the database value. If this constant is removed from wp-config, the URL will return to the old database value.

To change the siteurl value in the database, you can use the RELOCATE constant:

define( 'RELOCATE', true );

Setting the RELOCATE constant will initiate a check and (if needed) update the siteurl option when trying to log in via https://example.com/wp-login.php.

If WordPress is installed in a directory named "wp" for the domain example.com, define WP_SITEURL as follows:

define( 'WP_SITEURL', 'http://example.com/wp' );
define( 'WP_HOME', 'http://example.com' );

Dynamic setting based on $_SERVER['HTTP_HOST']:

define( 'WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST'] . '/path/to/wordpress' );
define( 'WP_HOME', 'https://' . $_SERVER['HTTP_HOST'] );

Note: HTTP_HOST is created by PHP dynamically based on the request data, which may lead to vulnerabilities associated with file inclusion. SERVER_NAME can also be created dynamically. However, when Apache is configured with UseCanonicalName=on, SERVER_NAME is set by the server configuration, not dynamically. In this case, it is safer to use SERVER_NAME rather than HTTP_HOST.

define( 'WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/path/to/wordpress' );
define( 'WP_HOME', 'http://' . $_SERVER['SERVER_NAME'] );

It is not always possible to use $_SERVER['SERVER_NAME'] instead of $_SERVER['HTTP_HOST']. More details: https://stackoverflow.com/questions/1459739/php-serverhttp-host-vs-serverserver-name-am-i-understanding-the-ma

WP_CONTENT_DIR and WP_CONTENT_URL

You can move the wp-content directory, where themes, plugins, and uploaded files are stored, outside of the WordPress directory.

To do that, set WP_CONTENT_DIR to the full path and WP_CONTENT_URL to the url of the wp-content folder:

define( 'WP_CONTENT_DIR', __DIR__ . '/blog/wp-content' );
define( 'WP_CONTENT_URL', 'http://example.com/blog/wp-content' );

There should be no trailing slash!

AUTOSAVE_INTERVAL

By default: 60 (seconds).

When editing posts, WordPress uses Ajax to automatically save changes. You can increase or decrease the time intervals between auto-saves.

Let's change the save interval to 120 seconds (every 2 minutes):

define( 'AUTOSAVE_INTERVAL', 120 );

WP_POST_REVISIONS

By default: true

By default, WordPress saves copies of all edits made to posts (an edit is saved when you save changes). This allows you to return to a previous version of a post. Saving edits can be disabled or set to a maximum number (how many maximum edits should be saved).

If the constant is not set, then by default it will be equal to true - revisions are enabled.

To completely disable revisions specify false:

define( 'WP_POST_REVISIONS', false );

To limit the maximum number of stored revisions, replace false with a number (for example, 5 or 10):

define( 'WP_POST_REVISIONS', 5 );

The number of revisions can also be finely tuned through hooks:

Hooks allow you to set up revision for a post type or for an individual post.

EMPTY_TRASH_DAYS

Default: 30

This constant is responsible for the WordPress trash bin. It defines the number of days after which posts, pages, attachments, and comments will be irretrievably deleted from the trash.

Only posts that have been in the trash for longer than the specified time will be deleted.

Set the trash to keep items for 7 days:

define( 'EMPTY_TRASH_DAYS', 7 ); // 7 days

Disable trash:

define( 'EMPTY_TRASH_DAYS', 0 ); // Zero days

Note: When using this setting, WordPress will not ask for confirmation when clicking the "Delete Permanently" button.

Read more about how to disable the trash in WordPress in this article (including trash for individual post types).

DISALLOW_FILE_EDIT

Default: not set

Allows you to disable the file editor for plugins or themes.

define( 'DISALLOW_FILE_EDIT', true );

Disabling may be useful to prevent the possibility of editing important files, which could lead to a broken website. Also, such a disablement provides an additional level of security in case a hacker gains access to a privileged user account.

Enabling this constant forcibly disables the following rights for all users:

edit_files
edit_plugins
edit_themes

See the list of user capabilities.

For example, current_user_can('edit_plugins') will always return false for all users. If a plugin relies on such user permission, it may stop working correctly.

I recommend always enabling this constant and editing files in some other way, but not through the WP admin panel!

DISALLOW_FILE_MODS

Default: not set

Disables any ability to modify the site from the admin panel. Specifically, disables the ability to install or update plugins, themes. Disables updating the core and translation files.

define( 'DISALLOW_FILE_MODS', true );

Enabling this constant will disable automatic updates for everything: themes, plugins, core, and translations. It will also forcibly disable the following rights for all users:

edit_files
edit_plugins
edit_themes

update_plugins
delete_plugins
install_plugins
upload_plugins
update_themes
delete_themes
install_themes
upload_themes
update_core

install_languages
update_languages

See the list of user capabilities.

Setting this constant also disables the file editor for plugins and themes - it does the same as DISALLOW_FILE_EDIT. Therefore, there's no point in setting DISALLOW_FILE_EDIT = true, as setting DISALLOW_FILE_MODS = true will have the same effect.

If you need to disable some but not all of the above rights and functions, you can use the file_mod_allowed hook.

AUTOMATIC_UPDATER_DISABLED

Default: not set

Disables all automatic updates.

There may be reasons why a site should not auto-update, such as custom configurations or updates provided by the host. This could also be done prior to the release of a major update to allow time for testing in a development environment before permitting the update on a live site.

To disable auto-updates, add this code to wp-config.php:

define( 'AUTOMATIC_UPDATER_DISABLED', true );

Auto-updates can also be disabled through hooks: automatic_updater_disabled and file_mod_allowed.

To disable only WordPress core auto-updates, use the following constants:

# Disable all core updates:
define( 'WP_AUTO_UPDATE_CORE', false );

# Enable all core updates, including minor and major:
define( 'WP_AUTO_UPDATE_CORE', true );

# Enable core updates for minor releases (by default):
define( 'WP_AUTO_UPDATE_CORE', 'minor' );

Read more about auto-updates in the article: Auto-updates in WordPress.

IMAGE_EDIT_OVERWRITE

Default: not set

By default, WordPress creates a new set of images every time you edit an image, and when restoring the original, it keeps all edits on the server. Defining the constant IMAGE_EDIT_OVERWRITE = true changes this behavior. Only one set of editable images will be created, and when restoring the original, all editable images will be deleted from the server.

define( 'IMAGE_EDIT_OVERWRITE', true );

ALLOW_UNFILTERED_UPLOADS

Default: not set

Enables the use of the unfiltered_upload user capability.

The unfiltered_upload capability allows users (roles) to upload any files, without checking their type.

By default, this capability is available to the roles:

  • Administrator.
  • Super-administrator (in multisite mode).

However, by default, this capability does not work (is blocked), i.e. the specified roles will not pass the check if( current_user_can('unfiltered_upload') ), despite having such a right.

To activate the unfiltered_upload right as usual, you need to “turn on” the constant:

define( 'ALLOW_UNFILTERED_UPLOADS', true );

WP_CACHE

Default: false

Enables the inclusion of the file wp-content/advanced-cache.php. This file will be included at a very early stage of WP loading. Page caching plugins such as WP Super Cache, Surge make use of this.

Learn more here.

Let's enable the loading of the file wp-content/advanced-cache.php if it exists:

define( 'WP_CACHE', true );

WP_HTTP_BLOCK_EXTERNAL

Default: not set

Blocks all external requests through the HTTP API.

By default, the HTTP API can make requests to any sites. If you enable this constant, such requests will be allowed only to your own domain:

define( 'WP_HTTP_BLOCK_EXTERNAL', true );

If you need to allow other domains as well, you need to list them separated by commas in the WP_ACCESSIBLE_HOSTS constant. The wildcard * is also supported here:

define( 'WP_ACCESSIBLE_HOSTS', 'api.wordpress.org, *.github.com' );

See more in the code of the method WP_Http::block_request().

FORCE_SSL_ADMIN

Default: true, if the siteurl option has an https protocol, otherwise false.

Forcibly enables https protocol for logging into the system (admin area), ensuring that passwords and cookies are never transmitted in clear text. See more in the section Administration over SSL.

When this constant is on, attempting to access the page /wp-load.php via http protocol, you will be redirected to https. https will also be set in other secure areas, for example for REST requests from the admin area.

Enable the https protocol for administration:

define( 'FORCE_SSL_ADMIN', true );

The constant FORCE_SSL_LOGIN.

Prior to WP version 4.0, the FORCE_SSL_LOGIN constant was used instead of this one; it is now deprecated.

WP_LANG_DIR

Default: WP_CONTENT_DIR . '/languages' or ABSPATH . WPINC . '/languages' (when WP_CONTENT_DIR/languages folder does not exist)

Allows you to specify the global directory where the .mo translation files are located. See wp_set_lang_dir().

WPLANG

Deprecated as of WordPress 4.0.

Allowed you to change the site language. It is now set from the admin area, on the page: Settings > General.

WP_MEMORY_LIMIT and WP_MAX_MEMORY_LIMIT

Default WP_MEMORY_LIMIT: 40M and 64M (for multisite)
Default WP_MAX_MEMORY_LIMIT: 256M

Allows increasing the memory limit for the PHP process.

These settings may be necessary in case of receiving messages like "Allowed memory size of xxxxxx bytes exhausted".

Through both these constants, WP will attempt to set the PHP option: ini_set( 'memory_limit' ), if the server allows it.

WP_MEMORY_LIMIT - sets the limit for regular requests.
WP_MAX_MEMORY_LIMIT - sets the limit for environments that require more memory, such as when updating WP. WP itself determines where more memory is needed and uses this constant in those cases.

By default, WordPress will try to increase the memory allocated to PHP to 40 MB and to 64 MB for multisite, so you should specify a value exceeding 40 MB or 64 MB.

Some hosts prohibit changing the PHP 'memory_limit' option via ini_set(). If this is the case, contact your host.

It is not recommended to indiscriminately increase the memory limit - it may lead to problems. For example, you can mask a problematic section of code, which will later emerge when the site's traffic grows or in other cases.

If you encounter the Out of Memory issue even after increasing the memory limit, you should fix the code.

Examples:

define( 'WP_MEMORY_LIMIT', '64M' );

Increase PHP memory to 96 MB

define( 'WP_MEMORY_LIMIT', '96M' );

Administration tasks may require more memory than normal operation. While in the administrative area, memory can be increased or decreased from WP_MEMORY_LIMIT by defining WP_MAX_MEMORY_LIMIT.

define( 'WP_MAX_MEMORY_LIMIT', '128M' );

WP_TEMP_DIR

Default: sys_get_temp_dir() or ini_get( 'upload_tmp_dir' )

The absolute path to the directory for temporary files. Usually, temporary files are written here during the upgrade of plugins, themes, the core, or when uploading files.

See get_temp_dir().

FS_CHMOD_DIR and FS_CHMOD_FILE

Default FS_CHMOD_DIR: 0755 or higher, if the ABSPATH folder permissions are higher.
Default FS_CHMOD_FILE: 0644 or higher if the index.php file permissions are higher.

Allow overriding the default permissions for created directories/files.

These settings will only work for folders/files processed by WordPress file system objects - See WP_Filesystem(). That is, if you use PHP functions like mkdir(), copy(), these constant values won't be utilized.

The value should be specified in octal notation, i.e. the number should begin with 0: 0644, not 644. These values are ultimately passed to the $permissions parameter of the function chmod().

Read more about the permissions scheme for WordPress files here.

Example of setting values considering server settings:

define( 'FS_CHMOD_DIR', ( fileperms( ABSPATH ) & 0777 | 0755 ) );
define( 'FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) );

Example: specify access permissions rigidly - without considering server settings:

define( 'FS_CHMOD_DIR', 0755 );
define( 'FS_CHMOD_FILE', 0644 );

Example: Set the maximum possible rights 755 and 644. Here, if the current mask for created folders/files on the server is less than the specified rights, it will be used. For example, if by default, folders are created with permissions 700 on the server, then FS_CHMOD_DIR will be 700. And if on the server folders are created with permissions 777, then FS_CHMOD_DIR will be 755.

define( 'FS_CHMOD_DIR', ( 0755 & ~ umask() ) );
define( 'FS_CHMOD_FILE', ( 0644 & ~ umask() ) );

Example: set rights together with setgid (set group ID). Here, the resulting value FS_CHMOD_DIR - is a modified value of the file system permission, where the directory has the setgid permission set (enabled bit group execute). This means that all new files and directories created within the directory will inherit the group right of the parent directory.

define( 'FS_CHMOD_DIR', ( 02755 & ~umask() ) );

Default: false (current domain)

Allows changing the domain specified when setting COOKIE.

The fifth parameter of the function setcookie():

(Sub)domain that the cookie is available to. Setting the domain to 'www.example.com' will make the cookie available in the domain and all its subdomains (for example, w2.www.example.com). To make the cookie available to the whole domain (including subdomains), just specify the domain name (e.g. 'example.com').

Old browsers that follow the obsolete document » RFC 2109 may require a . before the domain to include all subdomains.

You need to define this constant when you have an unusual domain configuration. For example, if you use sub-domains to serve static content, you can set the cookie domain to just your non-static domain to prevent the sending of WordPress cookies with every request to your static content on your sub-domain.

define( 'COOKIE_DOMAIN', 'example.com' );

See all possible cookie-related constants in the code of the functions:

Other cookie-related constants:

  • COOKIEHASH

    define( 'COOKIEHASH', md5( $siteurl ) );
  • USER_COOKIE

    define( 'USER_COOKIE', 'wordpressuser_' . COOKIEHASH );
  • PASS_COOKIE

    define( 'PASS_COOKIE', 'wordpresspass_' . COOKIEHASH );
  • AUTH_COOKIE

    define( 'AUTH_COOKIE', 'wordpress_' . COOKIEHASH );
  • SECURE_AUTH_COOKIE

    define( 'SECURE_AUTH_COOKIE', 'wordpress_sec_' . COOKIEHASH );
  • LOGGED_IN_COOKIE

    define( 'LOGGED_IN_COOKIE', 'wordpress_logged_in_' . COOKIEHASH );
  • TEST_COOKIE

    define( 'TEST_COOKIE', 'wordpress_test_cookie' );
  • COOKIEPATH

    define( 'COOKIEPATH', preg_replace( '|https?://[^/]+|i', '', get_option( 'home' ) . '/' ) );
  • SITECOOKIEPATH

    define( 'SITECOOKIEPATH', preg_replace( '|https?://[^/]+|i', '', get_option( 'siteurl' ) . '/' ) );
  • ADMIN_COOKIE_PATH

    define( 'ADMIN_COOKIE_PATH', SITECOOKIEPATH . 'wp-admin' );
  • PLUGINS_COOKIE_PATH

    define( 'PLUGINS_COOKIE_PATH', preg_replace( '|https?://[^/]+|i', '', WP_PLUGIN_URL ) );
  • COOKIE_DOMAIN

    define( 'COOKIE_DOMAIN', false );
  • RECOVERY_MODE_COOKIE
    define( 'RECOVERY_MODE_COOKIE', 'wordpress_rec_' . COOKIEHASH );

UPLOADS

Default: not set

Allows moving the /wp-content/uploads folder.

The constant is used in the function _wp_upload_dir().

It is used to determine the path and URL to the uploads folder.

Must contain a path relative to the ABSPATH constant and a URL relative to the siteurl option (or the WP_SITEURL constant).

Should not contain a slash / at the beginning and end!

Example, let's move the uploads folder to the root directory files, i.e. the URL will be like this https://example.com/files:

define( 'UPLOADS', 'files' );

I do not recommend moving the UPLOADS folder without a very good reason!

WP_PLUGIN_DIR and WP_PLUGIN_URL

Default WP_PLUGIN_DIR: WP_CONTENT_DIR . '/plugins'
Default WP_PLUGIN_URL: WP_CONTENT_URL . '/plugins'

Allows moving the plugins folder. Should not contain a slash / at the end!

I do not recommend moving the plugins folder without a very good reason! Because not all plugins know how to work properly with a non-standard path. And in general - it can cause a lot of problems due to the non-standard path.

Example: let's move the plugins folder to a different location:

define( 'WP_PLUGIN_DIR', __DIR__ . '/wp-plugins' );
define( 'WP_PLUGIN_URL', 'http://example.com/wp-plugins' );

There is also the deprecated constant PLUGINDIR - the old version of the WP_PLUGIN_DIR constant.

Some plugins may use it. So if you have any problems with an old plugin, you might need to set the value of this constant as well:

define( 'PLUGINDIR', WP_PLUGIN_DIR );

WPMU_PLUGIN_DIR and WPMU_PLUGIN_URL

Default WPMU_PLUGIN_DIR: WP_CONTENT_DIR . '/mu-plugins'
Default WPMU_PLUGIN_URL: WP_CONTENT_URL . '/mu-plugins'

Allows moving the must-use plugins folder.

Should not contain a slash / at the end!

I do not recommend moving the mu-plugins folder without a very good reason!

Example: let's move the mu-plugins folder to a different location:

define( 'WPMU_PLUGIN_DIR', __DIR__ . '/force-plugins' );
define( 'WPMU_PLUGIN_URL', 'http://example.com/force-plugins' );

There is also the deprecated constant MUPLUGINDIR - the old version of the WPMU_PLUGIN_DIR constant.

Some plugins may use it. So if you have any problems with an old plugin, you might need to set the value of this constant as well:

define( 'MUPLUGINDIR', WPMU_PLUGIN_DIR );

Moving the themes folder (themes)

It's not possible to move the themes folder, as its path is hardcoded relative to the wp-content folder:

$theme_root = WP_CONTENT_DIR . '/themes';

However, you can register additional theme directories using the function register_theme_directory().

See how to move the wp-content folder here.

For more details on how the themes folder is determined, see the file wp-includes/theme.php.

WP Cron

For details on how WP Cron works and how to configure it, see the dedicated article.

Below are the constants related to cron.

Enable alternative method of triggering cron tasks:

The user's browser receives redirection from PHP when cron needs to be triggered, allowing it to immediately return to the site while cron continues. This method has certain risks since it depends on a service not native to WordPress.

define( 'ALTERNATE_WP_CRON', true );

Complete deactivation of Cron

I do not recommend doing this, because important tasks are performed on cron, such as removing posts from the trash, cleaning auto-drafts, etc.

define( 'DISABLE_WP_CRON', true );

Restriction on re-running Cron

Let's set a minimum time limit (in seconds) between runs of Cron processes:

define( 'WP_CRON_LOCK_TIMEOUT', 60 );

WP_ALLOW_REPAIR

Default: not set

Enables support for automatic database repair:

define( 'WP_ALLOW_REPAIR', true );

After setting this constant, go to the link:

https://example.com/wp-admin/maint/repair.php

This function should be activated only when necessary and should be deactivated after resolving the issue. If enabled, anyone can access the mentioned page, as its primary purpose is to repair a corrupted database when you cannot log in.

CUSTOM_USER_TABLE and CUSTOM_USER_META_TABLE

These constants allow overriding the default table names where user data is stored. In this case, the default user tables will not be used, and instead, the tables specified in these constants will be used.

define( 'CUSTOM_USER_TABLE', 'myprefix_users' );
define( 'CUSTOM_USER_META_TABLE', 'myprefix_usermeta' );

This trick allows setting up different WP sites in a single database while keeping the same users across all sites.

However, in addition to these constants, other factors need to be taken into account as well. For example, all sites should have the same secret keys.

For more details on all the conditions, watch this video:

The steps are as follows:

  • Install the first site as usual.
  • After installing, add these constants to the wp-config.php. Hardcode the table prefix.
  • Create a second site and copy the wp-config.php from the first site into it. And change the $table_prefix for the second site. Meanwhile, the user table prefix should remain the same as it was during the first installation (hardcoded).
  • Install the second site. In this case, you will not be prompted to enter user information.
  • After the installation, when trying to log into the admin panel, you will see an error that you do not have sufficient rights. This is because the wp_usermeta table has an option wp_capabilities where the prefix must match the current $table_prefix. But the second installation has a different prefix, so for the second installation, it's as if this option does not exist. The WP-Orphanage Extended plugin will help resolve this issue.

FS_METHOD - WordPress Update Constants

Note: Define as many constants as necessary to solve update issues.

The most common reasons for the need to define the following constants are:

  • Hosting work with a special setup involving symlinks. There may be a requirement to define constants related to paths (FTP_BASE, FTP_CONTENT_DIR, and FTP_PLUGIN_DIR). Often it is enough to simply define the base.

  • Some PHP versions come with a PHP FTP extension that is incompatible with some FTP servers. In these rare situations, you may need to define FS_METHOD as "ftpsockets".

Below are the valid constants for WordPress updates:

  • FS_METHOD determines the file system operation method. It can only be: "direct", "ssh2", "ftpext", or "ftpsockets". Typically, this parameter should only be altered if there are update issues. If you've changed this parameter and it didn't help, revert it back or remove it.

    • (1st preference) direct - PHP works with the file system directly. This can lead to security problems on poorly configured servers. It is selected automatically if possible.
    • (2nd preference) ssh2 - uses the SSH PHP extension if it's installed.
    • (3rd preference) ftpext - forces the use of PHP's FTP extension for FTP access.
    • (4th preference) ftpsockets - uses PHP's Sockets class for FTP access.
  • FTP_BASE - full path to the WordPress installation folder (ABSPATH).

  • FTP_CONTENT_DIR - full path to the wp-content folder.

  • FTP_PLUGIN_DIR - full path to the plugins folder in the WordPress installation.

  • FTP_PUBKEY - full path to your SSH public key.

  • FTP_PRIKEY - full path to your SSH private key.

  • FTP_USER is either the FTP username or SSH username. They are likely the same, but use whichever is appropriate for the type of update you wish to perform.

  • FTP_PASS is the password for the username entered in FTP_USER. If you are using SSH public key authentication, this parameter may not be necessary.

  • FTP_HOST - the host:port combination for your SSH/FTP server. The default FTP port is 21, and the SSH port is 22. It is not mandatory to specify them.

  • FTP_SSL - TRUE for an SSL connection if it's supported by the underlying transport (not available on all servers). This refers to "Secure FTP," not SSH SFTP.

Example constant values:

define( 'FS_METHOD', 'ftpext' );
define( 'FTP_BASE', '/path/to/wordpress/' );
define( 'FTP_CONTENT_DIR', '/path/to/wordpress/wp-content/' );
define( 'FTP_PLUGIN_DIR ', '/path/to/wordpress/wp-content/plugins/' );
define( 'FTP_PUBKEY', '/home/username/.ssh/id_rsa.pub' );
define( 'FTP_PRIKEY', '/home/username/.ssh/id_rsa' );
define( 'FTP_USER', 'username' );
define( 'FTP_PASS', 'password' );
define( 'FTP_HOST', 'ftp.example.org' );
define( 'FTP_SSL', false );

In some configurations, it may be necessary to set the value of FTP_HOST to localhost to avoid problems with a 503 error when trying to update plugins or WP itself.

Enabling SSH Access for Updates

There are two ways to update via SSH2.

  • The first is to use the SSH SFTP Updater Support plugin.
  • The second is to use the built-in SSH2 update program by installing the pecl SSH2 extension.

To install the pecl SSH2 extension, execute a command similar to the following, or contact your hosting provider for its installation:

pecl install ssh2

After installing the pecl ssh2 extension, it's necessary to change the PHP configuration for the automatic loading of this extension.

pecl comes included in the pear package in most Linux distributions.

To install pecl in Redhat/Fedora/CentOS:

yum -y install php-pear

To install pecl in Debian/Ubuntu:

apt-get install php-pear

It's recommended to use a private key not protected by a passphrase. There are numerous reports suggesting that private keys protected by passphrase do not work properly. If you decide to use a private key protected by a passphrase, you will need to enter the passphrase for the private key in FTP_PASS or in the "Password" field of the presented credentials.

DO_NOT_UPGRADE_GLOBAL_TABLES

Default: not set

Defining the constant DO_NOT_UPGRADE_GLOBAL_TABLES prevents the dbDelta() function and update functions from executing costly queries to global tables.

Sites with large global tables (especially users and usermeta) and sites that share user tables with bbPress and other WordPress installations may prevent altering these tables during an update by setting DO_NOT_UPGRADE_GLOBAL_TABLES to true.

As performing ALTER as well as unrestricted DELETE or UPDATE can take a long time, large sites typically want to avoid them during an update and manage necessary updates on their own.

Furthermore, if user tables are shared with multiple bbPress and WordPress installations, it might be wise to select one site to act as the master for updates.

The function wp_should_upgrade_global_tables() is used to check if global tables need updating in the update functions.

Multisite

WP_ALLOW_MULTISITE

Default: false.

Enables multisite functionality. For more information, see Multisite Installation.

define( 'WP_ALLOW_MULTISITE', false );

NOBLOGREDIRECT

Used to redirect the browser if a visitor tries to access a non-existent subsite:

define( 'NOBLOGREDIRECT', 'http://example.com' );

Redirect to the main site of the network:

define( 'NOBLOGREDIRECT', '%siteurl%' );

For the main site of the network, if this constant is set, all 404 pages will be redirected to the URL specified here.

For a more correct redirect, it is recommended to use the ms_site_not_found hook instead of this constant.

Example wp-config.php

An example of wp-config.php is indicated in the file wp-config-sample.php. Let's take a look at its code:

GitHub
<?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file during the installation.
 * You don't have to use the website, you can copy this file to "wp-config.php"
 * and fill in the values.
 *
 * This file contains the following configurations:
 *
 * * Database settings
 * * Secret keys
 * * Database table prefix
 * * ABSPATH
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/
 *
 * @package WordPress
 */

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'database_name_here' );

/** Database username */
define( 'DB_USER', 'username_here' );

/** Database password */
define( 'DB_PASSWORD', 'password_here' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

/**#@+
 * Authentication unique keys and salts.
 *
 * Change these to different unique phrases! You can generate these using
 * the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
 *
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
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' );

/**#@-*/

/**
 * WordPress database table prefix.
 *
 * You can have multiple installations in one database if you give each
 * a unique prefix. Only numbers, letters, and underscores please!
 *
 * At the installation time, database tables are created with the specified prefix.
 * Changing this value after WordPress is installed will make your site think
 * it has not been installed.
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#table-prefix
 */
$table_prefix = 'wp_';

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 *
 * For information on other constants that can be used for debugging,
 * visit the documentation.
 *
 * @link https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/
 */
define( 'WP_DEBUG', false );

/* Add any custom values between this line and the "stop editing" line. */



/* That's all, stop editing! Happy publishing. */

/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

--

See also: https://developer.wordpress.org/apis/wp-config-php/