Styling Webforms

Styling webpages? Easy.
I’m guessing a lot of you had to work with CSS at some point in their lives.
Most parts of the web are fairly easy to style,
especially if you know some of the little hacks that you have to use to make a page look pretty.

So you go ahead and style everything the way you want it:
Nice grey background, elements in different shades of blue a bunch of elements in pink for contrast.
You put a nice image as a header for your page and add a sidebar, things that appear and disappear when you hover over them, even some nice animations.
All looking good.

Styling forms? Not so much.
Then you get to the user settings.
You try to apply styles to the checkboxes. Nothing happens.
You try to apply styles to the dropdowns of select elements. Nothing happens.
Need a date selector? Good luck on doing anything to that one!

But why is it so hard to style webforms?

In the end it all comes down to the fact that styling form elements is left up to the browsers.

A select will look different in Chrome than in Safari, Firefox, IE or any other User Agent.
But then again, in a Chrome browser a select will look the same in every web page you look at.

I’m not talking about whether you should or shouldn’t overwrite those defaults.
There are a lot of arguments for and against it, but all I’m going to focus on in this post is the how.


How do you restyle checkboxes?
Especially hacky is how the restyled checkboxes work:
The actual checkbox input is to be hidden:


input[type="checkbox"] {
position: absolute; // take it out of document flow
opacity: 0; // hide it
}

The new box for the checkbox is then built into the label of the checkbox with the ::before selector.
The tick is then styled with the ::after selector like this:


input[type="checkbox"] + label:before {
// Box for Checkbox
}


input[type="checkbox"] + label {
// Actual label
}


input[type="checkbox"]:checked + label:after {
// Tick
}

That way you can have a completely customised checkbox.

How does it look like all put together?
I had a little project where I spent a week researching how to make a webform pretty with only CSS.
The result was a melange of tips and tricks I found all over the web. (That little checkbox trick that i just explained was one of them)

Check it out below!

See the Pen Formstyles for Blogpost by Feu (@the_Feu) on CodePen.

Jennifer Mourek

Autor: Jennifer Mourek

Jennifer hat sich nach Ihrem Abitur erst einmal die große weite Welt angesehen, ehe es sie für Ihre Ausbildung zur Fachinformatikerin für Anwendungsentwicklung ab September 2016 nach Nürnberg zu NETWAYS verschlagen hat. Die Lieblingsfreizeitaktivitäten der gebürtigen Steigerwalderin sind das Zocken, Bouldern und sich mit Freunden und Kollegen auf gemütliche Spiele- und Filmabende zu treffen.

Flapping in Icinga 2.8.0

The author viewing the code for the first time

Flapping detection is a feature many monitoring suites offer. It is mainly used to detect unfortunately chosen thresholds, but can also help in detecting network issues or similar. In most cases two thresholds are used, high and low. If the flapping value, which is the percentage of state changes over a set time, gets higher than the high threshold, it is considered flapping. It will then stay flapping until the value drops below the low threshold.

Naturally Icinga 2 had such a feature, just that it implemented a different approach and didn’t work. For 2.8.0 we decided it was time to finally fix flapping, so I went to investigate. As I said the flapping was working differently from Icinga 1, Shinken, etc. Instead of two thresholds there was just one, instead of one flapping value there were two and they change based on the time since the last check. Broken down it looks like this:

positive; //value for state changes
negate; //value for stable changes
FLAPPING_INTERVAL; //Compile time constant to smoothen the values

OnCheckResult() {
  if (positive + negative > FLAPPING_INTERVAL) {
    pct = (positive + negative - FLAPPING_INTERVAL) / FLAPPING_INTERVAL;
    positive -= pct * positive;
    negative -= pct * negative;
  }

  weight = now - timeOfLastCheck;
  if (stateChange)
    positive += weight;
  else
    negative += weight;
}

IsFlapping() {
  return 100 * positive / (negative + positive);
}

