Configure Munin graphs with Nginx, FastCGI, and Debian 7
Par Mathieu le dimanche 25 août 2013, 11:40 - Informatique - Lien permanent
Setting up Munin with Nginx can be a little harsh. Here is the ready-to-go solution for Debian Wheezy.
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/
Commentaires
Je pense qu'il y a une petite typo dans le script d'init spawn-fcgi :
FCGI_SPAWN_HTML doit pointer vers /usr/lib/munin/cgi/munin-cgi-html
Hello and thanks.
By the way:
FCGI_SPAWN_HTML=/usr/lib/munin/cgi/munin-cgi-graph
should be:
FCGI_SPAWN_HTML=/usr/lib/munin/cgi/munin-cgi-html
.. at least on my installation.
Oui, effectivement, je viens de corriger. Merci. :)
Yes, you were right, I fixed it. Thanks. :)
thank you so much. I had already wasted an afternoon trying to get this working.
I owe you a beer.
Nginx is reporting "Permission denied" when trying to connect to /var/run/munin/fast-cgi-munin-graph.sock.
Can you let me know what permissions you've given the sockets? Mine appear as www-data:www-data rw-r
-.Thanks for the help! :)
Hello,
The permissions you mentionned looks correct for me (www-data 750 on /var/run/munin and www-data 640 on /var/run/munin/fast-cgi-munin-graph.sock ).
By the way, I wrote in the article /var/run/munin/fastcgi-munin-graph.sock and not /var/run/munin/fast-cgi-munin-graph.sock, could it be the problem ?
I suppose that you report this problem from the logs, and so it is not a regular "denied by configuration" problem (HTTP 403 when accessing the URL). If you have a 403, you may have an unreadable (wrong permissions) and/or empty htaccess and/or an upper rule that forbids that URL (are the server_name and document_root correct ?)
To check if the permissions are right, you can do a sudo -u www-data cat > /var/run/munin/fast-cgi-munin-graph.sock, you should have the regular "cat's stdin prompt", and no error returned (otherwise, your permissions are incorrect, either on the file OR on one of its parent directories (check sudo -u www-data ls /var/run/munin) ).
By the way, the www-data user depends on your OS and setup, Nginx usually runs as www-data, but it may not be the case; check with the ps command which user Nginx is running, and eventually fixes the CGI spawning user (replace www-data by the Nginx user).
The Nginx error log should help you with this issue, if needed you can augment its verbosity : error_log /path/to/log debug;