I will make the assumption that you have already configured Munin and Munin-node. I also assume that you didn’t change the CGI and CRON params in the Munin default configuration provided by the Debian package.

Abstract

  • In the default configuration, the HTML files for Munin graphes are generated by Cron, and are stored in /var/cache/munin/www/

  • To display Munin graphs, you have to call the munin-cgi-graph program located in /usr/lib/munin/cgi/

  • To display Munin extra HTML, you have to call the munin-cgi-html program located in /usr/lib/munin/cgi/

  • The configuration I use is an adapted version of Apache configuration delivered with the Debian package at /etc/munin/apache2.conf.

  • Unlike Apache, Nginx does not spawn CGI processes, you will have to make a startup script to create the appropriate sockets.

  • The spawned sockets run with the munin user, you will have to chown some logfiles and change logrotate configuration.

Installation

Let’s start with a basic Ningx installation : apt-get install nginx

Next, add fcgiwrap, the Ningx CGI wrapper : apt-get install fcgiwrap. Note that in the dependencies, you have spawn-fcgi. we will use it to create the CGI sockets.

The CGI sockets

To spawn the munin-cgi-graph and munin-cgi-html processes, create a startup script at /etc/init.d/munin-fastcgi :

#! /bin/sh
### BEGIN INIT INFO
# Provides:          munin-fastcgi
# Required-Start:    $remote_fs $network
# Required-Stop:     $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts munin-fastcgi
# Description:       Spawn Munin FCGI sockets for Web access
### END INIT INFO

#
# munin-fastcgi     Startup script for Munin CGI services
#
# chkconfig: - 84 15
# description: Loading Munin CGI services using spawn-cgi
#              HTML files and CGI.
#
# Author:  Ryan Norbauer <ryan.norbauer@gmail.com>
# Modified:     Geoffrey Grosenbach http://topfunky.com
# Modified:     David Krmpotic http://davidhq.com
# Modified:     Kun Xi http://kunxi.org
# Modified:     http://drumcoder.co.uk/
# Modified:     http://uname.pingveno.net/

DAEMON=/usr/bin/spawn-fcgi
FCGI_GRAPH_SOCK=/var/run/munin/fastcgi-munin-graph.sock
FCGI_HTML_SOCK=/var/run/munin/fastcgi-munin-html.sock
WWW_USER=www-data
FCGI_USER=munin
FCGI_GROUP=munin
FCGI_SPAWN_GRAPH=/usr/lib/munin/cgi/munin-cgi-graph
FCGI_SPAWN_HTML=/usr/lib/munin/cgi/munin-cgi-html
PIDFILE_GRAPH=/var/run/munin/fastcgi-munin-graph.pid
PIDFILE_HTML=/var/run/munin/fastcgi-munin-html.pid
DESC="Munin FCGI for Graph an HTML"

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0
test -x $FCGI_SPAWN_GRAPH || exit 0
test -x $FCGI_SPAWN_HTML || exit 0

start() {
  $DAEMON -s $FCGI_GRAPH_SOCK -U $WWW_USER -u $FCGI_USER -g $FCGI_GROUP -P $PIDFILE_GRAPH $FCGI_SPAWN_GRAPH 2> /dev/null || echo "Graph Already running"
  $DAEMON -s $FCGI_HTML_SOCK -U $WWW_USER -u $FCGI_USER -g $FCGI_GROUP -P $PIDFILE_HTML $FCGI_SPAWN_HTML 2> /dev/null || echo "HTML Already running"
}

stop() {
  kill -QUIT `cat $PIDFILE_GRAPH` || echo "Graph not running"
  kill -QUIT `cat $PIDFILE_HTML` || echo "HTML Not running"
}

restart() {
  kill -HUP `cat $PIDFILE_GRAPH` || echo "Can't reload Graph"
  kill -HUP `cat $PIDFILE_HTML` || echo "Can't reload HTML"
}

case "$1" in
  start)
    echo "Starting $DESC: "
    start
  ;;
  stop)
    echo "Stopping $DESC: "
    stop
  ;;
  restart|reload)
    echo "Restarting $DESC: "
    stop
    # One second might not be time enough for a daemon to stop,
    # if this happens, d_start will fail (and dpkg will break if
    # the package is being upgraded). Change the timeout if needed
    # be, or change d_stop to have start-stop-daemon use --retry.
    # Notice that using --retry slows down the shutdown process somewhat.
    sleep 1
    start
  ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|restart|reload}" >&2
    exit 3
  ;;
esac

exit $?

