Picture of Jürgen Kreileder

Chrooting Recent MySQL Versions on Debian and Ubuntu

I’ve posted a recipe for chrooting MySQL on Debian sarge a while ago. These instructions no longer work out of the box for newer MySQL packages from Debian and Ubuntu. The main problem is that the startup script added a few extra checks and script invocations that don’t understand the chroot environment. So here’s an updated plan:

  • Prepare the chroot directory. It’s recommended to use an extra partition/filesystem for it. I will use /srv/mysql (which is an LVM2 partition with an ext3 filesystem on my system) for the rest of the text.
  • Stop MySQL:
    /etc/init.d/mysql stop
  • Copy the databases to new location:
    mkdir -p /srv/mysql/var/lib
    cp -a /var/lib/mysql /srv/mysql/var/lib
  • Copy this script to /etc/default/mysql-chroot
  • Edit /etc/init.d/mysql:
    • Source the mysql-chroot script somewhere at the top:
      …
      test -x /usr/sbin/mysqld || exit 0
      
      . /etc/default/mysql-chroot
      
      SELF=$(cd $(dirname $0); pwd -P)/$(basename $0)
      …
    • Fix the disk space check:
      …
      # check for diskspace shortage
      datadir=`mysqld_get_param datadir`
      if LC_ALL=C BLOCKSIZE= df --portability $CHROOT_DIR$datadir/. | tail -n 1 | awk '{ exit ($4>4096) }'; then
        log_failure_msg "$0: ERROR: The partition with $datadir is too full!"
      …
    • Run setup_chroot right in the start section:
      …
      if mysqld_status check_alive nowarn; then
        echo "...already running."
      else
        setup_chroot
        /usr/bin/mysqld_safe > /dev/null 2>&1 &
      …
    • Somehow /var/run/mysqld/mysqld.pid disappears after each start. We have to create it each time, otherwise the stop command won’t work properly:
      …
      if mysqld_status check_alive warn; then
        log_end_msg 0
        ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.pid \
                       /var/run/mysqld
        # Now start mysqlcheck or whatever the admin wants.
        output=$(/etc/mysql/debian-start)
      …
  • In /etc/mysql/debian.cnf, change the two socket lines to:
    socket = /srv/mysql/var/run/mysqld/mysqld.sock
  • In /etc/mysql/my.cnf:
    • Change the socket line in the [client] section to:
      socket = /srv/mysql/var/run/mysqld/mysqld.sock

      Don’t change the socket lines in the other sections!

    • Add
      chroot = /srv/mysql

      to the [mysqld] section.

  • Prepend /srv/mysql to the log files listed in /etc/logrotate.d/mysql-server
  • Make /usr/bin/mysql_upgrade_shell use the chrooted socket. Note: Currently these changes must be made each time mysql gets upgraded because upgrades override this file!
    …
    --password=*) password=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    --socket=*) socket=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    --ldata=*|--data=*|--datadir=*) DATADIR=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
    …
    fi
    $bindir/mysql_fix_privilege_tables --silent --user=$user --password=$password --socket=$socket $args
    exit 0
    …
    check_args="--check-upgrade --all-databases --auto-repair --user=$user --password=$password --socket=$socket"
    …
    $bindir/mysql_fix_privilege_tables --silent --user=$user --password=$password --socket=$socket $args
    …
  • Start MySQL:
    /etc/init.d/mysql start
  • Check /var/log/syslog for errors ;-)

This article Jürgen Kreileder is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

23 Comments

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post. Both comments and pings are currently closed.

Bummer, i just see copying the ‘−−’ from the article doesn’t work. You have to delete the copied ‘−−’ and type them manually. I’ll correct that tomorrow.

ollie röschke said

hi hi…

thanks for that great doc, it really helped me out. there seems to be no other usable howto for chrooting mysql on debian on the net…

sadly I have some problems when starting the mysql daemon via the init script. the daemon itself comes up, but the ‘debian-start’ util within the ‘upgrade_system_tables_if_necessary’ function:

/etc/mysql/debian-start[17223]: Can’t find data directory. Please restart with –datadir=path-to-writable-data-dir

I didn’t change the datadir option in ‘/etc/mysql/my.cnf’ and the directory and files in it are writeable to the ‘mysql’ user.

any hints on that problem?
my current version is ‘5.0.32-7etch1’

thanks ollie

Hi ollie, try retyping all the ‘--’ you inserted. It should work then.

