Neues Projekt EasySkillTracker

Plattformen wie Udemy, Coursera und andere ermöglichen es auf einfache Art neue Fähigkeiten zu lernen. Die Kurse sind dort strukturiert und abgeschlossene Videos und Ressourcen lassen sich markieren. Ich habe nach einer Lösung gesucht, die ich selber betreiben kann um übergreifende Quellen (YouTube, Ted Talks, Links, …) zu Kursen zusammenzufassen. Leider habe ich nichts gefunden. Darum ist der EasySkillTracker entstanden der frei auf GitHub erhältlicht ist.

Umfang

Alle Daten liegen in lesbaren JSON Dateien. Ein Kurs und alle Inhalte dazu liegen in genau einer Datei. Diese kann leicht mit anderen geteilt werden. Außerdem lässt sich ein Kurs in Versionsverwaltungssystemen versionieren und verwalten.

Die Oberfläche ist auf die essentiellstens Teile optimiert. Auf allen Endgeräten können die Ressourcen geöffnet und als erledigt markiert werden.

Der Code ist quelloffen und kann eingesehen, verbessert und erweitert werden. EasySkillTracker lässt sich auf jedem System einfach bauen und starten. Für eine höhere Sicherheit empfhielt sich jedoch ein Proxy mit Passwortverwaltung als Vorsystem (z.B. Nginx).

Download auf der GitHub Webseite von EasySkillTracker.

DevOps im Startup

In agilen Umgebungen wie Startups sind starre Trennungen von Softwareentwicklung und IT Operations eher selten anzutreffen. Doch auch viele große Unternehmen wechseln immer öfter auf agile Prozesse und einem dazu passenden IT Umfeld. DevOps ermöglicht die Vernetzung der klassischen Silos. Durch die Einführung intelligenter und automatisierter Prozesse lässt sich die Auslieferung der Software und dessen Qualität erheblich steigern.

Die gängigen DevOps Prozesse und Tools decken die Bereiche Planung, Entwicklung, Build, Test, Release, Deployment, Operations und Monitoring ab. Welche Prozesse dabei automatisiert werden sollen und zu welchem Zeitpunkt hängt maßgeblich vom Reifegrad des Unternehmens und der verfügbaren Zeit ab. Dabei muss die DevOps Umgebung am Anfang nicht so perfekt optimiert sein wie bei Netflix deren Automatiserungsgrad einzigartig ist. Für die Einführung der Tools und Prozesse muss Zeit aufgewendet werden welche dann in der Entwicklung fehlt. Gerade bei Startups die noch ihr MVP (Minimum Viable Product) am Markt erproben wäre eine vollständige Automatisierung noch verfrüht. Dennoch hilft eine frühzeitige Einführung auch hier die Produktivität und Qualität zu erhöhen. Exemplarisch möchte ich die Umsetzung meines letzten Stacks für ein schnell wachsendes Startup Unternehmen beschreiben.

Ausgangslage und Anforderungen

Das MVP ist am Markt erprobt und das Team hat bereits einige Entwickler an Board. Die primären Anforderungen sind somit die Qualität der Software erhöhen, idealerweise durch Testautomatisierung und Code-Quality-Standards. Neue Features müssen jederzeit und von jedem Mitarbeiter getestet werden können bevor diese in die Produktionsumgebung kommen. Somit müssen mehrere Testumgebungen verfügbar sein. Im Hinblick auf weitere neue Entwickler sollen diese schnell produktiv sein. Außerdem müssen alle Umgebungen zur Nachstellung von Problemen gleichartig aufgesetzt und konfiguriert sein.

A fool with a tool is still a fool.

Ein weiteres wichtiges Kriterium ist eine einfache Wartbarkeit und Administration. Probleme und Anforderungen sollen nicht mit einem Zoo aus tausend Tools erschlagen werden. Dabei ist eine wichtige Frage welche Programme selber gehostet werden sollen und wo ein Zukauf bzw. ein SaaS Modell sinnvoll ist. Natürlich gilt es den Datenschutz bei letzterem zu wahren. Selber administrierte Tools müssen immer auf dem aktuellsten Softwarestand und mit sicheren Konfigurationen bestückt sein.