Don’t forget to set it executable : chmod +x /etc/init.d/munin-fastcgi

Finally, add your startup script to runlevels : update-rc.d munin-fastcgi defaults

And start it : service munin-fastcgi start

Fix for log files

The log files are owned by www-data user. In our configuration, the CGI process is run by munin.

Change the owner of logfiles : chown munin /var/log/munin/munin-cgi-graph.log && chown munin /var/log/munin/munin-cgi-html.log

Change the logrotate configuration : open /etc/logrotate.d/munin and change create 640 www-data adm to create 640 munin adm for the two logfiles.

Nginx VirtualHost configuration

Create the following /etc/nginx/sites-available/munin :

server {
        #listen   80; ## listen for ipv4; this line is default and implied
        #listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

        # Make site accessible from http://localhost/
        server_name localhost;

        # Here, the whole vhost has auth requirements.
        # You can duplicate it to the graph and html locations if you have
        # something else that doesn't need auth.
        auth_basic            "Private access";
        auth_basic_user_file  /etc/munin/munin_htpasswd;

        location /munin/ {
                alias /var/cache/munin/www/;

                # not authenticated => no rewrite (back to auth)
                if ($remote_user ~ ^$) { break; }

                # is on the right subtree ?
                set $ok "no";
                # admin can see it all
                if ($remote_user = 'admin') { set $ok "yes"; }
                # only allow given path
                if ($uri ~ /munin/([^/]*)) { set $path $1; }
                if ($path = $remote_user) { set $ok "yes"; }

                # not allowed here ? redirect them where they should land
                if ($ok != "yes") {
                        # redirect to where they should be
                        rewrite / /munin/$remote_user/ redirect;
                }
        }

        location ^~ /munin-cgi/munin-cgi-graph/ {
                # not authenticated => no rewrite (back to auth)
                if ($remote_user ~ ^$) { break; }

                # is on the right subtree ?
                set $ok "no";
                # admin can see it all
                if ($remote_user = 'admin') { set $ok "yes"; }
                # only allow given path
                if ($uri ~ /munin-cgi/munin-cgi-graph/([^/]*)) { set $path $1; }
                if ($path = $remote_user) { set $ok "yes"; }

                # not allowed here ? redirect them where they should land
                if ($ok != "yes") {
                        # redirect to where they should be
                        rewrite / /munin-cgi/munin-cgi-graph/$remote_user/ redirect;
                }

                fastcgi_split_path_info ^(/munin-cgi/munin-cgi-graph)(.*);
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_pass unix:/var/run/munin/fastcgi-munin-graph.sock;
                include fastcgi_params;
        }

        location  ^~ /munin-cgi/munin-cgi-html/ {
                # not authenticated => no rewrite (back to auth)
                if ($remote_user ~ ^$) { break; }

                # is on the right subtree ?
                set $ok "no";
                # admin can see it all
                if ($remote_user = 'admin') { set $ok "yes"; }
                # only allow given path
                if ($uri ~ /munin-cgi/munin-cgi-html/([^/]*)) { set $path $1; }
                if ($path = $remote_user) { set $ok "yes"; }

                # not allowed here ? redirect them where they should land
                if ($ok != "yes") {
                        # redirect to where they should be
                        rewrite / /munin-cgi/munin-cgi-html/$remote_user/ redirect;
                }

                fastcgi_split_path_info ^(/munin-cgi/munin-cgi-html)(.*);
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_pass unix:/var/run/munin/fastcgi-munin-html.sock;
                include fastcgi_params;
        }

        location /munin/static/ {
                alias /etc/munin/static/;
        }
}

Don’t forget to enable your VirtualHost : ln -s /etc/nginx/sites-available/munin /etc/nginx/sites-enabled/munin

And to restart Nginx : service nginx restart

Htaccess creation

To protect our stats, the VirtualHost includes HTTP authentication. But you have to create the htpasswd file in /etc/munin/munin_htpasswd. To do so, you can install Apache Utils.

Install Apache utils : apt-get install apache2-utils

Create the htpasswd : touch /etc/munin/munin_htpasswd && chown root:www-data /etc/munin/munin_htpasswd && chmod 640 /etc/munin/munin_htpasswd

And add your admin password : htpasswd /etc/munin/munin_htpasswd

Conclusion

Your Munin installation will be available at http://localhost/munin/ with your admin password.

I hope I saved you from a headhache. ;)

Sources

http://munin.readthedocs.org/en/latest/example/webserver/nginx.html

http://drumcoder.co.uk/blog/2010/aug/04/debian-initd-script-fcgi/