Change the default MySQL data directory with SELinux enabled

This is a short article that explains how you change the default MySQL data directory and adjust SELinux to account for the changes. The article assumes that you’re running either RHEL, CentOS, Scientific Linux or Fedora with SELinux enabled. This works with the most recent EL (6.2) version.

We’ll be doing this in the following order.

  • Stopping the MySQL server
  • Create a new data directory and move the content from the old data directory
  • Correct the MySQL configuration file
  • Adjust SELinux parameters to accept our new change
  • Starting the MySQL server

Stopping the MySQL server

# service mysqld stop

Create a new data diretory and move the content from the old one

Creating a new data directory

# mkdir /srv/mysql/
# chown mysql:mysql /srv/mysql

Moving the original data files

 # mv /var/lib/mysql/* /srv/mysql/

Correct the MySQL configuration file

Edit the my.cnf file for your distribution. In my example it’s located in the /etc/mysql/ directory. RHEL/CentOS/Scientific Linux put the my.cnf file directly in /etc by default.

# nano /etc/mysql/my.cnf









and save the file.

Adjust SELinux parameters to accept our new change

Should the following command output “Permissive” or “Disabled” then you may skip the details for SELinux.

# getenforce

Run the semanage command to add a context mapping for /srv/mysql.

# semanage fcontext -a -t mysqld_db_t "/srv/mysql(/.*)?"

Now use the restorecon command to apply this context mapping to the running system.

# restorecon -Rv /srv/mysql

Starting the MySQL server

# service mysqld start

Verifying access and connectivity

$ mysql -u root -p
mysql> show databases;

If this is working, you’re up and running. Should you get a message that says

ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’

then add the following to your /etc/my.cnf

socket = /srv/mysql/mysql.sock

Optionally you can just use

$ mysql -u root -p --protocol tcp

to avoid connecting via the socket.

// CrashMAG