Tools

Ansible

Eines der zwei zentralen Tools ist hier Ansible geworden. In den sogenannten Playbooks und den Konfigurationsdateien lässt sich die gesamte Umgebung definieren. Ansible verfolgt dabei den Ansatz, dass der Endzustand beschrieben wird. Die Definition für den Applikationsserver sieht dann also beispielsweise wie folgt aus.

  • [AppServer]
    • Server1
    • Server2
  • [AppServer Installation]
    • nginx: installiert
    • PM2: gestartet
    • DatendankVerbindung: DbServerCluster

Ich nutze Ansible sogar um die Server direkt bei dem Cloud Anbieter aufzusetzen. Somit gibt es zwei Ansible Projekte. Ein Projekt um die gesamte Serverumgebung inkl. Datenbankservern, VPNs, Firewall Regeln, SSH-Keys und Object Storages zu verwalten und ein zweites Projekt welches dann für jeden Server die Software und deren Konfiguration beschreibt. Durch die einfache Konfiguration können somit innerhalb weniger Minuten beliebig viele gleichartige Integrations-/Testumgebungen aufgebaut werden. Alle Umgebungen werden außerdem automatisch in die Monitoring- (Icinga/Nagios) und Loggingumgebung (Graylog 2) eingebunden. Ich habe mich bewusst gegen Datadog und ähnliche SaaS Dienste entschieden weil die Administration und Konfiguration von Tools wie Graylog, Icinga, Elasticsearch und vielen mehr mit Ansible ein Kinderspiel ist. Wichtig sind hier nur zuverlässige und sichere Konfigurationsdefinitionen und sauber abgetrennte Netzwerkbereiche und Firewall Regeln.

Jenkins

Die zweite Zentrale Software ist Jenkins. Dieser löst Deploybot ab um mehr Kontrolle über den gesamten Release Prozess zu haben. Jenkins kümmert sich um mehrere Teile. Zum einen prüft er sämtliche Check-Ins die auf GitHub getätigt werden. Dies umfasst die Prüfung der Code Qualität (Linting, SonarQube, …). Zum anderen führt Jenkins Unit Tests durch, startet die API Tests mit postman bzw. newman und führt die User Acceptance Tests von Selenium aus. Abhängig von den gewählten Branches automatisiert Jenkins auch das Deployment. Sämtliche commits auf den develop branch führen zu einem Deployment auf die Integrationsumgebung. Alle master commits müssen von mindestens zwei Entwicklern und Jenkins selber geprüft werden und führen dann zu einem Deployment auf die Produktionsumegbung.

Jeder Entwickler hat darüber hinaus jederzeit die Möglichkeit beliebige Branches auf Testumgebungen zu deployen. Dabei kann außerdem festgelegt werden welche Testdaten initial in den Datenbankservern zur Verfügung gestellt werden. Die Testumgebungen werden darüber hinaus in gesonderten virtuellen Netzwerken aufgebaut.

Produktion als lokale Entwicklunsumgebung

Ansible funktioniert auch mit Vagrant. Sämtliche Konfigurationen die für die Serverumgebungen definiert sind funktionieren somit auch lokal. Jeder Entwickler hat daher eine Umgebung deren Softwarestände und Konfiguration 1:1 mit der Produktion übereinstimmen. Lediglich die Datenbank ist in den Entwicklungsumgebung lokal anstelle von dedizierten Servern. Die lokalen Umgebungen können jederzeit auf Knopfdruck neu erstellt werden und erhalten direkt Testdaten. Neue Mitarbeiter lassen sich somit innerhalb von ca. 30 Minuten arbeitsfähig einbinden!

Zusammenfassung

