How to Secure MySQL on RHEL 7
A default MySQL installation leaves several security gaps that can expose your databases to unauthorized access, data theft, or privilege escalation. On Red Hat Enterprise Linux 7, taking deliberate steps to harden MySQL immediately after installation is essential for any production or internet-facing system. This guide walks through the complete MySQL security hardening process: running the built-in security script, auditing user privileges, restricting network access, enabling encrypted connections, and activating the audit log plugin. Following these steps reduces your attack surface significantly and brings your installation closer to compliance with security frameworks such as CIS Benchmarks and PCI-DSS.
Prerequisites
- RHEL 7 server with MySQL 5.6 or 5.7 installed (via the official MySQL Community or Red Hat Software Collections repository)
- Root or sudo access on the server
- MySQL service running:
systemctl status mysqld - The temporary root password from
/var/log/mysqld.logif using MySQL 5.7
Step 1: Run mysql_secure_installation
MySQL ships with a helper script called mysql_secure_installation that automates the most common hardening steps. Run it as root immediately after installation and before creating any application databases.
sudo mysql_secure_installation
The script will prompt you through the following decisions:
- Set or change the root password — Choose a strong password meeting MySQL’s validate_password policy (uppercase, lowercase, digit, special character, minimum 8 characters).
- Remove anonymous users — Answer
Y. Anonymous users allow anyone to connect to MySQL without credentials, which is unacceptable in production. - Disallow remote root login — Answer
Y. Root should only connect fromlocalhost. Remote administration should use a dedicated user with limited privileges. - Remove test database — Answer
Y. Thetestdatabase is accessible to all users by default and serves no production purpose. - Reload privilege tables — Answer
Yto apply changes immediately.
After the script completes, verify you can still log in as root locally:
mysql -u root -p
Step 2: Audit User Privileges
After securing defaults, audit every account in the system to understand who has access to what. Connect as root and query the user table:
mysql -u root -p
SELECT User, Host, authentication_string, plugin FROM mysql.user;
Look for:
- Users with
Host = '%'(wildcard remote access) — restrict these to specific IP addresses where possible - Accounts with empty passwords or using the deprecated
mysql_old_passwordplugin - Service accounts with more privileges than they need
Check global privileges for each user:
SELECT User, Host, Super_priv, Grant_priv, File_priv, Process_priv
FROM mysql.user
WHERE Super_priv = 'Y' OR Grant_priv = 'Y';
Revoke unnecessary privileges and remove stale accounts:
-- Revoke SUPER from an application user
REVOKE SUPER ON *.* FROM 'appuser'@'192.168.1.10';
-- Drop accounts no longer in use
DROP USER 'olduser'@'localhost';
-- Flush to apply
FLUSH PRIVILEGES;
Step 3: Restrict the bind-address in my.cnf
By default, MySQL listens on all network interfaces. If your application server and database server are on the same host, or if you use a private network, restrict MySQL to a specific IP to prevent exposure on public interfaces.
Edit the MySQL configuration file:
sudo vi /etc/my.cnf
Under the [mysqld] section, add or update:
[mysqld]
bind-address = 127.0.0.1
If your application connects from a separate server on a private network, use that private IP instead:
bind-address = 10.0.0.5
Restart MySQL to apply the change:
sudo systemctl restart mysqld
Confirm MySQL is now only listening on the intended address:
ss -tlnp | grep 3306
Step 4: Enable require_secure_transport (SSL/TLS)
For MySQL 5.7, you can require all client connections to use SSL, preventing plaintext credential transmission over the network. First verify SSL is available:
mysql -u root -p -e "SHOW VARIABLES LIKE '%ssl%';"
MySQL 5.7 auto-generates SSL certificates on first start in /var/lib/mysql/. To enforce SSL for all connections, add to /etc/my.cnf:
[mysqld]
require_secure_transport = ON
To enforce SSL for a specific user only:
ALTER USER 'appuser'@'192.168.1.10' REQUIRE SSL;
FLUSH PRIVILEGES;
Restart and test:
sudo systemctl restart mysqld
mysql -u appuser -p -h 192.168.1.10 --ssl-mode=REQUIRED
Step 5: Enable the MySQL Audit Log Plugin
The audit log plugin records all connections and SQL statements, providing a trail for security investigations and compliance reporting. It is available in MySQL Enterprise Edition, but the open-source equivalent audit_log plugin ships with MySQL Community in 5.7.
Install the plugin from within MySQL:
mysql -u root -p
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
Verify installation:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM information_schema.PLUGINS
WHERE PLUGIN_NAME = 'audit_log';
Add audit log settings to /etc/my.cnf:
[mysqld]
plugin-load-add = audit_log.so
audit_log_file = /var/log/mysql/audit.log
audit_log_format = JSON
audit_log_policy = ALL
Create the log directory and set correct ownership:
sudo mkdir -p /var/log/mysql
sudo chown mysql:mysql /var/log/mysql
sudo systemctl restart mysqld
Confirm the audit log is being written:
sudo tail -f /var/log/mysql/audit.log
Step 6: Additional Hardening Recommendations
- Enable the validate_password plugin to enforce strong passwords for all accounts:
INSTALL PLUGIN validate_password SONAME 'validate_password.so'; SET GLOBAL validate_password_policy = STRONG; - Disable LOCAL INFILE to prevent users from reading arbitrary server files via SQL:
[mysqld] local_infile = 0 - Set a connection limit per user to reduce risk from credential stuffing:
ALTER USER 'appuser'@'%' WITH MAX_USER_CONNECTIONS 10; - Use SELinux — RHEL 7 ships with SELinux in enforcing mode. MySQL’s SELinux policy is installed by default; confirm it is active with
sestatusand never disable it for convenience. - Open only the required firewall port and restrict it to known source IPs:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" port port="3306" protocol="tcp" accept' sudo firewall-cmd --reload
Conclusion
Securing MySQL on RHEL 7 is not a one-time task but an ongoing practice. By running mysql_secure_installation, removing anonymous accounts, restricting remote root access, binding MySQL to a specific interface, enforcing SSL transport, enabling audit logging, and applying SELinux and firewall controls, you dramatically reduce the risk of unauthorized access and data exposure. Revisit user privileges regularly, rotate passwords on a schedule, and monitor the audit log for suspicious activity. Combined with OS-level hardening, these measures form a strong defense-in-depth strategy for your MySQL databases.