Live Network Status

Adding live functionality to my network status page.

What I Have Planned

Until now my Network Status page has just included my @WatfordJC_WAN twitter feed.

I do, however, say the following on the page:

I am currently working on adding functionality to this page so as well as planned outages being shown by use of a Twitter widget, current service outages are automatically updated here.

John Cook. Network Status.

My "network" consists of my VPS and Home servers, and the services they provide.

There are a lot of services involved in serving pages on this site but they aren't all the services used on the network (i.e. mail and SIP don't use exactly the same services as web).

What I want to achieve is something easy to understand at a glance but able to be drilled into to see the cause of an issue.

My first thought is simple foundation-icons icons combined with the colours red, orange, and green. Are there suitable symbols?

The closest icon to represent connectivity between a client and the server would be a comments symbol.

I should be able to programtically determine whether connectivity is OK or not. I am not sure if I'd be able to check how long the lag is between both ends, however.

There is no problem with your browser, your connection, or my site.

There is some lag between your browser and my site.

There is a problem with either your browser, your connection, or my site.

As for the major services, some of them have suitable icons.

My Web servers are down.

My mail servers are iffy.

My phone system is OK.

I am not sure how best to represent things, however. Checking whether services are up or not is fairly simple programitcally. Is there a logical dependency order for the Web service?

  1. VPS
    1. Master DNS Server
    2. Loopback IPv6 Addresses
    3. Ethernet IPv6 Addresses
    4. Web Server
      1. Redis
      2. PHP
    5. Encrypted Tunnel to Home Server
    6. Network Bridge to Home Server
    7. Caching Proxy
    8. Home Server
      1. Loopback IPv6 Addresses
      2. Ethernet IPv6 Addresses
      3. Encrypted Tunnel to VPS
      4. Network Bridge to VPS
      5. Caching Proxy
      6. Web Server
        1. Redis
        2. PHP

That is the best I can represent it in a list, which isn't ideal—a tree or something else would probably be a better representation. I can look at representing things more logically and aesthetically later.

Redis Dependent

Upon thinking how best to store the status of everything, I believe a Redis database on my VPS and Home servers will likely be the best way.

The next question is how do I want to retrieve the data? Do I tack it on to the end of the service checking script or do I use PHP?

If I use bash-generated JSON, rather than php-generated, I will be able to update the service status even if PHP goes down. I will need to use Redis, however, because it will be fastest way to compare the current status to the previous status.

As with the rest of the site, I want caching to be utilised as much as possible, which means only updating the JSON when something has changed so that a 304 is the most common HTTP status code.

Current Scripts

I already have two scripts that can check the service status of everything.

This is the script on my VPS:

#!/bin/bash

SERVICE=(nginx varnish cjdns nsd postfix opendkim opendmarc ipv6-lo ipv6-eth0 ula-ipv6-tunnel php5-fpm mysql)
STATUS=()
STATUS+="MULTI
"

#echo $STATUS

for i in ${SERVICE[@]}; do
        tmp=`service "$i" status`
        alive=$?
        if [ $alive -eq 0 ]; then
        STATUS+="hset services:vps3 $i up
"
        else
        STATUS[$i]="down"
        fi
done

STATUS+="EXEC"

echo "$STATUS" 
#| redis-cli -h fdd7:5938:e2e6:1::80:c


exit 0

This is the script on my home server:

#!/bin/bash

SERVICE=(asterisk dovecot imapproxy postfix dkimproxy ipv6-addresses ipv6-tunnel hyperboria ula-ipv6-tunnel ula-ipv6-tunnel-vps3 isc-dhcp-server unbound radvd nginx postgresql lighttpd php5-fpm mysql)
STATUS=()
STATUS+=$'MULTI\n'

#echo $STATUS

for i in ${SERVICE[@]}; do
        tmp=`service "$i" status`
        alive=$?
        STATUS+="hset services:home $i "
        if [ $alive -eq 0 ]; then
        STATUS+=$'up\n'
        else
        STATUS+=$'down\n'
        fi
done

STATUS+="EXEC"

