Hi Everyone,
today I got the interesting project: take a vanilla CentOS 6.4, install a chrooted MySQL onto it. How hard can it be? As it turned out, it is tricky at least. Here’s how I did it:
First, I did a bog standard
yum install mysql-server
and then I started it
service mysqld start
this creates an empty database (actually, the mysql-required grant tables are in it), which I’ve given a new password:
/usr/bin/mysqladmin -u root password 'start123'
then I stopped the db again
service mysql stop
So, now you have a fresh database in /var/lib/mysql to use. Now I set up the chroot jail – I expected to have to install chroot with yum, but it is already included in the minimal CentOS install, yeah.
You’ll need to copy this 3 RPMs to the directory where your chroot is going to be: (I’m using /opt/mysql)
mysql-server-5.1.66-2.el6_3.x86_64 mysql-libs-5.1.66-2.el6_3.x86_64 mysql-5.1.66-2.el6_3.x86_64
(the versions can differ, I think the most actual is the 5.1.69)
change into /opt/mysql and extract all 3 RPMs:
rpm2cpio mysql-server-5.1.66-2.el6_3.x86_64.rpm | cpio -idmv
You should now have 3 directories, etc, usr and var as subdirectories in /opt/mysql – but for the chroot jail to function, we’ll need some extra stuff, like… libraries?
Make these extra directories (under /opt/mysql) bin, dev, lib, lib64, proc, sys, tmp chmod 777 /opt/mysql/tmp chown mysql:mysql /opt/mysql/var/run/mysqld chown mysql:mysql /opt/mysql/var/lib/mysql mkdir /home/chroot/home/chroot/var/log mkdir -p /opt/mysql/opt/mysql/var/log
Copy these libraries from the system directories into lib64: (some you’ll find in /lib64, some in /usr/lib64) – sorry ;)
ld-linux-x86-64.so.2 libcrypto.so.10 libgmp.so.3 libkrb5support.so.0 libnss_dns-2.12.so libnss_nis-2.12.so libpam_misc.so.0 libresolv.so.2 libz.so.1 libacl.so.1 libcrypt.so.1 libgssapi_krb5.so.2 libkrb5support.so.0.1 libnss_dns.so.2 libnss_nisplus-2.12.so libpam_misc.so.0.82.0 librt.so.1 libattr.so.1 libc.so.6 libk5crypto.so.3 libm.so.6 libnss_files-2.12.so libnss_nisplus.so.2 libpam.so.0 libselinux.so.1 libaudit.so.1 libdl.so.2 libkeyutils.so.1 libnsl.so.1 libnss_files.so.2 libnss_nis.so.2 libpam.so.0.82.2 libssl.so.10 libcap.so.2 libfreebl3.so libkrb5.so.3 libnss_compat-2.12.so libnss_hesiod-2.12.so libpamc.so.0 libpcre.so.0 libstdc++.so.6 libcom_err.so.2 libgcc_s.so.1 libkrb5.so.3.3 libnss_compat.so.2 libnss_hesiod.so.2 libpamc.so.0.82.1 libpthread.so.0 libtinfo.so.5
Copy everything (may be unnecessary, but I was lazy) from /bin to /opt/mysql/bin, also dirname, expr and nohup from /usr/bin
cp -a /bin/* /opt/mysql/bin/ cp -a /usr/bin/expr /opt/mysql/usr/bin/ cp -a /usr/bin/dirname /opt/mysql/usr/bin/ cp -a /usr/bin/nohup /opt/mysql/usr/bin/
Next, it would be nice to have some system functions, do a few bind mounts in the fstab file:
/sys /opt/mysql/sys none bind 0 0 /proc /opt/mysql/proc none bind 0 0 /dev /opt/mysql/dev none bind 0 0
Activate them with mount -a
Copy the user and group database files from the system’s etc into the jail:
cp /etc/passwd /opt/mysql/etc/ cp /etc/group /opt/mysql/etc/ cp /etc/nsswitch.conf /home/chroot/etc/ cp /etc/localtime /home/chroot/etc/
Copy everything from /var/lib/mysql/ to /opt/mysql/var/lib/mysql/ – now you have a database to start with. Change into the new chroot jail and start the server:
chroot /opt/mysql /usr/bin/mysqld_safe --chroot=/opt/mysql \ --datadir=/var/lib/mysql --socket=/var/run/mysqld/mysql.sock \ --pid-file=/var/run/mysqld/mysql.pid --basedir=/usr \ --user=mysql > /dev/null 2>&1 & logout [root@localhost log]# ps -ef | grep mysql root 5328 1 0 09:55 pts/0 00:00:00 /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql --socket=/var/lib/mysql/mysql.sock --pid-file=/var/run/mysqld/mysqld.pid --basedir=/usr --user=mysql mysql 5419 5328 0 09:55 pts/0 00:00:00 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --log-error=/var/log/mysqld.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/lib/mysql/mysql.sock
Now, to get the initscript to function properly, locate the following section in /etc/init.d/mysqld:
# alarms, per bug #547485 $exec --datadir="$datadir" --socket="$socketfile" \ --pid-file="$mypidfile" \ --basedir=/usr --user=mysql >/dev/null 2>&1 & safe_pid=$! # Spin for a maximum of N seconds waiting for the server to come up;
And change it to:
# alarms, per bug #547485 /usr/sbin/chroot /opt/mysql $exec --datadir="$datadir" --socket="$socketfile" \ --pid-file="$mypidfile" \ --basedir=/usr --user=mysql >/dev/null 2>&1 & ln -s /opt/mysql/var/lib/mysql/mysql.sock $datadir/mysql.sock 2>/dev/null ln -s /opt/mysql/var/run/mysqld/mysqld.pid /var/run/mysqld/mysqld.pid 2>/dev/null safe_pid=$! # Spin for a maximum of N seconds waiting for the server to come up;
From now on, you can start/stop/query the chrooted mysql just as you would normally.
[root@localhost etc]# /etc/init.d/mysqld status mysqld (pid 1905) is running...