Durch die Automatisierung des Aufbaus der lokalen Entwicklungsumgebung bis hin zur vollständigen Serverumgebung und der Automatisierung der Deployments findet jeder Entwickler jederzeit gleichartige Umgebungen vor. Fehler können lokal nachgestellt werden und notwenige Konfigurationsänderungen werden versioniert und auditiert zentral verwaltet. Jeder Entwickler kann jederzeit Änderungen von Code und Infrastruktur nachvollziehen und überprüfen.

 

Bildquelle: pixabay.com

MagicMirror² Dashboard

Endlich den MagicMirror² bauen stand schon sehr lange auf meiner ToDo-Liste. In der Kombination Urlaub und Erkältung habe ich das also umgesetzt. Selbst bei der manuellen Installation dauert die gesamte Einrichtung für ein Dashboard weniger als 15 Minuten. Ich wollte den Spiegel nicht als Wandspiegel nutzen, sondern nur als Dashboard oder vielleicht als Startseite im Browser. Somit entfällt das Bauen eines schönen Rahmens für den Monitor sowie das Beschaffen von durchlässigem Spiegelglas.

Umsetzung

Entweder die automatische Installationsdatei von der Webseite ausführen oder der Anleitung für die manuelle Installation folgen. Letzteres beschränkt sich auf das Code clonen und Node Module installieren. In der Zeit die der Raspberry Pi für das Kopieren der Module benötigt bietet sich das Lesen der Dokumentation an.

Nach dem auschecken habe ich die config Datei angepasst. Insbesondere das Freischalten meiner IP-Adresse vom Windows Rechner erlaubt mir den Zugriff über den Browser auf die Oberfläche. Aus diesem Grund starte ich den MagicMirror² nur über node serveronly. Das erlaubt mir auch die Momentum - Personal Dashboard New Tab Chrome Extension als Startseite zu ersetzen. Mit dem MM kann ich meine Startseite deutlich besser nach meinen Wünschen anpassen. Außerdem entfällt die monatliche Gebühr.

Der MagicMirror² lässt sich mit viele Modulen beliebig erweitern.

Module

Derzeit sind diese Module bei mir aktiv.

Noch nicht ausprobiert aber in Planung sind die folgenden Module.

Meine Config

config.js

var config = {
    [...]
        language: "de",
        timeFormat: 24,
        units: "metric",
    [...]
        modules: [
                {
                        module: "calendar",
                        header: "Termine",
                        position: "top_left",
                        config: {
                                calendars: [
                                        {
                                                symbol: "calendar-check-o ",
                                                url: "https://calendar.google.com/calendar/ical/de.german%23holiday%40group.v.calendar.google.com/public/basic.ics"
                                        }
                                ]
                        }
                },
    [...]
                {
                        module: "compliments",
                        position: "middle_center",
                        config: {
                                remoteFile: "remote_compliments.json"
                        }
                },
                {
                        module: "currentweather",
                        position: "top_right",
                        config: {
                                location: "XXXXXXXXXXXX",
                                locationID: "XXXXXXXXXXXX",
                                appid: "XXXXXXXXXXXX"
                        }
                },
                {
                        module: "weatherforecast",
                        position: "top_right",
                        header: "Weather Forecast",
                        config: {
                                location: "XXXXXXXXXXXX",
                                locationID: "XXXXXXXXXXXX",
                                appid: "XXXXXXXXXXXX"
                        }
                },
                {
                        module: "newsfeed",
                        position: "bottom_bar",
                        config: {
                                feeds: [
                                        {
                                                title: "Stern",
                                                url: "https://www.stern.de/feed/overview/"
                                        },
                                        {
                                                title: "Spiegel",
                                                url: "http://www.spiegel.de/index.rss"
                                        },
                                        {
                                                title: "Heise",
                                                url: "https://www.heise.de/newsticker/heise-atom.xml"
                                        },
                                        {
                                                title: "Golem",
                                                url: "https://rss.golem.de/rss.php?feed=RSS1.0"
                                        },
                                        {
                                                title: "Tagesschau",
                                                url: "http://www.tagesschau.de/xml/rss2"
                                        }
                                ],
                                showSourceTitle: true,
                                showPublishDate: true
                        }
                },
                {
                        disabled: true,
                        module: 'MMM-DailyDilbert',
                        position: 'bottom_bar',
                        config: {
                                updateInterval : 36000000
                        }
                },
                {
                        disabled: false,
                        module: "MMM-BMI",
                        position: "top_center",
                        config: {
                                name: "Sebastian",
                                imperialUnits: false,
                                weight: "111",
                                height: "111",
                                herName: "hidden",
                                herWeight: "111",
                                herHeight: "111",
                                useHeader: true,
                                header: "Gewicht",
                                maxWidth: "350px",
                        }
                },
                {
                        module: 'MMM-BackgroundSlideshow',
                        position: 'fullscreen_below',
                        config: {
                                imagePaths: ['modules/MMM-BackgroundSlideshow/myImages'],
                                transitionImages: true,
                                randomizeImageOrder: true,
                                recursiveSubDirectories: true
                        }
                },
        ]
};