echo "$STATUS"
#| redis-cli -h fdd7:5938:e2e6:1::80:c


exit 0

There are noticeable differences between the scripts, and that is because the one on my VPS is an old version that has some bugs.

New VPS Script

Creating a live network status page is going to involve a lot of thinking, which is why I have put it off for so long. With just two JSON files and a bit of JavaScript downloaded by a client, however, I should be able show what services are working and which are not.

If I code things properly I could even make a call to a JavaScript function to see if something is working. Chucking some JavaScript on the 5xx status pages would be useful, as it could allow me to show what is probably wrong even if /status can't be loaded because of the error.

First, I need to install Redis on my VPS.

sudo apt-get install redis-server
sudo nano /etc/redis/redis.conf
…
#bind 127.0.0.1
bind fdd7:5938:e2e6:6c8d::80:c
…
sudo service redis-server restart

With a bit of modification, the script on my VPS now looks like the following:

#!/bin/bash

SERVICE=(nginx varnish cjdns nsd postfix opendkim opendmarc ipv6-lo ipv6-eth0 ula-ipv6-tunnel php5-fpm mysql redis-server)
STATUS=()
STATUS+=$'MULTI\n'
HAS_CHANGED=0

for i in ${SERVICE[@]}; do
        tmp=`service "$i" status`
        alive=$?
        previous_alive=`redis-cli hget services:vps3 "$i"`
        if [ $alive -eq 0 ]; then
                if [ ! "$previous_alive" = "up" ]; then
                        STATUS+="hset services:vps3 $i "
                        STATUS+=$'up\n'
                        HAS_CHANGED=1
                fi
        else
                if [ ! "$previous_alive" = "down" ]; then
                        STATUS+="hset services:vps3 $i "
                        STATUS+=$'down\n'
                        HAS_CHANGED=1
                fi
        fi
done

STATUS+="EXEC"

if [ `echo "$STATUS" | wc -l` -gt 2 ]; then
        echo "$STATUS" | redis-cli -h fdd7:5938:e2e6:6c8d::80:c
fi

if [ $HAS_CHANGED = 1 ]; then

VALUES=(`redis-cli hgetall services:vps3`)
JSON+='{"vps3":['

j=0
for i in ${VALUES[@]}; do
        ((j++))
        if [ ! $(( $j % 2 )) -eq 0 ]; then
                JSON+='{"Service":"'
                JSON+="$i"
                JSON+='","Up":"'
        fi
        if [ $(( $j % 2 )) -eq 0 ]; then
                if [ "$i" = "up" ]; then
                        x=1
                else
                        x=0
                fi
                JSON+="$x"
                JSON+='"},'
        fi
done

JSON=${JSON%?}
JSON+=']}'
echo "$JSON" > /home/www/var/www/johncook_co_uk/js/vps3_status.js

fi

exit 0

While I could modify the JSON file in place, I am going to create a new file when there is a change.

Using the JSON

This is going to require some research as I have barely any experience with JSON with JavaScript/jQuery.

The following JavaScript/jQuery is a start:

NetworkStatus();

function NetworkStatus() {
	if (window.jQuery) {
		$("#status").slideUp(1000,function(){
			$("#status").html("");
			vps3status=$.getJSON("/js/vps3_status.js",function(){
				$.each(vps3status.responseJSON.vps3,function(i){if(vps3status.responseJSON.vps3[i].Up == 1){
					$("#status").append("<p class=\"vps3-"+vps3status.responseJSON.vps3[i].Service+"\""+vps3status.responseJSON.vps3[i].Service+" is <span class=\"label success\"><i class=\"fi-check\"></i> Up</span></p>"); 
				} else {
					$("#status").append("<p>"+vps3status.responseJSON.vps3[i].Service+" is <span class=\"label alert\"><i class=\"fi-x-circle\"></i> Down</p>"); 
				}
				});
			$("#status").slideDown(1000);
			});
		});
		setTimeout(NetworkStatus,60000);
	} else {
		setTimeout(NetworkStatus,1000);
	}

}

