Beispiel: Statusseite

Einfache Status Page erstellen zum selbst hosten

Habt ihr eine Reihe von Diensten selbst gehostet, auf einem eigenen Server, VPS oder gar einem Shared Hosting und einige Benutzer die sich auf deren Funktion verlassen? Status Pages sind eine praktische Lösung die Funktionsfähigkeit eurer Dienste im Auge zu behalten, Benachrichtigungen im Falle eines Ausfalls zu erhalten und andere öffentlich darüber zu unterrichten. Längere Zeit habe ich nach solch einem Dienst gesucht, der günstig und mit wenig Aufwand zu betreiben ist und ohne Lösung in der Cloud auskommt, die dazu oft auch noch kostenpflichtig sind. Eine Weile war ich mit Cachet recht zufrieden, der Dienst wurde jedoch unnötig umständlich zu pflegen und irgendwann unmöglich neu aufzusetzen. Cachet bietet neuerdings einen professionellen Installationsservice an, was wohl auch notwendig ist, da es kaum jemanden gelingt diese Software ohne Docker zu installieren.

Nun aber zum Thema: Wir verwenden zwei einfache Skripts. Ein bash-Skript welches die Funktionsfähigkeit eurer Dienste oder Webseiten regelmäßig prüft und entsprechend auf einer Statusseite anzeigt. Ein weiteres Skript sendet automatisch eine E-mail, sobald einer der Dienste ausfällt. So könnt ihr auftretende Ausfälle nicht nur von der Statusseite ablesen, sondern werdet auch zeitnah informiert und könnt schnell handeln.