The idea was to have the two flapping values (positive & negative) increase one or the other with every checkresult. Positive for state changes and negative for results which were not state changes, by the time since the last check result. The first problem which arises here, while in most cases the check interval is relatively stable, after a prolonged Icinga outage one of the values could be extremely inflated. Another problem is the degradation of the result, in my tests it took 17 consecutive stable results for a flapping value to calm down.

After some tweaking here and there, I decided it would be wisest to go with the old and proven style Icinga 1 was using. Save the last 20 checkresults, count the state changes and divide them by 20. I took inspiration in the way Shinken handles flapping and added weight to the sate changes, with the most recent one having a value of 1.2 and the 20th (oldest) one of 0.8. The issue of possibly wasting memory on saving the state changes could be resolved by using one integer as a bit array. This way we are actually using slightly less memory now \o/

The above example would then have a value of 39.1%, flapping in the case of default thresholds. More details on the usage and calculation of flapping in Icinga 2 can be found in the documentation once version 2.8.0 is released.

Jean-Marcel Flach

Autor: Jean-Marcel Flach

Geboren und aufgewachsen in Bamberg, kam Jean (das "-Marcel" ist still) nach einem Ausflug an die Uni, als Azubi zu NETWAYS. Dort sitzt er seit 2014 im Icinga 2 core Entwicklungsteam.

Vom Noob-OS zum IPv6-Router

Eigentlich habe ich in meinem letzten Blog-Post angekündigt, diesmal “den abgebissenen Apfel bis auf den Kern” zu schälen. Aber gerade als ich alle Vorbereitungen dafür abgeschlossen hatte, erinnerte mich ein außergewöhnlich religiöser Kollege (der an dieser Stelle nicht namentlich genannt werden möchte) daran, was Adam und Eva damals widerfahren ist, nachdem sie vom selbigen Apfel “nur” abgebissen hatten. Ein Risiko von solchem Kaliber für einen einzigen Blogpost einzugehen, wäre einfach nur unverhältnismäßig. Deshalb beschränke ich mich in diesem Beitrag darauf, dem Skript vom letzten mal IPv6-Unterstützung zu verleihen.

Bestandsaufnahme

Weder die Topologien der Netzwerke, noch die damit einhergehenden Probleme haben sich seit dem letzten Beitrag geändert. Das Setup wurde “lediglich” auf IPv6 umgestellt – schließlich wird man in Zukunft über die Nutzung von IPv4 wahrscheinlich ähnlich wertend reden wie heute über die Nutzung von Schreibmaschinen. Das Problem besteht darin, dass eine VM im Netz 2001:db8::192.0.2.16/124 nicht ohne weiteres mit Containern im Netz 2001:db8::192.0.2.32/124 kommunizieren kann, da sie nicht weiß, dass letztgenanntes Netz hinter der VM 2001:db8::192.0.2.18 liegt. Um dieses Problem zu beheben, kann man entweder jeder einzelner betroffener VM diesen Weg beizubringen – oder man nutzt…

Statische IPv6-Routen auf Mac OS X

Leider ist dies etwas schwieriger, als die Einrichtung von IPv4-Routen – zumindest wenn die VMs mit Parallels betrieben werden. Dem Host wird nämlich die IP 2001:db8::192.0.2.17 nicht automatisch zugewiesen. Und es gibt anscheinend keine Möglichkeit, dies über die Netzwerkeinstellungen dauerhaft zu ändern.

Dann eben durch die Hintertür…

Das zuletzt bereits angelegte Skript /usr/local/sbin/add-static-routes.sh, das beim Systemstart automatisch ausgeführt wird (siehe letzten Blogbeitrag), kann für diesen Zweck mitgenutzt werden, indem man am Ende folgende Zeile hinzufügt:

/usr/local/sbin/assign-inet6-address.pl "$(/usr/local/sbin/get-iface-by-inet-address.pl 192.0.2.17)" 2001:db8::192.0.2.17/124

Alle Skripte, die nicht im letzten Blogpost auftauchen stehen am Ende dieses Blogposts. Die konkreten Daten sind nicht aus der Luft gegriffen, sondern müssen mit den Parallels-Netzwerkeinstellungen übereinstimmen – wobei die Adresse der Netzwerk-Schnittstelle “Subnetz + 1” sein sollte:

