You can create nice and useful Graphs about your Server with Munin, like CPU Load, Memory usagem Traffic, MySQL Stats and so on.

1.) Installation
First at all we need a Debian System, like Sarge or Etch. We install munin with apt-get:

#apt-get install munin munin-node

2.) Configuration
After installation we must configure munin.

#vi /etc/munin/munin-node.conf

change host * to host 127.0.0.1

3.) Restart munin to bring the effect.

/etc/init.d/munin-node restart

4.) Bring munin and apache together
Munin is automatic creating a Directory under "/var/www/munin" and set a cronjob that every 5min generate new graphs. The only thing that we have to do, is to set this path in the Apache config. Here we need to create a new file under "/etc/apache2/sites-enabled/munin.conf"

#vi /etc/apache2/sites-enabled/munin.conf

Put this code in here:

Alias /munin "/var/www/munin"

<Directory /usr/lib/cgi-bin/>
   AllowOverride AuthConfig
  Options FollowSymLinks ExecCGI
</Directory>

Restart Apache to bring the effect:

/etc/init.d/apache2 restart

5.) Check it
Now open a new Browser-Tab and check Munin:

http://www.your-domain.tld/munin

6.) .htaccess
To make it more secure, you can put a .htaccess in the directory.

#vi /var/www/munin/.htpasswd

Contents :

USERNAME:iqhCaA/JBcng.

(Password can generated here --> http://de.selfhtml.org/servercgi/server/htaccess.htm under "Kennwort")

Create a .htaccess

#vi /var/www/munin/.htaccess

Contents:

AuthType Basic
AuthName "Munin Graphs"
AuthUserFile /var/www/munin/.htpasswd
require user USERNAME

7.) Put it in your ispCP Menu (optional)

Button name : munin Button link : http://www.your-domain.tld/munin Button target: http://www.your-domain.tld/munin Show in: Administrator Level (or change it if you want) Save.

Dont forget to wait 5min for the first Graphs ;-)

Here are some Munin directories. Only good to know.

# The Munin-Directory for Data
dbdir /var/lib/munin

# Munin -Directory for generated Websites
htmldir /var/www/munin

# The Munin logfiles
logdir /var/log/munin

# Temporary run files (pid file etc)
rundir /var/run/munin

# HTML Templates for the Munin Layout
tmpldir /etc/munin/templates

#Munin Plugin Direcotry
/usr/share/munin/plugins

And now have Fun with ispCP and Munin.

8.) Optional Plugins
Here you can find some optional Plugins for Munin