custom.css

 body {
   cursor: default;
 }

.MMM-BMI .header {
  color: #FFF;
}

.MMM-BMI .calc {
  color: #FFF;
}

.MMM-BMI .diagnosis {
  color: #FFF;
}

.MMM-BMI .spacer {
  color: #FFF;
  display: none;
}

.MMM-BMI .herCalc {
  color: #FFF;
  display: none;
}

.MMM-BMI .herDiagnosis {
  color: #FFF;
  display: none;
}
Hugo Shortcodes und Best Practices

Der statische Webseiten Generator Hugo ermöglicht schnelle und sichere Webseiten allerdings sind ein paar Fallstricke zu beachten. Ich habe meine Best Practices und nützliche Shortcodes in zwei Git Repositories zur Verfügung gestellt.

Hugo Best Practices

Das hugo-best-practices Repository beinhaltet eine Übersicht und viele Hilfen für den Umgang mit Hugo. Die Themen umfassen Verzeichnisstrukturen, Asset Optimierung und wichtige Tipps für Deployments, SEO und Performance. Alle Dokumente sind in englische Sprache erstellt damit die Community sich daran beteiligen kann.

Shortcodes

In dem hugo-shortcodes Repository gibt es eine Sammlung von nützlichen Funktionen für Hugo. Dies umfasst beispielsweise <figure> Blöcke mit automatischer Bildoptimierung.

Stackshare

Für meine Seite gibt es auch eine Übersicht der genutzten Tools auf stackshare.

 

Bildquelle: pixabay.com

WordPress zu Hugo

Etwas mehr als 1,5 Jahre ist es her, dass ich einen großen Teil meiner Webseiten zu WordPress migrierte. Jetzt sind sechs meiner Webseite mit Hugo erstellt. Dafür gibt es einige Gründe und auch ein paar Hindernisse.

Hugo

Zuerst ein kurzer Exkurs über Hugo. Hierbei handelt es sich um einen statischen Webseiten Generator welcher in der Programmiersprache Go geschrieben ist. Im Gegensatz zu WordPress liegen alle Daten und Inhalte in lokalen Dateien und nicht in einer Datenbank. Die Webseite wird vollständig aus diesen Daten generiert. Daraus ergeben sich direkt ein paar Vorteile. In der Ladezeit der Webseite fallen Datenbankabfragen und das Generieren der Inhalte raus. Statische Webseiten sind damit prinzipiell um Längen schneller als dynamisch generierte Webseiten. Außerdem sind statische Webseiten prinzipbedingt sicherer. Schadcode lässt sich nicht einfach über Sicherheitslücken in dem CMS System einschleusen. Ein großer Nachteil liegt aber darin, dass dynamische Inhalte schwieriger umzusetzen sind.

Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. (Hugo Webseite)