2001:db8::c000:210 + 1 = 2001:db8::c000:211 = 2001:db8::192.0.2.17

Zurück zu der Route

Nach der eben vollendeten Überwindung der Parallels-Hürde steht der Eigentlichen statischen Route nichts mehr im Wege. Diese wird einfach in /usr/local/sbin/add-static-routes.sh mit aufgenommen:

/usr/local/sbin/add-static-route6.pl 2001:db8::192.0.2.32/124 2001:db8::192.0.2.18

Diese Route tritt spätestens nach einem Neustart in Kraft. Mangels Geduld kann man auch die zwei hinzugefügten Zeilen direkt auf der Kommandozeile ausführen:

# bash
bash-3.2# /usr/local/sbin/assign-inet6-address.pl "$(/usr/local/sbin/get-iface-by-inet-address.pl 192.0.2.17)" 2001:db8::192.0.2.17/124
bash-3.2# /usr/local/sbin/add-static-route6.pl 2001:db8::192.0.2.32/124 2001:db8::192.0.2.18

Fazit

“Warum extrem einfach wenn es auch unnötig kompliziert geht?” Diesem Motto werde ich auch weiterhin treu bleiben – also stay tuned!

Skripte

/usr/local/sbin/get-iface-by-inet-address.pl

#!/usr/bin/perl 

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $inet_addr = shift;

exit 2 if ! defined $inet_addr; # RTFM at https://wp.me/pgR2o-rur


my $iface;
$inet_addr = quotemeta($inet_addr);

POLL: for (;;) {
	for (`/sbin/ifconfig`) {
		if (/^(\S+?): /) {
			$iface = $1
		} elsif (defined($iface) && /^\tinet $inet_addr /) {
			print $iface;
			last POLL
		}
	}

	sleep 1
}

/usr/local/sbin/assign-inet6-address.pl

#!/usr/bin/perl 

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $iface = shift;
my $inet6_addr = shift;

exit 2 if !(defined($iface) && defined($inet6_addr) && $inet6_addr =~ m~^(.+)/(\d+)$~); # RTFM at https://wp.me/pgR2o-rur


my $status = system("/sbin/ifconfig", $iface, "inet6", $1, "prefixlen", $2) >> 8;
die "/sbin/ifconfig: $status" if ($status != 0)

/usr/local/sbin/add-static-route6.pl

#!/usr/bin/perl 

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $destination = shift;
my $gateway = shift;

exit 2 if !(defined($destination) && defined($gateway) && $destination =~ m~^(.+)/(\d+)$~); # RTFM at https://wp.me/pgR2o-rur


$destination = $1;
my $destination_prefixlen = $2;
my $gatewayBin = ip6adr2bin($gateway);

POLL: for (;;) {
	for (`/sbin/ifconfig`) {
		if (/^\tinet6 (.+?)(?:%\S+)? prefixlen (\d+)/) {
			if (ip6bin2prefix($gatewayBin, $2) eq ip6bin2prefix(ip6adr2bin($1), $2)) {
				my $status = system("/sbin/route", "add", "-inet6", "-prefixlen", $destination_prefixlen, "-net", $destination, $gateway) >> 8;
				die "/sbin/route: $status" if ($status != 0);
				last POLL
			}
		}
	}

	sleep 1
}


sub ip6adr2bin
{
	my $raw = shift;

	if ($raw =~ /::/) {
		my ($head, $tail) = split(/::/, $raw);
		$head = ip6part2bin($head);
		$tail = ip6part2bin($tail);

		return $head . ("0" x (128 - (length($head) + length($tail)))) . $tail
	}

	ip6part2bin($raw)
}

sub ip6bin2prefix
{
	my $addr = shift;
	my $prefixlen = shift;

	substr($addr, 0, $prefixlen) . ("0" x (128 - $prefixlen))
}

sub ip6part2bin
{
	join("", map({ /\./ ? join("", map({ sprintf("%08b", $_) } split(/\./, $_))) : sprintf("%016b", hex($_)) } split(/:/, shift())))
}
Alexander Klimov