27 thoughts on “Change the default MySQL data directory with SELinux enabled”

  1. I had try it on RHEL 6.2 and it works fine. So i’m sure it will work also on CentOS 6.2

  2. Thank you very much for this concise guide. It saved me a lot of a hassle fiddling with SELinux!!!

  3. Hi,

    I carefully followed your instruction but it failed when I start the mysql service. What I did, is to reboot(restart) the server after applying the “semanage” and “restorecon”.

    For all the people out there trying to move datadir, this is the step. Follow the instruction until you reached here,

    # semanage fcontext -a -t mysqld_db_t “/diskmnt/data1/mysql_data/mysql(/.*)?”

    then apply restorecon command to apply context mapping,

    # restorecon -Rv /diskmnt/data1/mysql_data/mysql

    As suggested in the link, I can start the mysql services

    # service mysqld start

    Since mine has failed when I start the mysql service, I decided to restart/reboot the Server, cause I was thinking may be the SELinux still looking/expecting for the default datadir ‘/var/lib/mysql’. After rebooting the server, I expect that the changes made in SELinux has been loaded or something like that. Then mysql services has started successfully after invoking “/etc/init.d/mysqld start”.

  4. On CentOS 6.0 with the 5.x installation of MySQL, the semanage context needs to be mysqld_safe_t, not mysqld_db_t.
    “semanage fcontext -a -t mysqld_safe_t “/srv/mysql(/.*)?”
    Instead of:
    “semanage fcontext -a -t mysqld_db_t “/srv/mysql(/.*)?”

  5. Thanks for the clean steps. Saved some hours. Below setting helped me.

    socket = /srv/mysql/mysql.sock

  6. I have phpmyadmin installed, which, after the above steps, can not connect to mysql. Does anyone else have this problem/solution? Thanks!!

    1. I think Phpmyadmin does not like if the socket file moves. its okay to move the data directory, but leave the mysql.sock file in the original directory and phpmyadmin worked for me!

  7. A simpler solution from an SELinux perspective would have been to simply set a Equivalency label.

    # semanage fcontext -a -e /var/lib/mysql /srv/mysql
    # restorecon -R -v /src/mysql

    grep /var/lib/mysql /etc/selinux/targeted/contexts/files/file_contexts/var/lib/mysql(/.*)? system_u:object_r:mysqld_db_t:s0
    /var/lib/mysql/mysql\.sock -s system_u:object_r:mysqld_var_run_t:s0

    Since the mysql.sock is labeled differently then the database.

    Of course I would prever if the sock was in /run/mysql/mysql.sock which would be labeled correctly.

    Socket files should be in the run directory.

  8. I’ve decided for a bit different setup (2 USB drives in raid1, Luks-encrypted with ext4 on top) and the post did not help me at first place. At the same time it was a fresh install, i.e. no existing data to move.
    After I’ve mounted the volume under /mnt/data and created /mnt/data/mysql, the service would not start despite I did:
    # chcon -R -u system_u -t mysqld_db_t /mnt/data/mysql
    What has ultimately resolved my issue was:
    # chcon -t var_t /mnt/data
    Then the initial startup of mysqld succeeded creating its default ~table-space data structures. I did not need to use either semanage or restorecon.
    (All what I did was under CentOS 6.6)

  9. I have successfully moved my mysql databases and can access them ok. My localhost version of Moodle, however, has stopped being able to access the databases.
    The dbhost was localhost when mysql was at /var/lib/mysql. I cannot use localhost as an address anymore because moodle cannot find it’s database.
    Any suggestions?

  10. Tried all these steps, even with permessive sellinux, the mysqld just do not starts 🙁 I do not know may problem that I use
    /srv/mysql which is –binded in fstab to location on another hdd…
    Getting such message:
    ob for mysqld.service failed because the control process exited with error code. See “systemctl status mysqld.service” and “journalctl -xe” for details.
    [00:12 mike ~/Downloads]$ systemctl status mysqld.service
    ● mysqld.service – MySQL Server
    Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
    Active: activating (start) since Sun 2016-02-07 00:12:51 MSK; 1s ago
    Process: 30854 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
    Main PID: 1439 (code=exited, status=0/SUCCESS); : 30879 (mysqld)
    CGroup: /system.slice/mysqld.service
    ├─30879 /usr/sbin/mysqld –daemonize –pid-file=/var/run/mysqld/
    └─30882 /usr/sbin/mysqld –daemonize –pid-file=/var/run/mysqld/

    Feb 07 00:12:51 localhost.localdomain systemd[1]: Starting MySQL Server…

    Permissions etc all done… I made selinux part as well, so not even message in troubleshutter appears…

    It is under Fedora 23 and mysql 5.7

  11. You can use this steps also to get through selinux :
    1. make a datadir (newDir) then give a permission
    chown -R mysql:mysql /newDir
    2.stop mysql service
    3.make a change in my.cnf for datadir=/newDir
    4.type sestatus it will show current mode enforcing which is blocking for change in /newDir
    5. To change current mode from enforcing to permissive type : setenforce 0
    6 After this check sestatus’s current mode it should be permissive
    7. Now as you have change the Datadir’s new location in my.cnf . Restart the mysql service
    8. Your new location has been set .
    ( Prior to this use mysql_install_db in new location for mysql db)

  12. Thanks. I used your instructions for Centos 7 but I had one problem that took several hours to correct which I will include for others. My php driven website was looking in the original location for the mysql.socket. So you might someone might to change these lines in their php.ini file. It might be located at /etc/php.ini

    pdo_mysql.default_socket = /data/mysql/mysql.sock
    mysql.default_socket = /data/mysql/mysql.sock
    mysqli.default_socket = /data/mysql/mysql.sock

    I think a better solution would be for php.ini to look for the configuration in my.cnf.

    I think SELinux blocked me from using a symbolic link from the default socket to the new socket.

Leave a Reply

Your email address will not be published. Required fields are marked *