Voraussetzungen

  • Server auf den ihr das Skript aufsetzt. Könnte ein VPS sein, Raspberry Pi oder sogar Shared Hosting
  • Python (meistens bereits installiert, relevant falls ihr Shared Hosting verwendet)
  • Kommandozeilenprogramme bash, ping, traceroute, curl, nc (relevant falls ihr Shared Hosting verwendet, auf eurem eigenen Server einfach installierbar mittels sudo apt-get install curl iputils-ping traceroute netcat-openbsd
  • Cronjobs
  • Zeitaufwand: etwa 30 Minuten.

Installation

Erstellt ein Verzeichnis auf eurem Webserver und macht es über das Internet verfügbar. Da ihr eine Statusseite benötigt um bereits vorhandene Webseiten zu überprüfen, setze ich einfach mal voraus, daß dieser Schritt keine Probleme bereiten sollte. Wechselt dann in dieses Verzeichnis (welches euer Webserver bereitstellt) und ladet das Skript dorthin herunter.

sudo curl -f https://raw.githubusercontent.com/Cyclenerd/static_status/master/status.sh -o status.sh
sudo curl -f https://raw.githubusercontent.com/Cyclenerd/static_status/master/status_hostname_list.txt -o status_hostname_list.txt

Einige grundlegende Einstellungen geben wir im Skript vor. Daher öffnen wir es mit einem herkömmlichen Texteditor, z.b. direkt über die Kommandozeile mit nano.

sudo nano status.sh

Die folgenden Zeilen schauen wir uns näher an:

# Title for the status page
MY_STATUS_TITLE="Status Page"

Hier könnt ihr eintragen was ihr möchtet. Der Wert zwischen den Anführungszeichen erscheint als Seitentitel.

# Link for the homepage button
MY_HOMEPAGE_URL="https://github.com/Cyclenerd/static_status"

# Text for the homepage button
MY_HOMEPAGE_TITLE="Homepage"

Der sogenannte Homepage-Button wird oben rechts auf der Seite eingeblendet. Hier könnt den Knopf beschriften wie ihr möchtet und gegebenenfalls einen Verweis auf eure oder irgendeine Webseite eurer Wahl machen. Denkbar wäre auch eine Kontaktseite einzurichten, wo sich Benutzer eurer Dienste im Fehlerfall hinwenden können.

# List with the configuration. What do we want to monitor?
MY_HOSTNAME_FILE="$MY_STATUS_CONFIG_DIR/status_hostname_list.txt"

Eine Beispielliste haben wir bereits heruntergeladen und liegt im Verzeichnis. Diese passen wir im Anschluß an. Der Wert muß nicht verändert werden, aber es sollte uns bewußt sein, daß dies nach Bedarf anpassbar ist.

# Where should the HTML status page be stored?
MY_STATUS_HTML="$HOME/status_index.html"

Ich plädiere immer dafür diesen Wert einfach durch „index.html“ zu ersetzen. Jeder Webserver ist im Auslieferungszustand vorkonfiguriert nach einem Index zu suchen, wenn keine andere Seite explizit angegeben wird. So könnt ihr die Seite unkompliziert nur unter Angabe der Domäne erreichen (z.b. status.meinedomain.de).

# Where should the JSON status page be stored? Set to "" to disable JSON output
MY_STATUS_JSON="$HOME/status.json"

Wichtiger Wert, da wir diese Datei im nächsten Schritt für die E-mail Benachrichtigungen noch verwenden werden. Muß aber nicht geändert werden.

# Text file in which you can place a status message.
# If the file exists and has a content, all errors on the status page are overwritten.
MY_MAINTENANCE_TEXT_FILE="$MY_STATUS_CONFIG_DIR/status_maintenance_text.txt"

Macht was es sagt. Wenn das Skript eine Datei dieses Namens vorfindet, schreibt es den Inhalt als Wartungsmeldung an den Anfang der Statusseite. So könnt ihr selbst anderen Benutzern mitteilen, wenn es geplante Wartungszeiträume gibt, zu denen mit Ausfällen gerechnet werden muß. Den Wert müssen wir nicht ändern, sollten ihn aber gesehen haben. Wenn wir unsere Anpassungen gemacht haben können wir die Datei schließen und speichern.

Nun tragen wir Dienste zur Überwachung in die Datei status_hostname_list.txt ein.

sudo nano status_hostname_list.txt

Sehen wir uns den Inhalt der Datei genau an. Dort ist bereits beschrieben welche Funktionen wir mit dem Skript ausführen können.

# COMMAND: Command to run. Can be ping, curl or nc.
# ping = send ICMP ECHO_REQUEST packets to network hosts
# curl = transfer a URL
# nc = check TCP and UDP connections
# grep = extension to the curl check
# curl downloads the webpage and pipes it to grep,
# that checks if the keyword is in the page.
# traceroute = check if host or ip exists in route path to MY_TRACEROUTE_HOST
#
# HOSTNAME: Hostname for the 'ping', 'nc' or 'traceroute' command
# IP: IP adress for the 'ping', 'nc' or 'traceroute' command
# URL: URL called by the command 'curl' and 'grep'. I.e. https://www.heise.de/ping or ftp://ftp.debian.org/debian/README
#
# PORT: Optional port specification. Only for 'nc' command.

Da es sich bei den meisten unserer Services um Webseiten handeln dürfte, interessiert uns an dieser Stelle vor allen Dingen curl, was nichts anderes tut als eine Webseite abzurufen und eine Fehlermeldung auszuwerfen, wenn dies nicht gelingen sollte. Weiter unten in der Datei ergänzen wir also eine Reihe unserer Webadressen, die wir auf der Statusseite sehen möchten.

# curl;;
#
curl;https://www.heise.de/ping
curl;https://www.meinewebseite.de
curl;https://xyz.meinewebseite2.de
curl;https://www.golem.de

Dann schließen und speichern wir die Datei. Anschließend kann das Skript bereits für einen Testdurchlauf ausgeführt werden.

sudo bash status.sh loud

Anschließend seht ihr im Verzeichnis bereits die neu generierte html-Datei, welche ihr mit einem Webbrowser aufrufen könnt, wenn ihr die Seite über euren Webserver zur Verfügung stellt. Die Statusseite ist jetzt fertig und kann bereits betrachtet werden. Damit das Skript aber automatisch ausgeführt wird erstellen wir noch einen Cronjob.

sudo crontab -e

Damit ergänzen wir folgende Zeile:

@hourly bash /verzeichnis/eurer/status-seite/status.sh silent >> /dev/null

Ersetzt den Pfad oben mit dem Pfad, wo ihr das Skript abgelegt habt. Den Zeitintervall könnt ihr nach eigenen Gusto ebenfalls anpassen. Hier macht es natürlich Sinn einen Wert zu finden, der einerseits eure Server nicht unverhältnismäßig strapaziert, auf der anderen Seite aber kurz genug ist damit ihr noch zeitnah über Ausfälle informiert werdet. Stündliche Updates finde ich persönlich ausreichend. Sollte es sich jedoch um kritische Infrastruktur handeln, ist ein kürzerer Prüfintervall natürlich angemessen. Für diejenigen, die sich mit Cron noch nicht so richtig auskennen, gebe ich noch zwei weitere Beispiele, wie es aussieht wenn das Skript jede halbe Stunde ausgeführt werden soll:

*/30 * * * * bash /verzeichnis/eurer/status-seite/status.sh silent >> /dev/null

und jede Viertelstunde:

*/15 * * * * bash /verzeichnis/eurer/status-seite/status.sh silent >> /dev/null

E-mail Benachrichtigungen einrichten

Ladet das Skript herunter und entpackt die Datei in ein Verzeichnis eurer Wahl. Der Einfachheit halber könnt ihr es auch in das gleiche Verzeichnis kopieren, wo bereits eure Statusseite liegt.

Am Skript müssen lediglich eure eigenen E-mail Daten eingetragen werden. Deswegen öffnen wir die Datei mit einem Texteditor.

sudo nano static_status_notification.py

Dort füllen wir dann die Platzhalter mit unseren eigenen E-maildaten aus. Also Senderadresse, Empfängeradresse usw.

# E-mail properties
def send_email(data):
email = 'youremailaddress'
password = 'yourpassword'
send_to_email = 'sendtoaddress'
subject = 'Notification: service offline'
message = 'One or several of your services are currently offline: ' + data_string

msg = MIMEMultipart()
msg ['From'] = email
msg ['To'] = send_to_email
msg ['Subject'] = subject

#Attach the message to the MIMEMultipart object
msg.attach(MIMEText(message, 'plain'))

server = smtplib.SMTP('your.smtp.server', 587) #Insert your own smtp-server

Nur für den Fall, daß ihr das Skript nicht im selben Verzeichnis wie die Statusseite platziert habt, so muß an dieser Stelle der volle Pfad zu der Datei status.json angegeben werden:

# Import json data. If file resides in different location, enter full path for status.json
with open('status.json', 'r') as status:

Dann müssen wir zu guter Letzt nur noch einen Cronjob für dieses Skript einrichten, was ganz ähnlich funktioniert wie oben bereits beschrieben.

sudo crontab -e

Dieses Beispiel für eine stündliche Ausführung:

@hourly /usr/local/bin/python /verzeichnis/eures/Skripts/static_status_notification.py

Zu aufwendig?

Falls euch das ganze Prozedere nun doch etwas zu schwierig erscheint, nicht verzagen! Man kann diesen Service auch für einen läppischen Fünfer von mir kaufen!

Schreibe einen Kommentar