Autor: Alexander Klimov

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der Arbeit an Icinga Web 2 bei uns friedliche Wege.

Monthly Snap September > SensorProbe 2+, Icinga Director, OSBConf 2017, DevOpsDays, Benchmarking Graphite, OSMC

In September, Isabel started with introducing Intelligente Überwachung mit der AKCP sensorProbe 2+ while Eric shared his tips on Hidden pearls in Icinga Web 2. Nicole shared important information on NETWAYS Web Services on Request Tracker.

Marius told us how VM volumes live works using blkdeviotune and Shopware Update, Julia announced for new upcoming Advanced Puppet training and 7 reasons for join OSBConf. Markus shared Trick 17 with the Icinga Director while Tobias shared Trick 42 with the Icinga Director – Job in order.

Julia Announced OSMC in Hackathon, DevOpsDays in Berlin and continued with reasons for OSBConf 2017,she also  said thank to sponsors of OSBConf.

Blerim told us about Benchmarking Graphite, Nicole reviewed Managed Services team event 2017, And Dirk again shared his insights in The Consultant and The dear Certifications II.

Keya Kher

Autor: Keya Kher

Keya hat im Oktober ihr Praktikum im Marketing bei NETWAYS gestartet. Letzten Dezember startete Sie gemeinsam mit Ihrem Mann das “Abenteuer Deutschland”. Seitdem lernt Sie fleißig deutsch und fühlt sich bei NETWAYS schon jetzt pudelwohl. Sie hat schon viele Erfahrungen im Social Media Marketing und ist gerade dabei auch im Grafikdesign ein Profi zu werden. Wenn sie nicht gerade dabei ist, sich kreativ auszuleben, entdeckt sie die Stadt und schmökert gerne im ein oder anderen Büchlein. Ihr Favorit ist hierbei “The Shiva Trilogy”.

Vom Noob-OS zum IPv4-Router

Dass man die Docker-Alternative LXD ohne große Hürden auch auf Mac OS X betreiben kann, habe ich in meinem letzten Blog-Post bereits detailliert erläutert.

Leider kann ich im Rahmen meiner Arbeit nicht alles in diesen Ubuntu-Containern betreiben. Die Entwicklungsumgebungen für so manche Anwendungen wie z. B. Icinga Web 2 werden mit Vagrant provisioniert und dieses Programm lässt sich nur sehr mühsam an LXD koppeln. Deshalb komme ich nur mit der einen LXD-VM wohl oder übel nicht aus.

Spätestens wenn die anderen VMs (oder deren Container) mit den LXD-Containern kommunizieren müssen, stößt dieses Setup an seine Grenzen… oder?

Das Setup im Detail

Wie auch jeder andere Gewerbebetrieb, in dem keine Schreibmaschinen mehr zum Einsatz kommen, verfügt NETWAYS über ein internes IP-Netz – beispielhaft mit den Host-Adressen 192.0.2.1 – 192.0.2.14. Der Router zum Internet beansprucht für sich die 192.0.2.1 und meinem Arbeitsgerät ist die 192.0.2.2 zugeteilt.

Um mit meinen virtuellen Maschinen kommunizieren zu können, teilt meine Workstation sich ein IP-Netz mit ihnen (192.0.2.17 – 192.0.2.30). Und schließlich sollen auch meine LXD-Container nicht so isoliert sein wie ein Schreibmaschinen-Nutzer – deshalb teilen sie sich ein wieder anderes IP-Netz (192.0.2.33 – 192.0.2.46) mit der LXD-VM.

Wenn nun ein Knoten einen anderen ansprechen will, muss er entweder im selben IP-Netz sein wie der gewünschte Gesprächspartner – oder in der Netz-Hierarchie unter einem Router stehen, der den gewünschten Gesprächspartner erreichen kann.

Beispiel #1

