MySQL Secure Deployment Guide  /  Post Installation Setup

Chapter 5 Post Installation Setup

Post-installation setup involves creating a safe directory for import and export operations, configuring server startup options, initializing the data directory, starting MySQL using systemd, resetting the password for the MySQL root@localhost user account, and running a few tests to ensure that the server is working.

Creating a Safe Directory For Import and Export Operations

MySQL users with the FILE privilege have permission to read and write files on the server host using LOAD DATA INFILE and SELECT ... INTO OUTFILE statements, and the LOAD_FILE() function. By default, a user who has the FILE privilege can read any file on the server host that is either world-readable or readable by the MySQL server. (This implies the user can read any file in any database directory, because the server can access any of those files.) The FILE privilege also enables the user to create new files in any directory where the MySQL server has write access. This includes the server data directory containing the files that implement the privilege tables.

To limit the scope of the FILE privilege, create a directory that users with the FILE privilege can safely use for import and export operations. In this deployment, the directory created is named mysql-files and is located under the data directory. In a later step, when server startup options are configured, the secure_file_priv option is set to the mysql-files directory.

Press CTRL+C to copy
$> cd /usr/local/mysql $> mkdir mysql-files $> chown mysql:mysql mysql-files $> chmod 750 mysql-files

Configuring Server Startup Options

Specify options that the MySQL server should use at startup by placing them in a MySQL configuration file. If you do not do this, the server starts with its default settings (see Server Configuration Defaults).

Note

Certain InnoDB options can only be configured before initializing the data directory. Among these options are innodb_data_home_dir, innodb_data_file_path, innodb_log_file_size, innodb_log_group_home_dir, and innodb_page_size. If you do not want to use default values for these options, set your own values in the MySQL configuration file before initializing the data directory. This deployment uses default InnoDB configuration settings. For more information, see InnoDB Startup Configuration.

  1. To create a MySQL configuration file, issue these commands as root:

    Press CTRL+C to copy
    $> cd /etc $> touch my.cnf $> chown root:root my.cnf $> chmod 644 my.cnf
    Note

    If there is an existing my.cnf configuration file in the same location that belongs to another MySQL instance, use a different name for your configuration file.

  2. Under a [mysqld] group entry, set the datadir, socket, port, log-error options for the instance. If there are other MySQL installations on the host, ensure that the values for these options are unique to this instance. This deployment uses the default values.

    Press CTRL+C to copy
    [mysqld] datadir=/usr/local/mysql/data socket=/tmp/mysql.sock port=3306 log-error=/usr/local/mysql/data/localhost.localdomain.err
    Important

    The location of the MySQL data directory is critically important to the security of a MySQL installation. In addition to user data, the data directory contains data dictionary and system tables, which store sensitive information about database objects, users, privileges, and so on. Following the principle of least privilege, system user access to the data directory should be as restrictive as possible. The size of the file system where the data directory resides should also be considered. Ensure that the file system can accommodate the anticipated size of your data. The deployment described in this guide places the data directory in the default location (/usr/local/mysql/data), and access to the directory is limited to the mysql operating system user account.

  3. Set the user option to ensure that the server is started as the unprivileged mysql user account. For security reasons, it is important to avoid running the server as the operating system root user.

    Press CTRL+C to copy
    user=mysql
  4. If you intend to permit import and export operations, set the secure_file_priv system variable to the path of the mysql-files directory that you created previously. This option limits file import and export operations, such as those performed by the LOAD DATA and SELECT ... INTO OUTFILE statements and the LOAD_FILE() function, to the specified directory. If you do not intend to permit import or export operations, set secure_file_priv to NULL, which disables import and export operations entirely. NULL is the default setting.

    Press CTRL+C to copy
    secure_file_priv=/usr/local/mysql/mysql-files
  5. To avoid potential security issues with the LOCAL version of LOAD DATA, ensure that local_infile is disabled, which it is by default.

    Press CTRL+C to copy
    local_infile=OFF

    For more information, see Security Considerations for LOAD DATA LOCAL.

After completing the steps above, the configuration file should contain these settings, assuming you have not added others:

Press CTRL+C to copy
[mysqld] datadir=/usr/local/mysql/data socket=/tmp/mysql.sock port=3306 log-error=/usr/local/mysql/data/localhost.localdomain.err user=mysql secure_file_priv=/usr/local/mysql/mysql-files local_infile=OFF

Initializing the Data Directory

After installing MySQL, you must initialize the data directory, which includes the mysql system database and its tables, including grant tables, server-side help tables, and time zone tables. Initialization also creates the root@localhost superuser account and the InnoDB system tablespace and related data structures required to manage InnoDB tables.

To initialize the data directory:

  1. Change location to the top-level directory of the MySQL installation, create the data directory, and grant ownership to the mysql user.

    Press CTRL+C to copy
    $> cd /usr/local/mysql $> mkdir data $> chmod 750 data $> chown mysql:mysql data
    Note

    Data directory ownership is assigned to the mysql user, but most of the MySQL installation remains owned by root. Other exceptions are the error log file, the mysql-files directory, the pid file, and socket file, to which the mysql user must have write access. Files and resources that the mysql user requires read access to include configuration files (e.g., /etc/my.cnf) and the MySQL binaries (/usr/local/mysql/bin).

  2. Initialize the data directory.

    Press CTRL+C to copy
    $> cd /usr/local/mysql $> bin/mysqld --defaults-file=/etc/my.cnf --initialize

    Initialization output is printed to the error log (/usr/local/mysql/data/localhost.localdomain.err) and appears similar to the output shown below. The output includes an initial random password for the root@localhost account. The password is required later to reset the root@localhost password.

    Press CTRL+C to copy
    2018-05-02T17:47:49.806563Z 0 [System] [MY-013169] [Server] /usr/local/mysql-commercial-8.0.11-linux-glibc2.12-x86_64/bin/mysqld (mysqld 8.0.11-commercial) initializing of server in progress as process 16039 2018-05-02T17:47:54.083010Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: uZmx9ihSd2;. 2018-05-02T17:47:56.225881Z 0 [System] [MY-013170] [Server] /usr/local/mysql-commercial-8.0.11-linux-glibc2.12-x86_64/bin/mysqld (mysqld 8.0.11-commercial) initializing of server has completed
