MySQL – Changing Database Location on RH with Selinux

  1. Run the ls -lZ /var/lib/mysql command to view the SELinux context of the default database location for mysql:
    ~]# ls -lZ /var/lib/mysql
    drwx------. mysql mysql unconfined_u:object_r:mysqld_db_t:s0 mysql
    This shows mysqld_db_t which is the default context element for the location of database files. This context will have to be manually applied to the new database location that will be used in this example in order for it to function properly.
  2. Enter mysqlshow -u root -p and enter the mysqld root password to show the available databases:
    ~]# mysqlshow -u root -p
    Enter password: *******
    |     Databases      |
    | information_schema |
    | mysql              |
    | test               |
    | wikidb             |
  3. Shut down the mysqld daemon with the service mysqld stop command as the root user:
    ~]# service mysqld stop
    Stopping MySQL:                                            [  OK  ]
  4. Create a new directory for the new location of the database(s). In this example, /mysql/ is used:
    ~]# mkdir -p /mysql
  5. Copy the database files from the old location to the new location:
    ~]# cp -R /var/lib/mysql/* /mysql/
  6. Change the ownership of this location to allow access by the mysql user and group. This sets the traditional Unix permissions which SELinux will still observe.
    ~]# chown -R mysql:mysql /mysql
  7. Run the ls -lZ /opt command to see the initial context of the new directory:
    ~]# ls -lZ /opt
    drwxr-xr-x. mysql mysql unconfined_u:object_r:usr_t:s0   mysql
    The context usr_t of this newly created directory is not currently suitable to SELinux as a location for MySQL database files. Once the context has been changed, MySQL will be able to function properly in this area.
  8. Open the main MySQL configuration file /etc/my.cnf with a text editor and modify the datadir option so that it refers to the new location. In this example the value that should be entered is /mysql.
    Save this file and exit.
  9. Run the service mysqld start command as the root user to start mysqld. The service should fail to start, and a denial will be logged to the /var/log/messages file. However, if the audit daemon is running alongside the setroubleshoot service, the denial will be logged to the /var/log/audit/audit.log file instead:
    SELinux is preventing /usr/libexec/mysqld "write" access on /mysql. For complete SELinux messages. run sealert -l b3f01aff-7fa6-4ebe-ad46-abaef6f8ad71
    The reason for this denial is that /mysql/ is not labeled correctly for MySQL data files. SELinux is stopping MySQL from having access to the content labeled as usr_t. Perform the following steps to resolve this problem:
  10. Run the following semanage command to add a context mapping for /mysql. Note that semanage is not installed by default. If it is missing on your system, install the policycoreutils-python package.
    ~]# semanage fcontext -a -t mysqld_db_t "/mysql(/.*)?"
  11. This mapping is written to the /etc/selinux/targeted/contexts/files/file_contexts.local file:
    ~]# grep -i mysql /etc/selinux/targeted/contexts/files/file_contexts.local
    /mysql(/.*)?    system_u:object_r:mysqld_db_t:s0
  12. Now use the restorecon command to apply this context mapping to the running system:
    ~]# restorecon -R -v /mysql
  13. Now that the /mysql/ location has been labeled with the correct context for MySQL, the mysqld daemon starts:
    ~]# service mysqld start
    Starting MySQL:                                            [  OK  ]
  14. Confirm the context has changed for /mysql/:
    ~]$ ls -lZ /opt
    drwxr-xr-x. mysql mysql system_u:object_r:mysqld_db_t:s0 mysql
  15. The location has been changed and labeled, and the mysqld daemon has started successfully. At this point all running services should be tested to confirm normal operation.