Building on from that, I thought about I could just update the buttons. I'm currently using jQuery's slideUp and slideDown functions because I am wiping the content of a div and then replacing it, and doing so looked awful without any animation.

I think I'll be using fadeTo on just the buttons. I've also had a bit of playing around and think I can now create the first half of that ordered list.

NetworkStatus();

function NetworkStatus() {
	if (window.jQuery) {
		vps3status=$.getJSON("/js/vps3_status.js",function(){
			$.each(vps3status.responseJSON.vps3,function(i){
				var service = vps3status.responseJSON.vps3[i].Service;
				var up = vps3status.responseJSON.vps3[i].Up;
				if (up == "1") {
					$("span.vps3-"+service).fadeTo(1500,0.01,function(){
						$("span.vps3-"+service).html("<i class=\"fi-check\"></i> Up").addClass("success").removeClass("alert").removeClass("warning");
						$("span.vps3-"+service).fadeTo(1000,1);
					});
				} else if (up == "0") {
						$("span.vps3-"+service).fadeTo(1500,0.01,function(){
						$("span.vps3-"+service).html("<i class=\"fi-x-circle\"></i> Down").addClass("alert").removeClass("warning").removeClass("success");
						$("span.vps3-"+service).fadeTo(1000,1);
					});
				}
			});
		setTimeout(NetworkStatus,60000);
		});
	} else {
		setTimeout(NetworkStatus,1000);
	}

}

I am going to also be checking the status of the services on my home server, and will be updating variables for overall status of a service (i.e. Web, mail, phone).

The best thing to do here would be to refactor my script and split off things into reusable functions.

NetworkStatus();

function NetworkStatus() {
	if (window.jQuery) {
		vps3status=$.getJSON("/js/vps3_status.js",function(){
			$.each(vps3status.responseJSON.vps3,function(i){
				ServiceStatusUpdate("vps3",vps3status.responseJSON.vps3[i].Service,vps3status.responseJSON.vps3[i].Up,"Down","Up","");
			});
		setTimeout(NetworkStatus,60000);
		});
	} else {
		setTimeout(NetworkStatus,1000);
	}
}

function ServiceStatusUpdate(server,service,status,text0,text1,text2) {
	var selectSpan = "span."+server+"-"+service;
	$(selectSpan).fadeTo(1500,0.001,function() {
		switch (status) {
			case "0":
				$(selectSpan).html("<i class=\"fi-x-circle\"></i> "+text0).addClass("alert").removeClass("warning").removeClass("success");
				break;
			case "1":
				$(selectSpan).html("<i class=\"fi-check\"></i> "+text1).addClass("success").removeClass("alert").removeClass("warning");
				break;
			case "2":
				$(selectSpan).html("<i class=\"fi-alert\"></i> "+text2).addClass("warning").removeClass("alert").removeClass("success");
				break;
		}
		$(selectSpan).fadeTo(1000,1);
	});
}

New Home Server Script

I can't look at the overall status of a service without knowing what the status of things are on my home server.

#!/bin/bash

SERVICE=(asterisk dovecot imapproxy postfix dkimproxy ipv6-addresses ipv6-tunnel hyperboria ula-ipv6-tunnel ula-ipv6-tunnel-vps3 isc-dhcp-server unbound radvd nginx postgresql lighttpd php5-fpm mysql redis-server varnish)
STATUS=()
STATUS+=$'MULTI\n'
HAS_CHANGED=0

for i in ${SERVICE[@]}; do
        tmp=`service "$i" status`
        alive=$?
        previous_alive=`redis-cli hget services:home "$i"`
        if [ $alive -eq 0 ]; then
                if [ ! "$previous_alive" = "up" ]; then
                        STATUS+="hset services:home $i "
                        STATUS+=$'up\n'
                        HAS_CHANGED=1
                fi
        else
                if [ ! "$previous_alive" = "down" ]; then
                        STATUS+="hset services:home $i "
                        STATUS+=$'down\n'
                        HAS_CHANGED=1
                fi
        fi
done

STATUS+="EXEC"