LXD-Container #1 will mit 192.0.2.50 kommunizieren, ist aber nicht im selben Netz. Ihm bleibt nichts anderes, als über sein Standard-Gateway, 192.0.2.33, zu senden und zu hoffen, dass die Verbindung erfolgreich zustande kommt. Die LXD-VM ist aber auch nicht im selben Netz. Daher muss sie sich wiederum auf ihren Standard-Gateway (192.0.2.17) verlassen. Meine Workstation delegiert wiederum an 192.0.2.1 usw.. Und wenn da draußen tatsächlich eine 192.0.2.50 online ist (und alle Internet-Router so rund laufen wie unser Firmen-Gateway) kommt letztendlich die Verbindung erfolgreich zustande.

Beispiel #2

VM #1 will mit 192.0.2.34 kommunizieren, ist aber nicht im selben Netz. Ihr bleibt nichts anderes, als an ihr Standard-Gateway, 192.0.2.17, zu delegieren. Leider weiß Mac OS nichts vom Netz 192.0.2.32/28 und delegiert an unser Firmen-Gateway. Das und alles dahinter kann noch so rund laufen, aber der Zug in Richtung des LXD-Container-Netzes ist längst abgefahren.

Aber ich würde nicht schon gut 3,5 Jahre bei NETWAYS arbeiten wenn ich diese Hürde nicht spielend einfach überwinden könnte. Dazu braucht es nur…

Statische Routen auf Mac OS X

Natürlich könnte ich auch auf jeder VM eine statische Route hinterlegen, aber das wäre zusätzlicher Aufwand bei jeder VM-Erstellung. Sollte darüber hinaus die Anzahl der VMs mit Linux-Containern zunehmen, steigt damit auch mein Aufwand beim Routen-Management nicht zu knapp…

Deshalb ist es langfristig so oder so sinnvoller, alle VMs an die Workstation delegieren zu lassen und diese zum Router zu befördern. Wie praktisch, dass Mac OS X auf 4.4BSD basiert und damit zur *nix-Familie gehört. Damit ist dieses Vorhaben ein Kinderspiel (wenn man weiß wie es geht).

Jetzt aber endlich mal Butter bei die Fische

Schritt 1: Konzentration!

Um Mac OS die gewünschten statischen Routen beizubringen, muss man tiefer ins System eingreifen, als es ein durchschnittlicher Mac-Nutzer es gewohnt ist. Dabei lässt sich mit ein bisschen Schusseligkeit sehr viel kaputt machen. Wenn Du gerade z. B. eine ordentliche Portion G&T konsumiert hast… habe Geduld. Morgen ist auch noch ein Tag und Mac OS läuft schon nicht weg.

Schritt 2: Root-Rechte

Obwohl Mac OS sich an weniger versierte Nutzer richtet, bietet es die Möglichkeit, Root-Rechte zu erlangen wie man das von verbreiteten GNU/Linux-Distributionen kennt:

Alexanders-MacBook-Pro:~ aklimov$ sudo -i
Password:
Alexanders-MacBook-Pro:~ root#

Schritt 3: Hilfs-Skripte

Die eben erlangten Privilegien berechtigen uns, Skripte in dem OS vorbehaltene Verzeichnisse zu platzieren – wovon wir auch Gebrauch machen, indem wir zunächst das Verzeichnis /usr/local/sbin erstellen und darin zwei Skripte ablegen:

Alexanders-MacBook-Pro:~ root# mkdir -p /usr/local/sbin
Alexanders-MacBook-Pro:~ root# vim /usr/local/sbin/add-static-route.pl
Alexanders-MacBook-Pro:~ root# chmod 0755 /usr/local/sbin/add-static-route.pl
Alexanders-MacBook-Pro:~ root# vim /usr/local/sbin/add-static-routes.sh
Alexanders-MacBook-Pro:~ root# chmod 0755 /usr/local/sbin/add-static-routes.sh

Das erste Skript, /usr/local/sbin/add-static-route.pl, dient dem Hinzufügen von statischen Routen, sobald die entsprechende Netzwerk-Schnittstelle online ist:

#!/usr/bin/perl

# (C) 2017 NETWAYS GmbH | GPLv2+
# Author: Alexander A. Klimov