Apache vHost monitoring
With this Plugin is every vHost in the Graphic. So can you see wich vHost needs the most Power.
Here is an example Graph -> [http://www.freshnet.org/foto/apache-vrequests.png ]
This plugin must be compiled on your Machine. So we need some Apache2 Dev-Packages:

# apt-get install apache2-dev libcrypt-ssleay-perl libwww-perl

or this for prefork

# apt-get install apache2-prefork-dev libcrypt-ssleay-perl libwww-perl

Then we must enable some Apache Modules:

# a2enmod info
# a2enmod status
# /etc/init.d/apache2 force-reload

Download and extract the Module apache_watch

# cd /root
# wget http://forums.cacti.net/download.php?id=8888
# mv download.php\?id\=8888 mod_watch-4.3_apache22_mod.tar.gz
# tar -xvzf mod_watch-4.3_apache22_mod.tar.gz
# cd mod_watch-4.3_apache22_mod

Change the Makefile.dso to our needs for Debian Etch

# vi Makefile.dso

Change the File like this:

# The location of apxs utility.
#
#APXS=/home/apache2/bin/apxs
APXS=/usr/bin/apxs2

#
# The location of apachectl utility to stop/start/restart targets.
#
APACHECTL=apache2ctl

#
# Where the scripts should live
#
SCRIPTDIR=/usr/local/sbin

#
# Where to store the weenie files.
#
STATEDIR=/usr/lib/apache2/modules/mod_watch/

#
# Define to use unsigned long long counters.
#
#BIG=-DUSE_OCTET_COUNTER_64

#
# Extras
#
DEF=$(BIG) -DSTATEDIR='\"$(STATEDIR)\"'
INC=
LIB=

Then build the package

# make -f Makefile.dso build
# make -f Makefile.dso install

Load the Module in Apache

# vi etc/apache2/httpd.conf

and put this line in it

LoadModule watch_module /usr/lib/apache2/modules/mod_watch.so

Now we need to add some lines to the apache2.conf

# vi /etc/apache2/apache2.conf

Add these lines at the end of the File

<IfModule mod_status.c>
    #
    # Allow server status reports generated by mod_status,
    # with the URL of http://servername/server-status
    # Change the ".example.com" to match your domain to enable.
    #
    ExtendedStatus On
    <Location /server-status>
        SetHandler server-status
        Order deny,allow
        Deny from all
        Allow from 127.0.0.1
    </Location>
</IfModule>

<IfModule mod_info.c>

     #Allow remote server configuration reports, with the URL of
     # http://servername/server-info (requires that mod_info.c be loaded).
     #Change the ".example.com" to match your domain to enable.

    <Location /server-info>
        SetHandler server-info
        Order deny,allow
        Deny from all
        Allow from 127.0.0.1
    </Location>
</IfModule>


<IfModule mod_watch.c>
    # Allows the URL used to query virtual host data:
    #
    # http://www.snert.com/watch-info
    #
    <Location /watch-info>
    SetHandler watch-info
    Order allow,deny
    Allow from 127.0.0.1
    </Location>


    # Intended for debugging and analysis of shared memory
    # hash table and weenie files:
    #
    #http://127.0.0.1/watch-table
    #

    <Location /watch-table>
    SetHandler watch-table
    Order allow,deny
    Allow from 127.0.0.1
    </Location>

    <Location /watch-list>
    SetHandler watch-list
    Order allow,deny
    Allow from 127.0.0.1
    </Location>
</IfModule>

Now we copy the compiled mod to the right place

# cd /root/mod_watch-4.3_apache22_mod
# cp mod_watch.c /usr/share/munin/plugins/
# chmod 755 /usr/share/munin/plugins/mod_watch.c
# /etc/init.d/apache2 force-reload

Create the apache_watch_ File

# vi /usr/share/munin/plugins/apache_watch_

And put these lines in it

#!/usr/bin/perl
#
# Parameters supported:
#
#     config
#     autoconf
#
# Configurable variables
#
#     url      - Override default status-url
#
# Must be symlinked to what the graph should monitor. Run with --suggest
# to see valid targets - or just run munin-node-configure --shell
#
# Written by Bj�rn Ruberg 2006-2007
#
# Magic markers:
#%# family=auto
#%# capabilities=autoconf suggest

my $ret = undef;
if (!eval "require LWP::UserAgent;") {
  $ret = "LWP::UserAgent not found";
}

# watch-list exists on localhost
# watch-info does not

my %plugs = (
         'bytes'     => 'Input/output (bytes)',
         'requests'  => 'Requests',
         'documents' => 'Documents served',
            );

my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://localhost:%d/watch-list";
my @PORTS = exists $ENV{'ports'} ? split(' ', $ENV{'ports'}) : (80);
my $type = "throughput";

if (exists $ARGV[0] and $ARGV[0] eq "autoconf") {
  if ($ret) {
    print "no ($ret)\n";
    exit 1;
  }
  my $ua = LWP::UserAgent->new (timeout => 30);
  my @badports;
    
  foreach my $port (@PORTS) {
    my $url = sprintf $URL, $port;
    my $response = $ua->request (HTTP::Request->new('GET', $url));
    push @badports, $port unless $response->is_success;
  }
    
  if (@badports) {
    print "no (no mod_watch exists on ports @badports)\n";
    exit 1;
  } else {
    print "yes\n";
    exit 0;
  }
}

if (exists $ARGV[0] and $ARGV[0] eq "suggest") {
  while (my ($key, undef) = each %plugs) {
    print "$key\n";
  }
  exit 0;
}

my @servers = ();
my @data;
foreach my $port (@PORTS) {
  my $ua = LWP::UserAgent->new (timeout => 30);
  my $url = sprintf $URL, $port;
  my $response = $ua->request (HTTP::Request->new ('GET', $url));
  foreach my $string (split (/\n/, $response->content)) {
    my ($server, undef, $ifInOctets, $ifOutOctets, $ifRequests,
        $ifDocuments) = split (/\s/, $string, 6);
    push @servers, $server unless $server eq "SERVER";
    push @data, "$server $ifInOctets $ifOutOctets $ifRequests $ifDocuments"
      unless $server eq "SERVER";
  }
}

# From here and out, the plugin must be run with a symlinked service.
my $check = join ("|", keys %plugs);
die ("Plugin must be symlinked to aspect to be monitored")
  unless $0 =~ /\_($check)$/;

my $action = $1;

if (exists $ARGV[0] and $ARGV[0] eq "config") {
  print "graph_title Apache $plugs{$action}\n";
  print "graph_args --base 1000 -l 0\n";
  print "graph_category apache\n";
  print "graph_vlabel activity\n";
  my $i = 0;
  foreach my $server (sort (@servers)) {
    (my $txtserver = $server) =~ s/(-|\.)/\_/g;
    my $draw = ($i==0) ? 'AREA' : 'STACK';
    if ($action eq "bytes") {
      print "${txtserver}.label $server\n";
      print "${txtserver}.draw $draw\n";
      print "${txtserver}.type COUNTER\n";
    } else {
      print "${txtserver}.label $server\n";
      print "${txtserver}.draw $draw\n";
      print "${txtserver}.type COUNTER\n";
    }
    $i++;
  }
  exit 0;
}

foreach my $string (sort (@data)) {
  my ($server, $ifInOctets, $ifOutOctets, $ifRequests, $ifDocuments) =
    split (/\s/, $string);
  (my $txtserver = $server) =~ s/(-|\.)/\_/g;
  if ($action eq "documents") {
    print "${txtserver}.value $ifDocuments\n";
  } elsif ($action eq "requests") {
    print "${txtserver}.value $ifRequests\n";
  } elsif ($action eq "bytes") {
    print "${txtserver}.value " . ($ifInOctets + $ifOutOctets) . "\n";
  }
}

chmod & and some symlinks

# chmod 755 /usr/share/munin/plugins/apache_watch_
# ln -s /usr/share/munin/plugins/apache_watch_ /etc/munin/plugins/apache_watch_bytes
# ln -s /usr/share/munin/plugins/apache_watch_ /etc/munin/plugins/apache_watch_documents
# ln -s /usr/share/munin/plugins/apache_watch_ /etc/munin/plugins/apache_watch_requests
# cd /usr/share/munin/plugins/
# ./apache_watch_ autoconf
# /etc/init.d/apache2 restart
# /etc/init.d/munin-node restart

Now we can test the Plugin

# cd /usr/local/sbin/
# ./mod_watch.pl -f ifRequests,ifDocuments http://127.0.0.1/watch-list/

You should see something like this

69
13
6.10
SERVER

And config the rest

# cd /usr/share/munin/plugins/
# munin-run apache_watch_bytes config
# munin-run apache_watch_documents config
# munin-run apache_watch_requests config

Now you should see a Graph for every vHost in Munin.