if [ `echo "$STATUS" | wc -l` -gt 2 ]; then
        echo "$STATUS" | redis-cli -h fdd7:5938:e2e6:1::80:c
fi

if [ $HAS_CHANGED = 1 ]; then

VALUES=(`redis-cli hgetall services:home`)
JSON+='{"home":['

j=0
for i in ${VALUES[@]}; do
        ((j++))
        if [ ! $(( $j % 2 )) -eq 0 ]; then
                JSON+='{"Service":"'
                JSON+="$i"
                JSON+='","Up":"'
        fi
        if [ $(( $j % 2 )) -eq 0 ]; then
                if [ "$i" = "up" ]; then
                        x=1
                else
                        x=0
                fi
                JSON+="$x"
                JSON+='"},'
        fi
done

JSON=${JSON%?}
JSON+=']}'
echo "$JSON" > /home/www/var/www/johncook_co_uk/js/home_status.js

fi

exit 0

And with a slight modification to the JavaScript I have now got the status of the services on my home server.

NetworkStatus();

function NetworkStatus() {
	if (window.jQuery) {
		vps3status=$.getJSON("/js/vps3_status.js",function(){
			$.each(vps3status.responseJSON.vps3,function(i){
				ServiceStatusUpdate("vps3",vps3status.responseJSON.vps3[i].Service,vps3status.responseJSON.vps3[i].Up,"Down","Up","");
			});
			homestatus=$.getJSON("/js/home_status.js",function(){
				$.each(homestatus.responseJSON.home,function(i){
					ServiceStatusUpdate("home",homestatus.responseJSON.home[i].Service,homestatus.responseJSON.home[i].Up,"Down","Up","");
				});
				setTimeout(NetworkStatus,60000);
			});
		});
	} else {
		setTimeout(NetworkStatus,1000);
	}
}

function ServiceStatusUpdate(server,service,status,text0,text1,text2) {
	var selectSpan = "span."+server+"-"+service;
	$(selectSpan).fadeTo(1500,0.001,function() {
		switch (status) {
			case "0":
				$(selectSpan).html("<i class=\"fi-x-circle\"></i> "+text0).addClass("alert").removeClass("warning").removeClass("success");
				break;
			case "1":
				$(selectSpan).html("<i class=\"fi-check\"></i> "+text1).addClass("success").removeClass("alert").removeClass("warning");
				break;
			case "2":
				$(selectSpan).html("<i class=\"fi-alert\"></i> "+text2).addClass("warning").removeClass("alert").removeClass("success");
				break;
		}
		$(selectSpan).fadeTo(1000,1);
	});
}

Add a cronjob on both servers to run the bash script, and I will have JSON giving a complete picture of my servers.

After adding the cronjobs, I started to notice some eroneous errors. I needed to add PATH to both bash scripts:

#!/bin/bash

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
…

With that done, I could now place a span anywhere on the page and give it a class of .label.server-service and with the included JavaScript it would replace the span with a green or red Foundation label.

With access to the status of any service, I could now group the services in switch statements to update the status of www, mx, and sip (i.e. Web, mail, and phone).

Web Service

For the Web Service to work properly (OK), the following services need to be up:

  • vps3-ipv6-lo
  • vps3-ipv6-eth0
  • vps3-nginx
  • vps3-php5-fpm
  • vps3-mysql
  • vps3-cjdns
  • vps3-ula-ipv6-tunnel
  • vps3-varnish
  • vps3-redis-server
  • home-ipv6-addresses
  • home-hyperboria
  • home-ula-ipv6-tunnel-vps3
  • home-varnish
  • home-nginx
  • home-lighttpd
  • home-php5-fpm
  • home-redis-server