my $destination = shift;
my $gateway = shift;

if (!(defined($destination) && defined($gateway))) {
    exit 2 # RTFM at https://wp.me/pgR2o-rlj
}


my $gatewayDec = ip4_2dec($gateway);

POLL: for (;;) {
    for (`/sbin/ifconfig`) {
        if (/^\tinet (.+?) netmask (.+?) /) {
            my $mask = hex($2);
            if (($gatewayDec & $mask) == (ip4_2dec($1) & $mask)) {
                my $status = system("/sbin/route", "add", "-net", $destination, $gateway) >> 8;
                die "/sbin/route: $status" if ($status != 0);
                last POLL
            }
        }
    }

    sleep 1
}


sub ip4_2dec
{
    hex(join("", map({ sprintf("%02x", $_) } split(/\./, shift()))))
}

Das zweite Skript, /usr/local/sbin/add-static-routes.sh, ruft das erste Skript auf und fügt damit konkrete Routen hinzu:

#!/bin/bash

set -e
set -o pipefail

/usr/local/sbin/add-static-route.pl 192.0.2.32/28 192.0.2.18

Die Kommandozeilen-Schnittstelle des ersten Skripts habe ich extra so gestaltet, dass die Routen-Liste (das zweite Skript) möglichst einfach erweitert werden kann. Wenn bspw. eine zweite LXD-VM mit der IP-Adresse 192.0.2.21 dazukommt und mit ihren Containern über das Netz 192.0.2.64/28 verbunden ist, gehört folgende Zeile ans Ende der Routen-Liste:

/usr/local/sbin/add-static-route.pl 192.0.2.64/28 192.0.2.21

Schritt 4: Autostart

Damit das zweite Skript nicht bei jedem Systemstart manuell ausgeführt werden muss, lassen wir Mac OS es für uns automatisch starten:

Alexanders-MacBook-Pro:~ root# pushd /Library/LaunchDaemons
/Library/LaunchDaemons ~
Alexanders-MacBook-Pro:LaunchDaemons root# vim mystaticroutes.plist
Alexanders-MacBook-Pro:LaunchDaemons root# launchctl load mystaticroutes.plist

Inhalt von mystaticroutes.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>MyStaticRoutes</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/sbin/add-static-routes.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
  </dict>
</plist>

Fazit

Obwohl mich die Kollegen aus den eigenen Reihen – aber auch aus NMS und PS – spätestens seit diesem Blogeintrag mit besorgten Blicken überschütten, werde ich einfach nicht müde, das Noob-OS von Apple auf biegen und brechen meinen seltsamen Bedürfnissen entsprechend aufzubohren.

Abonniert gerne kostenlos diesen Blog um auch über die nächste Runde informiert zu werden – wenn ich den abgebissenen Apfel bis auf den Kern schäle…

Alexander Klimov

Autor: Alexander Klimov

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der Arbeit an Icinga Web 2 bei uns friedliche Wege.

Revisited – Graphite-Web installation unter Debian 9

Erstmal wieso Revisited ?

Dies ist ein update meines älteren Blog Posts Blogpost 2016 welcher darauf einging das unter Debian 8.4 graphite-web wegen eines Fehlenden Eintrages in der Apache 2.4 Konfiguration nicht korrekt gestartet/aufgerufen werden konnte.
Es ist schon einige Zeit ins Land gegangen und ich habe weniger ein Auge darauf geworfen ob das weiterhin so Funktioniert.
Deshalb Revisited.

Here we Go again !

Ich gehe in diesem Fall von einer Debian Version der Nummer 9 aus und werde wie bei dem alten Blogpost. In der Grundannahme mal davon ausgehen das alles Funktioniert wie es soll:

Also hier die folgenden installationschritte:

