Securing MySQL/MariaDB with mysql_secure_installation

Learn how to secure your MySQL/MariaDB database using the mysql_secure_installation script to remove default vulnerabilities and implement security.

Securing MySQL/MariaDB with mysql_secure_installation

Table of Contents

1. [Introduction](#introduction) 2. [Prerequisites](#prerequisites) 3. [Understanding mysql_secure_installation](#understanding-mysql_secure_installation) 4. [Installation Process](#installation-process) 5. [Security Configuration Steps](#security-configuration-steps) 6. [Command Options and Parameters](#command-options-and-parameters) 7. [Best Practices](#best-practices) 8. [Troubleshooting](#troubleshooting) 9. [Advanced Security Measures](#advanced-security-measures) 10. [Verification and Testing](#verification-and-testing)

Introduction

The mysql_secure_installation script is a crucial security utility that comes bundled with MySQL and MariaDB installations. This interactive script helps database administrators implement essential security measures by removing default insecure settings and configurations that could potentially expose the database to unauthorized access or attacks.

When MySQL or MariaDB is initially installed, it often comes with default settings that prioritize ease of setup over security. These default configurations may include anonymous user accounts, test databases accessible to all users, and weak authentication mechanisms. The mysql_secure_installation script addresses these vulnerabilities systematically.

Prerequisites

Before running the mysql_secure_installation script, ensure the following requirements are met:

| Requirement | Description | Command to Verify | |-------------|-------------|-------------------| | MySQL/MariaDB Installation | Database server must be installed and running | systemctl status mysql or systemctl status mariadb | | Root Access | Administrative privileges on the system | sudo whoami | | Database Service Running | MySQL/MariaDB service must be active | ps aux \| grep mysql | | Network Access | Ability to connect to database locally | mysql -u root -p |

System Requirements

- Operating System: Linux, macOS, or Windows with MySQL/MariaDB installed - Memory: Minimum 512MB RAM (recommended 1GB or more) - Disk Space: At least 100MB free space for logs and temporary files - Network: Local network access to database port (default 3306)

Understanding mysql_secure_installation

The mysql_secure_installation script performs several critical security enhancements:

Security Improvements Overview

| Security Measure | Default State | Secure State | Impact | |------------------|---------------|--------------|--------| | Root Password | Often empty or weak | Strong password required | Prevents unauthorized root access | | Anonymous Users | Present by default | Removed | Eliminates unnamed user access | | Remote Root Login | Usually enabled | Disabled | Restricts root access to localhost | | Test Database | Created by default | Removed | Eliminates potential attack vector | | Password Validation | Disabled | Enabled (optional) | Enforces strong password policies |

Script Functionality

The script operates by connecting to the MySQL/MariaDB server and executing SQL commands to modify user accounts, databases, and privilege tables. It provides an interactive interface that guides administrators through each security configuration step.

Installation Process

Step 1: Verify Database Installation

First, confirm that MySQL or MariaDB is properly installed and running:

`bash

For MySQL

sudo systemctl status mysql

For MariaDB

sudo systemctl status mariadb

Alternative verification

mysqladmin version `

Step 2: Start Database Service

If the service is not running, start it:

`bash

For MySQL

sudo systemctl start mysql sudo systemctl enable mysql

For MariaDB

sudo systemctl start mariadb sudo systemctl enable mariadb `

Step 3: Execute mysql_secure_installation

Run the security script with appropriate privileges:

`bash sudo mysql_secure_installation `

Security Configuration Steps

Initial Connection and Authentication

When you execute the script, it first attempts to connect to the database server:

` NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!

In order to log into MySQL to secure it, we'll need the current password for the root user. If you've just installed MySQL, and you haven't set the root password yet, the password will be blank, so you should just press enter here.

Enter current password for root (enter for none): `

Note: If this is a fresh installation, the root password is typically empty. Press Enter to continue.

Step 1: Set Root Password

The script will prompt you to set a root password if one doesn't exist:

` Setting the root password ensures that nobody can log into the MySQL root user without the proper authorisation.

Set root password? [Y/n] Y New password: Re-enter new password: Password updated successfully! Reloading privilege tables.. ... Success! `

Important Considerations: - Choose a strong password with mixed case letters, numbers, and special characters - Minimum length should be 12-16 characters - Avoid dictionary words or personal information - Store the password securely

Step 2: Remove Anonymous Users

Anonymous users allow anyone to log into MySQL without a user account:

` By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment.

Remove anonymous users? [Y/n] Y ... Success! `

Security Impact: Removing anonymous users prevents unauthorized access and ensures all connections are authenticated with specific user credentials.

Step 3: Disable Remote Root Login

This step prevents root login from remote machines:

` Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] Y ... Success! `

Security Rationale: Remote root access increases attack surface. Administrative tasks should be performed locally or through dedicated administrative accounts.

Step 4: Remove Test Database

The default test database is accessible to all users:

` By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment.

Remove test database and access to it? [Y/n] Y - Dropping test database... ... Success! - Removing privileges on test database... ... Success! `

Security Benefit: Eliminates a potential attack vector where malicious users could exploit the test database to gain system information or escalate privileges.

Step 5: Reload Privilege Tables

The final step reloads the privilege tables to ensure all changes take effect:

` Reloading the privilege tables will ensure that all changes made so far will take effect immediately.

Reload privilege tables now? [Y/n] Y ... Success!

All done! If you've completed all of the above steps, your MySQL installation should now be secure.

Thanks for using MySQL! `

Command Options and Parameters

Basic Command Syntax

`bash mysql_secure_installation [OPTIONS] `

Available Options

| Option | Description | Example Usage | |--------|-------------|---------------| | --help | Display help information | mysql_secure_installation --help | | --host=hostname | Connect to specific host | mysql_secure_installation --host=localhost | | --port=port_num | Use specific port number | mysql_secure_installation --port=3306 | | --protocol=type | Connection protocol | mysql_secure_installation --protocol=TCP | | --socket=path | Unix socket file path | mysql_secure_installation --socket=/var/run/mysqld/mysqld.sock | | --user=username | MySQL username | mysql_secure_installation --user=root |

Advanced Usage Examples

#### Remote Database Server

`bash mysql_secure_installation --host=192.168.1.100 --port=3306 --user=root `

#### Custom Socket Connection

`bash mysql_secure_installation --socket=/tmp/mysql.sock `

#### Specific Protocol

`bash mysql_secure_installation --protocol=TCP --host=localhost --port=3306 `

Best Practices

Password Security

| Practice | Description | Implementation | |----------|-------------|----------------| | Complexity | Use mixed character types | Include uppercase, lowercase, numbers, symbols | | Length | Minimum 12 characters | Prefer 16+ characters for critical systems | | Uniqueness | Avoid reusing passwords | Generate unique passwords for each service | | Storage | Secure password management | Use password managers or encrypted storage | | Rotation | Regular password changes | Change passwords quarterly or after incidents |

Post-Installation Security Measures

#### 1. Create Dedicated Administrative Users

Instead of using root for daily operations, create specific administrative accounts:

`sql -- Create administrative user CREATE USER 'dbadmin'@'localhost' IDENTIFIED BY 'strong_password_here'; GRANT ALL PRIVILEGES ON . TO 'dbadmin'@'localhost' WITH GRANT OPTION; FLUSH PRIVILEGES; `

#### 2. Configure Firewall Rules

Restrict database access at the network level:

`bash

Allow MySQL only from localhost

sudo ufw allow from 127.0.0.1 to any port 3306

Allow from specific IP range

sudo ufw allow from 192.168.1.0/24 to any port 3306 `

#### 3. Enable SSL/TLS Encryption

Configure encrypted connections:

`sql -- Check SSL status SHOW VARIABLES LIKE 'have_ssl';

-- Require SSL for users ALTER USER 'username'@'hostname' REQUIRE SSL; `

Configuration File Security

#### MySQL Configuration (/etc/mysql/mysql.conf.d/mysqld.cnf)

`ini [mysqld]

Network security

bind-address = 127.0.0.1 port = 3306 skip-networking = false

Authentication

default-authentication-plugin = mysql_native_password

Logging

log-error = /var/log/mysql/error.log general-log = 1 general-log-file = /var/log/mysql/mysql.log

Security settings

local-infile = 0 skip-show-database `

Troubleshooting

Common Issues and Solutions

| Issue | Symptoms | Solution | |-------|----------|----------| | Access Denied | "ERROR 1045: Access denied for user 'root'@'localhost'" | Reset root password using --skip-grant-tables | | Service Not Running | "Can't connect to local MySQL server" | Start MySQL service: sudo systemctl start mysql | | Socket Connection Error | "Can't connect to local MySQL server through socket" | Check socket file location and permissions | | Permission Denied | Script fails to execute | Run with sudo privileges |

Detailed Troubleshooting Steps

#### 1. Root Password Reset

If you've forgotten the root password:

`bash

Stop MySQL service

sudo systemctl stop mysql

Start MySQL in safe mode

sudo mysqld_safe --skip-grant-tables --skip-networking &

Connect without password

mysql -u root

Reset password

USE mysql; UPDATE user SET authentication_string=PASSWORD('new_password') WHERE User='root'; FLUSH PRIVILEGES; EXIT;

Restart MySQL normally

sudo systemctl restart mysql `

#### 2. Socket File Issues

Check socket file location and permissions:

`bash

Find socket file

sudo find /var -name "*.sock" -type s 2>/dev/null

Check permissions

ls -la /var/run/mysqld/mysqld.sock

Fix permissions if needed

sudo chown mysql:mysql /var/run/mysqld/mysqld.sock sudo chmod 755 /var/run/mysqld/mysqld.sock `

#### 3. Service Start Problems

Diagnose service startup issues:

`bash

Check service status

sudo systemctl status mysql

View detailed logs

sudo journalctl -u mysql -f

Check error logs

sudo tail -f /var/log/mysql/error.log `

Advanced Security Measures

Database-Level Security Enhancements

#### 1. User Account Management

Create role-based user accounts with minimal privileges:

`sql -- Create application user with limited privileges CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'secure_password'; GRANT SELECT, INSERT, UPDATE, DELETE ON application_db.* TO 'appuser'@'localhost';

-- Create read-only user for reporting CREATE USER 'readonly'@'localhost' IDENTIFIED BY 'secure_password'; GRANT SELECT ON application_db.* TO 'readonly'@'localhost';

-- Create backup user CREATE USER 'backup'@'localhost' IDENTIFIED BY 'secure_password'; GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON . TO 'backup'@'localhost'; `

#### 2. Network Security Configuration

Implement network-level restrictions:

`sql -- Restrict user to specific IP addresses CREATE USER 'webuser'@'192.168.1.%' IDENTIFIED BY 'secure_password';

-- Allow access only from application servers CREATE USER 'apiuser'@'10.0.1.100' IDENTIFIED BY 'secure_password'; `

#### 3. Audit Logging

Enable comprehensive audit logging:

`ini

Add to MySQL configuration

[mysqld]

Enable general query log

general-log = 1 general-log-file = /var/log/mysql/general.log

Enable slow query log

slow-query-log = 1 slow-query-log-file = /var/log/mysql/slow.log long-query-time = 2

Enable binary logging

log-bin = /var/log/mysql/mysql-bin.log expire-logs-days = 7 `

Monitoring and Alerting

#### Performance Monitoring Queries

`sql -- Monitor failed login attempts SELECT * FROM mysql.general_log WHERE command_type = 'Connect' AND argument LIKE '%Access denied%' ORDER BY event_time DESC LIMIT 10;

-- Check user connections SELECT user, host, db, command, time, state FROM information_schema.processlist WHERE user != 'system user';

-- Monitor privilege changes SELECT * FROM mysql.general_log WHERE argument LIKE '%GRANT%' OR argument LIKE '%REVOKE%' ORDER BY event_time DESC; `

Verification and Testing

Security Validation Checklist

| Security Check | Command/Method | Expected Result | |----------------|----------------|-----------------| | Root password set | mysql -u root | Should prompt for password | | Anonymous users removed | SELECT User, Host FROM mysql.user WHERE User = ''; | Empty result set | | Remote root disabled | SELECT User, Host FROM mysql.user WHERE User = 'root'; | Only localhost entries | | Test database removed | SHOW DATABASES; | No 'test' database listed | | SSL enabled | SHOW VARIABLES LIKE 'have_ssl'; | Value should be 'YES' |

Comprehensive Security Test

Execute this verification script to validate security configuration:

`bash #!/bin/bash

echo "=== MySQL Security Verification ==="

Test 1: Anonymous user access

echo "Testing anonymous access..." mysql -u '' -e "SELECT 1;" 2>/dev/null && echo "FAIL: Anonymous access allowed" || echo "PASS: Anonymous access denied"

Test 2: Root remote access

echo "Testing remote root access..." mysql -u root -h 127.0.0.1 -p -e "SELECT 1;" 2>/dev/null && echo "WARNING: Remote root access possible" || echo "PASS: Remote root access denied"

Test 3: Test database existence

echo "Checking for test database..." mysql -u root -p -e "USE test;" 2>/dev/null && echo "FAIL: Test database exists" || echo "PASS: Test database removed"

Test 4: Password policy

echo "Checking password validation..." mysql -u root -p -e "SHOW VARIABLES LIKE 'validate_password%';"

echo "=== Security verification complete ===" `

Performance Impact Assessment

Monitor the performance impact of security measures:

`sql -- Check connection overhead SHOW STATUS LIKE 'Connections'; SHOW STATUS LIKE 'Aborted_connects';

-- Monitor SSL overhead SHOW STATUS LIKE 'Ssl_cipher'; SHOW STATUS LIKE 'Ssl_sessions_reused';

-- Audit log impact SHOW VARIABLES LIKE 'general_log'; SHOW VARIABLES LIKE 'log_output'; `

Maintenance and Updates

#### Regular Security Maintenance Tasks

1. Password Rotation Schedule `bash # Create automated password rotation script #!/bin/bash NEW_PASSWORD=$(openssl rand -base64 32) mysql -u root -p -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$NEW_PASSWORD';" echo "Password updated on $(date)" >> /var/log/mysql-security.log `

2. User Account Auditing `sql -- Monthly user account review SELECT User, Host, account_locked, password_expired, password_last_changed FROM mysql.user ORDER BY password_last_changed; `

3. Privilege Review `sql -- Quarterly privilege audit SELECT User, Host, Db, Select_priv, Insert_priv, Update_priv, Delete_priv FROM mysql.db ORDER BY User, Db; `

The mysql_secure_installation script provides a solid foundation for database security, but it should be considered the first step in a comprehensive security strategy. Regular monitoring, updates, and adherence to security best practices are essential for maintaining a secure MySQL or MariaDB environment in production systems.

Tags

  • MariaDB
  • MySQL
  • database-security
  • system-administration

Related Articles

Popular Technical Articles & Tutorials

Explore our comprehensive collection of technical articles, programming tutorials, and IT guides written by industry experts:

Browse all 8+ technical articles | Read our IT blog

Securing MySQL/MariaDB with mysql_secure_installation