Picture of Jürgen Kreileder

PHP Error Logging to syslog from a chroot

Here’s a little trick to log PHP errors to syslog from an apache chroot. Instead of creating a $CHROOT/dev/log socket in the chroot and configuring syslog to listen on that, just define a bogus virtual host that logs to syslog.

<VirtualHost 127.0.0.2:80>
        ServerName JustForOpeningSyslog
        Redirect permanent / http://127.0.0.1/
        ErrorLog syslog
</VirtualHost>

Now apache calls openlog(3) with LOG_NDELAY before being chrooted by libapache2-mod-chroot, and libapache2-mod-php4’s syslog(3) calls work just fine.
(Idea stolen from syslog(3) and chroot(2).)

Chrooting MySQL on Debian

It’s quite easy to chroot bind9 and apache on Debian. (See this page for bind9 and libapache2-mod-chroot or libapache2-mod-security for apache.)

But I’ve found no guide for chrooting MySQL, so here’s my short recipe:

  • 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)
      …
    • 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
        echo "."
        ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.pid \
                       /var/run/mysqld
        # Now start mysqlcheck or whatever the admin wants.
        /etc/mysql/debian-start
      …
  • In /etc/mysql/debian.cnf, change the socket line 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
  • Start MySQL:
    /etc/init.d/mysql start
  • Check /var/log/syslog for errors ;-)

March 13th, 2005: I’ve updated the script for newer Debian packages, see Updated MySQL Chroot Script for more information.

July 30th, 2006: These modifications still work fine on the current stable Debian release (3.1, “sarge”). The mysql packages in the testing (“etch”) and unstable (“sid”) distributions of Debian need a few additional changes, I’ll post an updated guide in a few days.

December 30th, 2006: I’ve made an updated guide on how to chroot more recent MySQL packages on Debian and Ubuntu

Tilt Wheel Mouse

Now that I finally got the kernel’s evdev driver running on my machine, I managed to get my tilt-wheel mouse working.

  • Mouse section from /etc/X11/XF86Config-4:
    Section "InputDevice"
      Identifier "Configured Mouse"
      Driver     "mouse"
      Option     "CorePointer"
      Option     "Protocol"        "evdev"
      Option     "Dev Name"        "*Microsoft IntelliMouse*"
      Option     "Buttons"         "9"
      Option     "ZAxisMapping"    "8 9 6 7"
      Option     "Emulate3Buttons" "false"
    EndSection
  • To get the buttons in the correct order for X11, change /etc/X11/Xmodmap to:
    pointer = 1 2 3 8 9 7 6 4 5

    Now horizontal scrolling should work with GNOME!

  • In Mozilla-based browsers however, tilting the wheel moves back- or forward in the history now. To fix this open about:config and set mousewheel.horizscroll.withnokey.action to 0.
    Unfortunately Mozilla and GNOME seem to have different interpretations of left and right; set mousewheel.horizscroll.withnokey.sysnumlines to true to fix that.
  • To get the sides buttons going back- and forward in history again, install xbindkeys and xvkbd. Bind the buttons to Alt-Left and Alt-Right in ~/.xbindkeysrc:
    "xvkbd -text "\[Alt_L]\[Left]""
      m:0x10 + b:8
    "xvkbd -text "\[Alt_L]\[Right]""
      m:0x10 + b:9

    and run xbindkeys in ~/.gnomerc

January 15th, 2006: Xorg 6.9 and later come with a different evdev driver. I’ve made a new guide now. The new guide talks about the Logitech MX1000 but it’s quite easy to adapt the configuartion for other mice.

32-bit compat evdev driver

I’m running a ppc64 kernel with ppc32. This combination has a few shortcomings. One was that the kernel’s evdev driver had no 32-bit compatibility. I couldn’t use XFree86’s evdev support because of this, and hal had some problems too. I finally was annoyed enough to hack the evdev driver. Here’s the ugly patch:
evdev-compat-2.6.11-rc3-mm2.patch

March 16th, 2005: The patch has been integrated into 2.6.11-mm3

Exim 4 and Dynamic IP-Addresses

I’ve recently changed my network connection at home to a provider which assigns dynamic addresses. Exim always provided a broken HELO/EHLO name to my smarthost since then because my externally visible hostname changes each time I connect. I’m now using Exim’s Perl interface to lookup the assigned hostname when connecting my smarthost:

  • /etc/exim4/exim.pl:
    Don’t forget to change ppp0 to the interface you want to handle!
    #! /usr/bin/perl
    
    # Requires libio-interface-perl
    
    use strict;
    use IO::Socket;
    use IO::Interface;
    
    sub get_remote_helo_data()
    {
        my $s = IO::Socket::INET->new(Proto => 'udp');
        my $addr = inet_aton($s->if_addr('ppp0'));
        my $hostname = gethostbyaddr($addr, AF_INET);
    
        $hostname = '' if (!$hostname);
    
        return $hostname;
    }
    
  • /etc/exim4/conf.d/main/50_exim4-localconfig_perl:
    #main/50_exim4-localconfig_perl
    perl_at_start = true
    perl_startup = do '/etc/exim4/exim.pl'
    
  • Add the following code to the appropriate transport, e.g. remote_smtp_smarthost:
    helo_data = \
      ${if >{${strlen:${perl{get_remote_helo_data}}}}{0} \
                     {${perl{get_remote_helo_data}}} \
                     {$primary_hostname}}