Note

Data directory initialization creates time zone tables in the mysql database but does not populate them. To do so, refer to the instructions in MySQL Server Time Zone Support.

For more information about data directory initialization, see Initializing the Data Directory.

Starting the Server using systemd

This section describes how to start the server with systemd and how to enable automatic restart of the MySQL server when the host is rebooted.

systemd provides manual server management using the systemctl command:

Press CTRL+C to copy
systemctl {start|stop|restart|status} mysqld

To configure the MySQL installation to work with systemd:

  1. Add a systemd service unit configuration file with details about the MySQL service. The file is named mysqld.service and is placed in /usr/lib/systemd/system.

    Press CTRL+C to copy
    $> cd /usr/lib/systemd/system $> touch mysqld.service $> chmod 644 mysqld.service

    Add this configuration information to the mysqld.service file:

    Press CTRL+C to copy
    [Unit] Description=MySQL Server Documentation=man:mysqld(8) Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html After=network.target After=syslog.target [Install] WantedBy=multi-user.target [Service] User=mysql Group=mysql # Have mysqld write its state to the systemd notify socket Type=notify # Disable service start and stop timeout logic of systemd for mysqld service. TimeoutSec=0 # Start main service ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf $MYSQLD_OPTS # Use this to switch malloc implementation EnvironmentFile=-/etc/sysconfig/mysql # Sets open_files_limit LimitNOFILE = 10000 Restart=on-failure RestartPreventExitStatus=1 # Set environment variable MYSQLD_PARENT_PID. This is required for restart. Environment=MYSQLD_PARENT_PID=1 PrivateTmp=false
  2. Enable the mysqld service to automatically start at reboot.

    Press CTRL+C to copy
    $> systemctl enable mysqld.service Created symlink from /etc/systemd/system/multi-user.target.wants/mysqld.service to /usr/lib/systemd/system/mysqld.service.
  3. To ensure the systemd configuration works, start the mysqld service manually using systemctl.

    Press CTRL+C to copy
    $> systemctl start mysqld
  4. Check the status of the mysqld service. The output should appear similar to the following, which shows that the mysqld service was started successfully.

    Press CTRL+C to copy
    $> systemctl status mysqld ● mysqld.service - MySQL Server Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2018-05-02 18:18:05 ADT; 5s ago Docs: man:mysqld(8) http://dev.mysql.com/doc/refman/en/using-systemd.html Main PID: 19520 (mysqld) Status: "SERVER_OPERATING" CGroup: /system.slice/mysqld.service └─19520 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf May 02 18:18:04 localhost.localdomain systemd[1]: Starting MySQL Server... May 02 18:18:05 localhost.localdomain systemd[1]: Started MySQL Server.
  5. To verify that systemd automatically starts MySQL when the system is rebooted, restart your system and check the status of the mysqld service again.

    Press CTRL+C to copy
    $> systemctl status mysqld
Note

systemd has its own log file which can be accessed using journalctl. To view mysqld-related log messages, use journalctl -u mysqld. Some messages, such as MySQL startup messages, may be printed to the systemd log.

For more information about systemd, see Managing MySQL Server with systemd.

Resetting the MySQL root Account Password

This procedure assumes that the MySQL server is running. You can check server status by issuing:

Press CTRL+C to copy
$> systemctl status mysqld

When the data directory was initialized, a random initial password was generated for the MySQL root account (root@localhost) and marked as expired. Perform these steps to set a new password:

  1. Using the mysql client, connect to the server as root@localhost using the random password that the server generated during the initialization sequence:

    Press CTRL+C to copy
    $> cd /usr/local/mysql $> bin/mysql -u root -p Enter password: (enter the random root password here)
  2. After connecting, assign a new root@localhost password. Use a strong password. Ideally, the password should conform to the password policy that you will define using the validate_password component, which is enabled in a later step. (See Chapter 6, Installing the MySQL Password Validation Component.)

    Press CTRL+C to copy
    mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';

    Alternatively, you can generate a random password using the RANDOM PASSWORD option. For more information, see Random Password Generation.

Testing the Server

Now that MySQL is installed and initialized, and the MySQL root user password is reset, perform a couple of simple tests to verify that the server works.

  1. Use mysqlshow to verify that you can retrieve information from the server.

    Press CTRL+C to copy
    $> cd /usr/local/mysql $> bin/mysqlshow -u root -p Enter password: (enter root password here) +--------------------+ | Databases | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+
  2. Use mysqladmin to view MySQL server version information.

    Press CTRL+C to copy
    $> cd /usr/local/mysql $> bin/mysqladmin -u root -p version Enter password: (enter root password here)

    The output should be similar to that shown here:

    Press CTRL+C to copy
    bin/mysqladmin Ver 8.0.19-commercial for linux-glibc2.12 on x86_64 (MySQL Enterprise Server - Commercial) Copyright (c) 2000, 2020, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Server version 8.0.19-commercial Protocol version 10 Connection Localhost via UNIX socket UNIX socket /tmp/mysql.sock Uptime: 11 min 7 sec Threads: 3 Questions: 8 Slow queries: 0 Opens: 146 Flush tables: 3 Open tables: 63 Queries per second avg: 0.011

For additional tests, see Testing the Server.