Apache2: Logging To A MySQL Database With mod_log_sql (Debian Etch)

Version 1.0
Author: Falko Timme

This guide shows how you can write the Apache2 access log to a MySQL database instead of a file. To achieve this, I use the Apache2 module mod_log_sql. I'm using a Debian Etch server in this tutorial.

I do not issue any guarantee that this will work for you!


1 Installing Apache2, MySQL, mod_log_sql

Unfortunately libapache2-mod-log-sql-mysql is available as a Debian package only for Debian Lenny (testing) and Sid (unstable), but not for Etch. Therefore we will install the libapache2-mod-log-sql-mysql package from Lenny. To do this, open /etc/apt/sources.list and add the line deb http://ftp2.de.debian.org/debian/ lenny main; your /etc/apt/sources.list could then look like this:

vi /etc/apt/sources.list

deb http://ftp2.de.debian.org/debian/ etch main
deb-src http://ftp2.de.debian.org/debian/ etch main

deb http://ftp2.de.debian.org/debian/ lenny main

deb http://security.debian.org/ etch/updates main contrib
deb-src http://security.debian.org/ etch/updates main contrib

Of course (in order not to mess up our system), we want to install packages from Lenny only if there's no appropriate package from Etch - if there are packages from Etch and Lenny, we want to install the one from Etch. To do this, we give packages from Etch a higher priority in /etc/apt/preferences:

vi /etc/apt/preferences

Package: *
Pin: release a=etch
Pin-Priority: 700

Package: *
Pin: release a=lenny
Pin-Priority: 650

(The terms etch and lenny refer to the appropriate terms in /etc/apt/sources.list; if you're using stable and testing there, you must use stable and testing instead of etch and lenny in /etc/apt/preferences as well.)

Afterwards, we update our packages database:

apt-get update

If you're getting an error like this:

Segmentation faultsts... 96%

or this one:

E: Dynamic MMap ran out of room

open /etc/apt/apt.conf and add a line for APT::Cache-Limit with a very high value, e.g. like this:

vi /etc/apt/apt.conf

APT::Cache-Limit "100000000";

Then run

apt-get update

again and upgrade the installed packages:

apt-get upgrade

(If you see any questions, you can accept the default values.)

To install Apache2, MySQL, and mod_log_sql, we run:

apt-get install apache2 mysql-server mysql-client libapache2-mod-log-sql-mysql

Create a password for the MySQL user root (replace yourrootsqlpassword with the password you want to use):

mysqladmin -u root password yourrootsqlpassword

Then check with

netstat -tap | grep mysql

on which addresses MySQL is listening. If the output looks like this:

tcp        0      0 localhost.localdo:mysql *:*                     LISTEN     2713/mysqld

which means MySQL is listening on localhost.localdomain only, then you're safe with the password you set before. But if the output looks like this:

tcp        0      0 *:mysql *:*                     LISTEN     2713/mysqld

you should set a MySQL password for your hostname, too, because otherwise anybody can access your database and modify data:

mysqladmin -h server1.example.com -u root password yourrootsqlpassword

mod_log_sql got enabled automatically when we installed it, but there's another module which we should enable: mod_uique_id (it's not necessary, but without it, mod_log_sql will leave the id column in the MySQL table for the access log empty). The id column will contain the unique request ID supplied by the standard Apache module mod_unique_id.

a2enmod unique_id

Reload Apache:

/etc/init.d/apache2 force-reload


2 Creating A Virtual Host

I will now create a default Apache vhost in the directory /var/www/web1/web. For this purpose, I will modify the default Apache vhost configuration in /etc/apache2/sites-available/default. If you already have a vhost for which you'd like to enable MySQL logging, you must adjust this tutorial to your situation.

First, we create the directory /var/www/web1/web and make the Apache user (www-data) the owner of that directory:

mkdir -p /var/www/web1/web
chown www-data /var/www/web1/web

Then we back up the default Apache vhost configuration (/etc/apache2/sites-available/default) and create our own one:

mv /etc/apache2/sites-available/default /etc/apache2/sites-available/default_orig
vi /etc/apache2/sites-available/default

NameVirtualHost *
<VirtualHost *>
        ServerAdmin [email protected]

        DocumentRoot /var/www/web1/web/
        <Directory /var/www/web1/web/>
                Options Indexes MultiViews
                AllowOverride None
                Order allow,deny
                allow from all