There still were some problems with the script text on this page (see the first comment). I hope I’ve fixed all now.
The text on this site contained some − (−) entities, they looked like a normal ‘-‘ signs but it’s quite different for scripts.

funbag said

Hi!

I’m having the same problem as ollie.. I have double checked the ‘–‘ characters and they are correct. I think something else is causing this.

Would really appreciate some help here!

Cheers,
Tom

ollie fixed his problem by adding ‘--datadir=<CHROOT_DIR>/var/lib/mysql’ to
the MYUPGRADE variable in ‘/etc/mysql/debian-start’.

I have to check with a fresh install if this is needed now.

stjohn said

woo-hoo great howto! keep updating it!
have you had a chance to see if its needed in fresh installs?

Not yet. But stay tuned!

Teppo Kauppinen said

Thanks! Seems to work just fine with Debian Etch 4.0r1! No need to use the fix Ollie had to use.

Thanks Teppo!

Also, I just did a fresh install on Ubuntu Gutsy. It worked fine like described above.

B-man said

You da man, Juergen.
Great script + great instruction = no problems.
Working beautifully. Thanks 10^6.

Dieter said

Hi

I had to add an / to your chrootdir in my.cnf
-> “chroot = /srv/mysql/”

Thanks for your recipe !

Greets,
Dieter

bieniu said

Hi!
Great HowTo !!
I had a problem with php and mysql.sock i sloved it by adding:

ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.sock /var/run/mysqld
after:
ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.pid /var/run/mysqld

Greets,
Bieniu

Thanks for the tip on adding “–datadir” to /etc/mysql/debian-start, that solved a non-chroot issue I’ve been having for an hour now.

I would advice to put the “datadir” configuration parameter inside /etc/mysql/debian.cnf instead, thus removing the need of fiddling with init-scripts.

Just my €.02… Thanks for a great blog for us Debian techies ;-)

airween said

Great tutorial – I used it many times.

Just a small reflection: above you have use the ‘ln’ command to create a symlink to pidfle, but many programs searches the socket under /var/run/mysqld. I think the bind mount better than use ‘ln’, just simply put this line to fstab:

/srv/mysql/var/run/mysqld /var/run/mysqld none bind 0 2

Thank you again.

a.

Good idea!

[…] Årsaken til dette er at scriptet ikke er optimalisert for et chrootet miljø. Jeg fant denne guiden, den virket ikke for meg men gjorde meg i stand til å bedre skjønne prosessen (noe utdatert). For […]

Still works great on Lenny with MySQL 5!!

Thanks for this!!

Mark said

I have a debian squeeze 64 bit system running, and I need to create a 32 bit chroot to run 32 bit mysql and other apps. I have the chroot working (lenny), but apt-get won’t install mysql in the chroot, and there are no error messages. This recipe copies an existing mysl to the chroot, but I need to create a new 32 bit mysql. Any suggestions or hints would be greatly appreciated!

Thanks!

Mark

[…] but for the MySQL DB server, both methods are not working in the “chrooted” environment. I then start it like this /usr/bin/mysqld_safe & You can have a look to solve that problem: Chrooting Recent MySQL Versions on Debian and Ubuntu by Juergen Kreileder. […]

freaker said

thanks for this nice tutorial, it worked fine for me the last years.

the current mysql includes a chroot-function (as of 5.1 at least), so squeeze is much easier to setup the chroot-environment:

you do not need the script any more and also an edit of /etc/init.d/mysql is not necessary any more.

only the changes to /etc/mysql/debian.cnf and /etc/mysql/my.cnf are needed to setup the chroot.

Nuno Brito said

Hi,

I confirm that using “/usr/bin/mysqld_safe &” is good enough to start MySQL from a chroot environment under Ubuntu 11.10

No other changes are needed. Just start up your web server and then MySQL to get minimal services running. Good luck and thank you for this tutorial along with helpful comments from other admins.

Logesh said

thanks for the tutorial,it worked for me
As freaker said you do not need the script and an edit of /etc/init.d.mysql
I have one doubt
How to start and stop mysql service from inside the chroot jail
If any one knows please update
Thank u advance and also thanks for the tutorial……

Logesh said

thanks for the tutorial,it worked for me
As freaker said you do not need the script and an edit of /etc/init.d/mysql
I have one doubt
How to start and stop mysql service from inside the chroot jail
If any one knows please update
Thank u advance and also thanks for the tutorial……