Darwin's Theories Blog

New Theories for a New Time

Nagios for monitoring everything (including virtual hosts)

2007-04-05
They said it was hard to do; it's not.
For some time I've been using Nagios to monitor my own server and that of some clients. Nagios has shown itself to be very useful, and it's really not that hard to configure, with a bit of practice. And it is very flexible.

One of the machines I monitor has a batch of virtual web servers. Nagios' documentation doesn't say much about monitoring virtual hosts, and a web search only turned up people using extreme copy-and-paste to implement this (even a script to automate the redundancy), so I came up with a better way.

Virtual hosts are the backbone of the web hosting industry: a single server computer hosting a handful or hundreds of low-volume web sites. They all have the same IP address but different domain names; the web server decides which site to use by the host name, which is sent as an extra header in the HTTP request. The web server uses its configuration information to determine which local directory goes with which virtual host.

In your service definitions you might change the default http_check rule to:

define command {
    command_name    check_http
    command_line    $/check_http -I $ -u $ -s $
}

I'm not going to explain this, other than to say that I'm using a URL (the -u) that includes the virtual host name; I assume if you've read this far that you are interested enough in Nagios to read the documentation that comes with it, or a good book on the subject.

What's the -s? To really test virtual hosts, it does not suffice to check that a virtual host is responding; in order to ensure that the correct content is being served, I use the -s (string check) option of the check_http program, typically matching the site name or a related string that is in the page (string check is fractionally cheaper than regex checking). So, to check a batch of virtual hosts, all you need is:

define service {
    use         generic-service
    host_name       myhost
    service_description My WWW
    check_command       check_http!https://www.host.domain/!"My Site"
}
define service {
    use         generic-service
    host_name       myhost
    service_description My Blog
    check_command       check_http!https://blog.host.domain/index.jsp!"My Blog"
}

That's all there is to it; you don't need to duplicate the host entry, just define a service entry that uses the host name in a full URL