MySQLi storage engine

In Wordfence 7.4.0, an alternate data storage engine has been added to the firewall, so that sites can store firewall data in the MySQL database instead of using files in "wp-content/wflogs/".

Switching to the MySQLi storage engine

We only recommend using this option if your site is unable to read and write to the firewall files consistently, or if your host uses multiple web servers that do not share the same filesystem, since better performance and efficient resource usage are likely when using the default file-based storage on most hosts. Some examples where using the MySQLi storage engine may be useful include:

  • Multiple web servers behind a load balancer, without a shared filesystem
  • Servers where some paths are not always writable, including “wp-content/wflogs/”
  • Servers where file locking is not enforced on NFS filesystems
  • Auto-scaling servers without a shared filesystem

This change is automatic on hosting at the hosting provider “WP Engine” since the file-based method is not compatible with their configuration.

On other hosts, you will need to add this to your “wordfence-waf.php” file:

define('WFWAF_STORAGE_ENGINE', 'mysqli');

If you have not optimized the firewall, you could add the line to the WordPress “wp-config.php” file as described on our constants help page instead. A number of other constants are also explained, in case Wordfence cannot connect to your database automatically using the WordPress “wp-config.php” file, or if you need to change MySQL’s SSL/TLS settings.

For example, in the “wordfence-waf.php” file, the line should be added after the opening PHP tag, but before any other code:

<?php
// Before removing this file, please verify the PHP ini setting `auto_prepend_file` does not point to this.
define('WFWAF_STORAGE_ENGINE', 'mysqli');

if (file_exists(__DIR__ . '/wp-content/plugins/wordfence/waf/bootstrap.php')) {
define("WFWAF_LOG_PATH", __DIR__ . '/wp-content/wflogs/');
include_once __DIR__ . '/wp-content/plugins/wordfence/waf/bootstrap.php';
}

If either your “wordfence-waf.php” file or “wp-content” directory is not in the site’s document root directory, you may need to adjust the path to “wp-content” used in this example.

After this change is made, the firewall will start with fresh settings. You may need to switch from “Learning Mode” mode to “Enabled and Protecting” mode on the “Firewall Options” page if you want to skip Learning Mode. Otherwise, Learning Mode will run for one week as it does in a new installation.

Optional MySQLi storage engine constants

If your database settings cannot be read automatically from wp-config.php, you can set these constants in wordfence-waf.php. This may be necessary if you set the WordPress database constants dynamically in your dev/staging/production environments, or if you load them from environment variables or other files. Setting these “WFWAF_DB_” constants will override the values read from wp-config.php, when the WAF connects to the database, and they will not affect the database connection that WordPress itself uses.

Note: The WAF must be able to connect to the database. Be sure these values are correct, since the site will fail to load if incorrect values are used. If you have trouble entering them, commenting them out or removing them temporarily will restore the site’s operation.

Example:
define('WFWAF_DB_NAME', 'db_name');
define('WFWAF_DB_USER', 'db_user');
define('WFWAF_DB_PASSWORD', 'db_password');
define('WFWAF_DB_HOST', '127.0.0.1');
define('WFWAF_DB_CHARSET', 'utf8');
define('WFWAF_DB_COLLATE', '');
define('WFWAF_TABLE_PREFIX', 'wp_');

WFWAF_MYSQL_CLIENT_FLAGS

If you use MYSQL_CLIENT_FLAGS to connect WordPress to your database via SSL/TLS, you should also set WFWAF_MYSQL_CLIENT_FLAGS in wordfence-waf.php, so that the WAF will also use SSL/TLS. Supported values are MYSQLI_CLIENT_SSL, and optionally MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT if you do not need the server’s certificate checked.

Example:
define('WFWAF_MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL | MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT);

MySQL also accepts additional SSL/TLS settings. These constants are optional and are passed to mysqli_ssl_set(). You should use the same settings that you use for WordPress itself, if your site needs them. Otherwise, do not set them.

Example:
define('WFWAF_DB_SSL_KEY', '/path/to/client-key.pem');
define('WFWAF_DB_SSL_CERTIFICATE', '/path/to/client-cert.pem');
define('WFWAF_DB_SSL_CA_CERTIFICATE', '/path/to/ca-files/ca.pem');
define('WFWAF_DB_SSL_CA_PATH', '/path/to/ca-files/');
define('WFWAF_DB_SSL_CIPHER_ALGOS', 'DHE-RSA-AES128-SHA');

Reverting back to the file-based firewall data storage engine

You can also revert back to the file-based firewall data storage engine as follows.

You will need to remove the Wordfence “wflogs” directory located below:

~/wp-content/wflogs

Then you will need to remove the constant that was added to switch to the MySQLi firewall data storage engine.

Loading any page on your site will automatically create a new Wordfence “wflogs” directory. After these changes are made, the firewall will start with fresh settings. You may need to switch from “Learning Mode” mode to “Enabled and Protecting” mode on the “Firewall Options” page if you want to skip Learning Mode. Otherwise, Learning Mode will run for one week as it does in a new installation.

Using WP-CLI with the MySQLi storage engine

Using WP-CLI with the MySQLi storage engine can potentially cause the generation of PHP Warning errors. To prevent this you can add this line of code to your WordPress “wp-config.php” configuration file:

if( ! defined('WFWAF_STORAGE_ENGINE')) { define('WFWAF_STORAGE_ENGINE', 'mysqli'); }

Our line of code must be added above either one of the two comment lines listed below (based on the version of WordPress you have installed):

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

/* Custom Values must appear above this line. That's all, stop editing! Happy publishing. */

If you are hosted at WP Engine then they are known to use this custom comment line listed below and our line of code must be added above it:

# That's It. Pencils down