Then reload Apache:

/etc/init.d/apache2 reload


3 Configure The Virtual Host For MySQL Logging

You can find the documentation for mod_log_sql in the HTML file /usr/share/doc/libapache2-mod-log-sql/manual.html. You should copy it to your workstation (e.g. with WinSCP) and study it.

Having read this file, we create a MySQL database called apachelogs which will contain the tables for our access logs (it can contain multiple access log tables, for example one for each virtual host you have). In addition to that we create the MySQL user loguser - this user will be used by mod_log_sql to connect to MySQL later on. loguser will have CREATE and INSERT privileges so that it can automatically create tables for the access logs (if the tables don't already exist) and insert records in these tables:

mysql -u root -p

create database apachelogs;

grant insert,create on apachelogs.* to [email protected] identified by 'loguser_password';
grant insert,create on apachelogs.* to [email protected] identified by 'loguser_password';

(Replace loguser_password with a password of your choice.)

Then we leave the MySQL shell:


Now we modify our vhost in /etc/apache2/sites-available/default so that it looks as follows:

vi /etc/apache2/sites-available/default

LogSQLLoginInfo mysql://loguser:[email protected]/apachelogs
LogSQLCreateTables on
LogSQLDBParam socketfile /var/run/mysqld/mysqld.sock
LogSQLTransferLogFormat AbHhmRSsTUuvI

NameVirtualHost *
<VirtualHost *>
        ServerAdmin [email protected]

        DocumentRoot /var/www/web1/web/
        <Directory /var/www/web1/web/>
                Options Indexes MultiViews
                AllowOverride None
                Order allow,deny
                allow from all

        LogSQLTransferLogTable web1_access_log

The LogSQLLoginInfo (which holds the login credentials to the database), LogSQLCreateTables (which tells mod_log_sql to create tables if they don't exist), LogSQLDBParam socketfile (which specifies the MySQL socket), and LogSQLTransferLogFormat (which specifies what gets logged in the database) directives go into the global Apache configuration. The LogSQLTransferLogTable directive goes into the vhost configuration - that way you can specify different access log tables for each virtual host (e.g. web1_access_log, web2_access_log, web3_access_log, etc.).

The LogSQLTransferLogFormat directive is explained in more detail in the /usr/share/doc/libapache2-mod-log-sql/manual.html file.

Reload Apache afterwards:

/etc/init.d/apache2 reload


4 Testing mod_log_sql

Now access some pages from your vhost in a browser and check the apachelogs database afterwards:

mysql -u root -p

use apachelogs;
show tables;

You should now see that the table web1_access_log has been created by mod_log_sql:

mysql> show tables;
| Tables_in_apachelogs |
| web1_access_log      |
1 row in set (0.00 sec)


Now let's check what's in that table:

select * from web1_access_log;

If all went well, you should find access logs in that table:

mysql> select * from web1_access_log;
| id                  | agent                                                                                       ...
| JpEF8MCoAGQAAFyuEBU | Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20080404 Firefox/
| JpPHIMCoAGQAAFyuEBY | Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20080404 Firefox/
| JpTj0MCoAGQAAFyuEBc | Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20080404 Firefox/
3 rows in set (0.00 sec)




to leave the MySQL shell.


Share this page:

Suggested articles

3 Comment(s)

Add comment



As usual, a very nice tutorial Falko, cheers.

Please note however that if the MySQL server is down or unavailable, Apache will display timeouts and may not even serve websites at all.

For high performance websites, this might be a consideration. You may want to provide redundant MySQL logging servers or agressive availability monitoring on either Apache and MySQL.


For those who don't want to mess with their Etch apt config:

wget http://ftp.at.debian.org/debian/pool/main/t/tzdata/tzdata_2008e-3_all.deb
wget http://ftp.at.debian.org/debian/pool/main/g/glibc/libc6_2.7-13_i386.deb
wget http://ftp.at.debian.org/debian/pool/main/liba/libapache-mod-log-sql/libapache2-mod-log-sql_1.100-13_i386.deb

dpkg -i tzdata_2008e-3_all.deb
dpkg -i libc6_2.7-13_i386.deb
dpkg -i libapache2-mod-log-sql_1.100-13_i386.deb

From: Anonymous