For the Web Service to sort of work (iffy—to serve cached pages and serve pages that don't use the varnish caches), the following services need to be up:

  • vps3-nginx

And if vps3-nginx is down, the service is completely down.

Status of Service

What I need is a case statement for every one of those services. At the start of the statement, we assume the www service has a status of 1.

If vps3-nginx is down, we set the status to 0.

If www has a status of 1 and a service that isn't vps3-nginx is down, we set the status to 2.

NetworkStatus();
var status_www = "1";

function NetworkStatus() {
	if (window.jQuery) {
		vps3status=$.getJSON("/js/vps3_status.js",function(){
			$.each(vps3status.responseJSON.vps3,function(i){
				ServiceStatusUpdate("vps3",vps3status.responseJSON.vps3[i].Service,vps3status.responseJSON.vps3[i].Up,"down","up","");
			});
			homestatus=$.getJSON("/js/home_status.js",function(){
				$.each(homestatus.responseJSON.home,function(i){
					ServiceStatusUpdate("home",homestatus.responseJSON.home[i].Service,homestatus.responseJSON.home[i].Up,"down","up","");
				});
				ServiceStatusUpdate("network","www",status_www,"down","OK","iffy");
				setTimeout(NetworkStatus,60000);
			});
		});
	} else {
		setTimeout(NetworkStatus,1000);
	}
}

function ServiceStatusUpdate(server,service,status,text0,text1,text2) {
	var selectSpan = "span."+server+"-"+service;
	$(selectSpan).fadeTo(1500,0.001,function() {
		switch (status) {
			case "0":
				$(selectSpan).html("<i class=\"fi-x-circle\"></i> "+text0).addClass("alert").removeClass("warning").removeClass("success");
				switch (server) {
					case "vps3":
						switch (service) {
							case "nginx":
								status_www = "0";
								break;
							case "ipv6-lo":
							case "ipv6-eth0":
							case "php5-fpm":
							case "mysql":
							case "cjdns":
							case "ula-ipv6-tunnel":
							case "varnish":
							case "redis-server":
								if (status_www == "1") {
									status_www = "2";
								}
								break;
						}
						break;
					case "home":
						switch (service) {
							case "ipv6-addresses":
							case "hyperboria":
							case "ula-ipv6-tunnel-vps3":
							case "varnish":
							case "nginx":
							case "lighttpd":
							case "php5-fpm":
							case "redis-server":
								if (status_www == "1") {
									status_www = "2";
								}
								break;
						}
				}
				break;
			case "1":
				$(selectSpan).html("<i class=\"fi-check\"></i> "+text1).addClass("success").removeClass("alert").removeClass("warning");
				break;
			case "2":
				$(selectSpan).html("<i class=\"fi-alert\"></i> "+text2).addClass("warning").removeClass("alert").removeClass("success");
				break;
		}
		$(selectSpan).fadeTo(1000,1);
	});
}

My Web servers are .

Mail Service

For the Mail Service to work properly (OK), the following services need to be up:

  • vps3-ipv6-lo
  • vps3-ipv6-eth0
  • vps3-mysql
  • vps3-cjdns
  • vps3-ula-ipv6-tunnel
  • vps3-postfix
  • vps3-opendkim
  • vps3-opendmarc
  • home-ipv6-addresses
  • home-hyperboria
  • home-ula-ipv6-tunnel-vps3
  • home-mysql
  • home-postfix
  • home-dovecot
  • home-imapproxy
  • home-dkimproxy

My mail system is one of those things that I rarely touch unless it stops working, so the setup is not something I know of the top of my head.

Having said that, I need postfix and mysql to be up for there to be any chance of postfix accepting the mail.

Postfix relies on ipv6-eth0, mysql has no dependencies.

That leaves me with a choice. Some mail is deferred if opendkim or opendmarc are down, do I want to consider that as being "down" or "iffy"?

I think I'm going to go with "down" because I believe most mail admins should be using DKIM and DMARC these days.

Since both services use my ULA network, that means ipv6-lo is another dependency.

So, if anything on this list is down, my mail system is down:

  • vps3-ipv6-lo
  • vps3-ipv6-eth0
  • vps3-mysql
  • vps3-postfix
  • vps3-opendkim
  • vps3-opendmarc

Status of Service

The JavaScript is getting a bit too big now.

NetworkStatus();
var status_www = "1";
var status_mail = "1";

function NetworkStatus() {
	if (window.jQuery) {
		vps3status=$.getJSON("/js/vps3_status.js",function(){
			$.each(vps3status.responseJSON.vps3,function(i){
				ServiceStatusUpdate("vps3",vps3status.responseJSON.vps3[i].Service,vps3status.responseJSON.vps3[i].Up,"down","up","");
			});
			homestatus=$.getJSON("/js/home_status.js",function(){
				$.each(homestatus.responseJSON.home,function(i){
					ServiceStatusUpdate("home",homestatus.responseJSON.home[i].Service,homestatus.responseJSON.home[i].Up,"down","up","");
				});
				ServiceStatusUpdate("network","www",status_www,"down","OK","iffy");
				ServiceStatusUpdate("network","mail",status_mail,"down","OK","iffy");
				setTimeout(NetworkStatus,60000);
			});
		});
	} else {
		setTimeout(NetworkStatus,1000);
	}
}

function ServiceStatusUpdate(server,service,status,text0,text1,text2) {
	var selectSpan = "span."+server+"-"+service;
	$(selectSpan).fadeTo(1500,0.001,function() {
		switch (status) {
			case "0":
				$(selectSpan).html("<i class=\"fi-x-circle\"></i> "+text0).addClass("alert").removeClass("warning").removeClass("success");
				switch (server) {
					case "vps3":
						switch (service) {
							case "nginx":
								status_www = "0";
								break;
							case "postfix":
								status_mail = "0";
								break;
							case "ipv6-lo":
							case "ipv6-eth0":
							case "mysql":
								if (status_www == "1") {
									status_www = "2";
								}
								status_mail = "0";
								break;
							case "opendkim":
							case "opendmarc":
								status_mail = "0";
								break;
							case "php5-fpm":
							case "varnish":
							case "redis-server":
								if (status_www == "1") {
									status_www = "2";
								}
								break;
							case "cjdns":
							case "ula-ipv6-tunnel":
								if (status_www == "1") {
									status_www = "2";
								}
								if (status_mail == "1") {
									status_mail = "2";
								}
								break;
						}
						break;
					case "home":
						switch (service) {
							case "ipv6-addresses":
							case "hyperboria":
							case "ula-ipv6-tunnel-vps3":
								if (status_www == "1") {
									status_www = "2";
								}
								if (status_mail == "1") {
									status_mail = "2";
								}
								break;
							case "varnish":
							case "nginx":
							case "lighttpd":
							case "php5-fpm":
							case "redis-server":
								if (status_www == "1") {
									status_www = "2";
								}
								break;
							case "home-mysql":
							case "home-postfix":
							case "home-dovecot":
							case "home-imapproxy":
							case "home-dkimproxy":
								if (status_mail == "1") {
									status_mail = "2";
								}
								break;
						}
				}
				break;
			case "1":
				$(selectSpan).html("<i class=\"fi-check\"></i> "+text1).addClass("success").removeClass("alert").removeClass("warning");
				break;
			case "2":
				$(selectSpan).html("<i class=\"fi-alert\"></i> "+text2).addClass("warning").removeClass("alert").removeClass("success");
				break;
		}
		$(selectSpan).fadeTo(1000,1);
	});
}

My mail servers are .

Phone Service

Unlike my Web and mail services, my phone service does not rely on my VPS.

For the time being I am going to go with a simple "OK" or "down" because detecting issues in Asterisk such as major lag is something I have not worked out how to do yet.

  • home-asterisk
  • home-radvd
  • home-isc-dhcp-server
  • home-unbound
  • home-ipv6-addresses
  • home-postgresql
  • home-lighttpd
  • home-nginx

Service Status

I think I am going to have to have a look at how I can reduce the size of this JavaScript. I haven't even added error checking yet.

NetworkStatus();
var status_www = "1";
var status_mail = "1";
var status_phone = "1";

function NetworkStatus() {
	if (window.jQuery) {
		vps3status=$.getJSON("/js/vps3_status.js",function(){
			$.each(vps3status.responseJSON.vps3,function(i){
				ServiceStatusUpdate("vps3",vps3status.responseJSON.vps3[i].Service,vps3status.responseJSON.vps3[i].Up,"down","up","");
			});
			homestatus=$.getJSON("/js/home_status.js",function(){
				$.each(homestatus.responseJSON.home,function(i){
					ServiceStatusUpdate("home",homestatus.responseJSON.home[i].Service,homestatus.responseJSON.home[i].Up,"down","up","");
				});
				ServiceStatusUpdate("network","www",status_www,"down","OK","iffy");
				ServiceStatusUpdate("network","mail",status_mail,"down","OK","iffy");
				ServiceStatusUpdate("network","phone",status_phone,"down","OK","iffy");
				setTimeout(NetworkStatus,60000);
			});
		});
	} else {
		setTimeout(NetworkStatus,1000);
	}
}

function ServiceStatusUpdate(server,service,status,text0,text1,text2) {
	var selectSpan = "span."+server+"-"+service;
	$(selectSpan).fadeTo(1500,0.001,function() {
		switch (status) {
			case "0":
				$(selectSpan).html("<i class=\"fi-x-circle\"></i> "+text0).addClass("alert").removeClass("warning").removeClass("success");
				switch (server) {
					case "vps3":
						switch (service) {
							case "nginx":
								status_www = "0";
								break;
							case "postfix":
								status_mail = "0";
								break;
							case "ipv6-lo":
							case "ipv6-eth0":
							case "mysql":
								if (status_www == "1") {
									status_www = "2";
								}
								status_mail = "0";
								break;
							case "opendkim":
							case "opendmarc":
								status_mail = "0";
								break;
							case "php5-fpm":
							case "varnish":
							case "redis-server":
								if (status_www == "1") {
									status_www = "2";
								}
								break;
							case "cjdns":
							case "ula-ipv6-tunnel":
								if (status_www == "1") {
									status_www = "2";
								}
								if (status_mail == "1") {
									status_mail = "2";
								}
								break;
						}
						break;
					case "home":
						switch (service) {
							case "ipv6-addresses":
								if (status_www == "1") {
									status_www = "2";
								}
								if (status_mail == "1") {
									status_mail = "2";
								}
								status_phone = "0";
								break;
							case "hyperboria":
							case "ula-ipv6-tunnel-vps3":
								if (status_www == "1") {
									status_www = "2";
								}
								if (status_mail == "1") {
									status_mail = "2";
								}
								break;
							case "nginx":
							case "lighttpd":
								if (status_www == "1") {
									status_www = "2";
								}
								status_phone = "0";
								break;
							case "varnish":
							case "php5-fpm":
							case "redis-server":
								if (status_www == "1") {
									status_www = "2";
								}
								break;
							case "home-mysql":
							case "home-postfix":
							case "home-dovecot":
							case "home-imapproxy":
							case "home-dkimproxy":
								if (status_mail == "1") {
									status_mail = "2";
								}
								break;
							case "home-asterisk":
							case "home-radvd":
							case "home-isc-dhcp-server":
							case "home-unbound":
							case "home-postgresql":
								status_phone = "0";
								break;
						}
				}
				break;
			case "1":
				$(selectSpan).html("<i class=\"fi-check\"></i> "+text1).addClass("success").removeClass("alert").removeClass("warning");
				break;
			case "2":
				$(selectSpan).html("<i class=\"fi-alert\"></i> "+text2).addClass("warning").removeClass("alert").removeClass("success");
				break;
		}
		$(selectSpan).fadeTo(1000,1);
	});
}

My phone system is .

Network Services Status

Bringing it all together, I can now display the status of Web, mail and phone as I wanted to do near the start of this article:

My Web servers are .

My mail servers are .

My phone system is .

I still need to do error checking for the script to be usable.

For example, if something between NGINX on my VPS and lighttpd on my Home server breaks, the script will wait for a response from lighttpd. No change in status occurs as a result.

I am not yet sure how I am going to approach this issue. I think I'll end this article here and revisit the topic at a later time when I have refined the code.