#> apt-get install apache2 libapache2-mod-wsgi python-django python-django-tagging fontconfig python-tz python-pip python-dev python-twisted python-cairo
#> pip install carbon whisper graphite-web
#> pip install --upgrade twisted
#> cp /opt/graphite/conf/carbon.conf.example /opt/graphite/conf/carbon.conf
#> cp /opt/graphite/conf/storage-schemas.conf.example /opt/graphite/conf/storage-schemas.conf
#> /opt/graphite/bin/carbon-cache.py start
#> /opt/graphite/bin/carbon-cache.py status
#> cp /opt/graphite/examples/example-graphite-vhost.conf /etc/apache2/sites-available/graphite.conf
#> cp /opt/graphite/conf/graphite.wsgi.example /opt/graphite/conf/graphite.wsgi
#> cp /opt/graphite/webapp/graphite/local_settings.py.example \ /opt/graphite/webapp/graphite/local_settings.py
#> python /opt/graphite/webapp/graphite/manage.py syncdb
#> chown www-data. -R /opt/graphite/storage
#> a2dissite 000-default
#> a2ensite graphite
#> a2enmod wsgi
#> service apache2 restart
#> chmod +x /etc/init.d/carbon-cache // Damit 'carbon-cache.py start' mit Systemstart erfolgt

Ergebnis davon ist -> Nichts funktioniert.

Back to the Roots

Ab hier kommt der Weg graphite-web auf einem Debian 9 (Stretch) in Betrieb zu nehmen.

Ausgangspunkt ist ein frisch installiertes Debian 9.

#> apt-get install vim -y
#> vim /etc/apt/sources.list

Wir müssen die Sources auf die Jessie Repositories setzen da zum Zeitpunkt dieses Blogposts die graphite-web Pakete nicht abrufbar sind.

Daher fügen wir folgendes hinzu in der sources.list
deb http://httpredir.debian.org/debian jessie main
Gefolgt von einem frischem #> apt-get update -y .

Nun installieren wir den großteil der Pakete welche wir benötigen.
#> apt-get install graphite-web graphite-carbon mysql-server python-mysqldb python-pymysql apache2 libapache2-mod-wsgi apt-transport-https ssl-cert python-pip -y

Es folgen ca. 300MB an Daten.
Daraufhin stürzen wir uns direkt auf die Konfig.

Wir fangen an folgende Datei zu editieren.
#> vim /etc/graphite/local_settings.py
Darin ändern wir folgende Settings Sinnvoll in etwas was wir für unsere Installation benötigen.

Also SECRET_KEY, TIME_ZONE & ALLOWED_HOSTS setzen.

Danach muss in der folgenden Datei ein “true” gesetzt werden damit graphite & carbon gemeinsam starten.

#> vim /etc/default/graphite-carbon

Nun kommt der trickreichste Part wir sind leider dazu genötigt eine alte django Version zu installieren.

#> pip install "django==1.4"

Damit haben wir die Grundlage womit wir das folgende Kommando erfolgreich absetzen können.

#> graphite-manage syncdb
#> chown _graphite. /var/lib/graphite/graphite.db
HINWEIS ! Dies setzt erst mal die voreingestellte sqlitedb in Gang.
Wenn eine andere DB verwendet werden soll dann sollte dies bitte in der “local_settings.py” vorgenommen werden.

Wir sind fast am Ziel ein funktionierendes graphite-web zu haben.
Es fehlt nur etwas Apache2 Magie.

#>a2dissite 000-default.conf
#>cp /usr/share/graphite-web/apache2-graphite.conf /etc/apache2/sites-available/
#> a2ensite apache2-graphite.conf
#> systemctl restart apache2

Voilà !

Es sollte nun auf dem Host System das graphite-web aufrufbar sein.

Danke für die Aufmerksamkeit !

David Okon

Autor: David Okon

Weltenbummler David hat aus Berlin fast den direkten Weg zu uns nach Nürnberg genommen. Bevor er hier anheuerte, gab es einen kleinen Schlenker nach Irland, England, Frankreich und in die Niederlande. Alles nur, damit er sein Know How als IHK Geprüfter DOSenöffner so sehr vertiefen konnte, dass er vom Apple Consultant den Sprung in unser Professional Services-Team wagen konnte. Er ist stolzer Papa eines Sohnemanns und bei uns mit der Mission unterwegs, unsere Kunden zu glücklichen Menschen zu machen.