Since Icinga 2 runs stable and is considered mature (1.x still works, but is a pain to configure) I’ve taken 2015 for starting to use it on my productive systems. The server which hosts legendiary.at also serves several other vhosts, overall it is hosted in the NETWAYS cloud (thanks!), one situation where you love your managed service guys & Opennebula, Foreman, Puppet.

Afterall I wanted to monitor at least some web and dns services for all vhosts (more to come though). Web services are just a simple http reachability check, while dns verifies that the A record of the given vhost also returns the server’s ip address. That is mandatory to see whether the dns records are still intact, or some misconfiguration is happening.

Therefore I’ve created a file ‘hosts.conf’ containing one host so far, introducing the ‘vhosts’ dictionary.

# cat hosts.conf

object Host "srv-mfriedrich" {
  check_command = "hostalive"

  address = "185.11.252.96"

  vars.vhosts["www.legendiary.at"] = {
  }
  vars.vhosts["www.teamobsession.at"] = {
  }
  vars.vhosts["www.freerunningacademy.at"] = {
  }
}

The services.conf file is rather generic – it takes all hosts with the custom attribute ‘vhosts’ and loops over that dictionary, creating new service object. Each service is prefixed with either “http-” or “dns-” depending on the generated check then. Read more about apply-for-rules.

I’m using the shipped Icinga 2 plugin check commands “http” and “dns” and only set the expected custom attributes.

 # cat services.conf

apply Service "http-" for (http_vhost => config in host.vars.vhosts) {
  import "generic-service"

  check_command = "http"

  vars += config
  vars.http_vhost = http_vhost

  notes = "HTTP checks for " + http_vhost

  assign where host.vars.vhosts
}

apply Service "dns-" for (dns_lookup => config in host.vars.vhosts) {
  import "generic-service"

  check_command = "dns"

  vars += config
  vars.dns_lookup = dns_lookup

  notes = "DNS checks for " + dns_lookup

  assign where host.vars.vhosts
}

Note: Apply For was introduced in Icinga 2 v2.2.0 and is the preferred way of configuring the magic stuff.

icinga2_legendiary_01 icinga2_legendiary_02 icinga2_legendiary_03

Added some notifications and users, in that example it’s just everything for vhosts and myself. I don’t like to get notified when someone forgets to configure the ‘address’ attribute required for the checks, so the notifications are not generated for these objects.

The ‘mail-{host,service}-notification’ templates are shipped with Icinga 2 in conf.d/templates.conf, similar to ‘generic-{host,service-user}’ templates. The notification templates do reference the mail notification command, but I don’t really care about it. The only important thing is to set the User object’s ’email’ attribute.

# cat users.conf 
object User "michi" {
  import "generic-user"

  email = "michael.friedrich@gmail.com"
}

# cat notifications.conf 

apply Notification "vhost-mail-host" to Host {
  import "mail-host-notification"

  users = [ "michi" ]

  assign where host.vars.vhosts
  ignore where !host.address //prevent wrong configuration being notified
}


apply Notification "vhost-mail-service" to Service {
  import "mail-service-notification"

  users = [ "michi" ]

  assign where host.vars.vhosts
  ignore where !host.address //prevent wrong configuration being notified
}

icinga2_legendiary_04Using the new dynamic Icinga 2 language could become rather complex. But still, for simple vhost monitoring it even saves you a lot of typing. And keep in mind – the notification rules are applied based on patterns. I don’t have to worry about contacts assign to hosts/services as I always struggled with in Icinga 1.x or Nagios.

In the end, I’m also using Icinga Web 2‘s git master. It’s still beta, but works far better than Classic UI or Web 1.x. So you’ll see, it’s time for Icinga 2* and a bright future. Next up – Graphite, Graylog2 and automated Puppet deployments of remote checker clients/satellites.