Die Pro Seite

Wie oben beschrieben sind die Webseiten initial meistens extrem schnell und durch optimiertes Assetmanagemet nochmal deutlich schneller. Lediglich ein Theme in meinen Tests nutze ein externen und langsames CDN um viele Javascript Dateien nachzuladen.

Durch das Generieren der Webseiten bin ich nun komplett unabhängig von dem schnelllebigen PHP und der MySQL Datenbank. Die Inhalte werden nur bei neuen Beiträgen lokal neu generiert und dann hochgeladen (bzw. in Zukunft über meinen Buildserver).

Alle Inhalte kann ich in schlanken und übersichtlichen Markdown Dateien pflegen. Die relevanten Bilder für die Beiträge liegen im selben Ordner. Jedes Bild ist mit seiner maximalen Auflösung gespeichert. Shortcodes generieren die benötigten Größen beim Bauen. Dadurch muss nur eine Datei pro Projekt vorhanden sein. Die perfekte Auflösung ist bei einem Wechsel des Themes somit auch sicher (sofern das Original groß genug war…).

Jede Webseite kann als Ganzes Projekt bei GitHub, Bitbucket oder jedem anderen Versionsverwaltungssystem versioniert werden. Es gibt somit automatisch eine Historie. Bei vielen Providern können die Markdown Dateien auch direkt auf der Webseite betrachtet werden. Theoretisch lassen sich die Inhalte auch im GitHub Editor bearbeiten. Einige Projekte nutzen dies um die Dokumentation ihrer Software einfach zu ermöglichen.

Ich muss mich nicht mehr mit ständig aktualisierten WordPress Plugins und deren Hinweisen auf neue Pro Versionen herumärgern. Daten über meine Webseite laden nun auch nicht mehr bei fremden Anbietern. Durch die fehlenden Plugins (bzw. deren native Einbindung in Hugo) ist der Footprint trotz der vielen WordPress Optimierungen deutlich kleiner. Javascript Dateien von 24 auf 1 und CSS Dateien von 15 auf 4 auf einer meiner Webseiten.

Was gegen Hugo spricht

Hugo ist meiner Meinung nach nur für Nutzer welche sich mit Dateien, Kommandozeile, Versionsverwaltungssoftware und HTML wohl fühlen. Natürlich kann eine minimale Seite mit einem Standardtheme erstellt werden aber dann ist an Anpassungen nicht zu denken.

Viele Themes bei Hugo sind leider etwas älter. Also sie wurden erstellt vor den 0.3*/0.4 Versionen. Dadurch sind Features wie Assets Bundles und Minification nicht vorhanden. Ich musste bei JEDEM Theme selber Hand anlegen. Einige Themes hatten die Verkleinerung von Bildern nicht dabei. Bei anderen Themes fehlten grundlegende SEO Funktionen. Oft waren die CSS Dateien nicht minifiziert oder es wurden mehrere Dateien eingebunden. Ein Bundling ist bei neuen Hugo Versionen Standard. Das Theme muss dies aber berücksichtigen.

Fazit

Für technisch Interessierte oder Webmaster die optimale Webseiten bauen möchten ist Hugo eine spannende Wahl. Bei PageSpeed Insights von Google Developers sind hohe Punktzahlen quasi garantiert. Mit der Hilfe von bundling und minification in den neuen Versionen gibt es diese Features ohne npm, grunt, webpack oder andere Tools jetzt geschenkt. Die Toolchain beschränkt sich somit auf Hugo und gegenbenenfalls Cotinous Deployment Software wie Jenkins oder Deploybot.

WordPress ist für einen großen Teil der Seitenbetreiber natürlich weiterhin eine gute Wahl. Allerdings sollte man sich der Schwächen bewusst sein. Eine einfache Landing Page braucht kein komplettes CMS und jeder Plugin erhöht den Overhead und die Angriffsfläche eines CMS!