MDV

Das kleine Programm mdv kann Markdown auf der Konsole rendern, sodass ein vereinfachtes lesen gegenüber des Quelltextes auf der Konsole möglich wird.

Installation

Der Terminal Markdown Viewer lässt sich einfach per yay aus dem AUR Repository installieren.

 yay -S --noconfirm terminal_markdown_viewer

Markdown anzeigen

Das Programm befindet sich nach der Installation in /usr/bin/mdv und steht daher mit dem Paket pyhton-markdown im Konflikt.

Mit Scrolling

Man kann den Output von mdv nach less pipen, aber dann werden in der Standardeinstellung die Escape Colorsequenzen nicht angewendet und man hat nur Zeichensalat. Damit less nun diese interpretiert, muss der Parameter -r angegeben werden. Daraus ergibt sich nun folgender Aufruf von mdv:

mdv readme.md | less -r

Eine Vereinfachung ist, wenn man sich einen simplen Wrapper dafür anlegt. Dieser muss in dem ausführbaren Pfad liegen und vor /usr/bin eingebunden sein.

#!/bin/bash
mdv $0 | less -r

Midnight Commander

Mit F3 kann man im MC Dateien anschauen. Die Dateierweiterungen lassen sich konfigurieren, sodass man für die Endung .md für Markdown Dateien einen neuen externen Viewer definieren kann.

Hier kommt nun wieder less -R ins Spiel. Definiert man folgenden Regulären Ausdruck in der Datei ~/.config/mc/mc.ext welche sich über Befehl -> Erweiterungsdatei bearbeiten editieren lässt:

# Markdown
regex/i/\.md?$
    View=/usr/bin/mdv %f | less -R

dann kann man mit F3 auf die Markdown Datei die sich im Hintergrund bei MC anzeigen lassen.

Speicherung der Credentials für GIT auf der Komandozeile

Oft ist es so, dass man auf einem Server (wo man nur die Kommandozeile zur Verfügung hat) sehr mühselig jedes Mal beim Pushen oder Pullen die Credentials einzugeben. GIT kann diese dauerhaft speichern, was den Komfort deutlich erhöhen kann. Ob dieses zu einem Sicherheitsrisiko führt, ist hier nicht Thema und wird nicht weiter betrachtet.

File Storage einrichten

git config --global credential.helper 'store --file ~/.my-credentials'

Ein privates Repository von GitHub per PAT clonen

Möchte man ein privates Repository von GitHub auschecken, so kann man Zugriff auf das Repository über ein PAT (Personal Access Token) erhalten.

Dazu muss folgendes Schema angewendet werden:

git clone https://xxxxzzzzxxxxzzzzxxxxzzzzxxxxzzzzxxxxzz:@github.com/MaxMeier/Projekt.git

Wichtig ist der :, da dieser ein leeres Passwort signalisiert, welches bei einem PAT nicht benötigt wird.

Liferay Plugins Sharepoint und SAML2

Die Plugins Sharepoint REST und das Plugin für die ADFS Anbindung SAML2 benötigten ein spezielle Behandlung, da sie sonst einen Neustart des Osgi Runtime Containers benötigen. Diese ist bei der containercreation im Kubernetes Lifecylcle natürlich nicht möglich.

Deployen

Auto Deploy

Zunächst habe ich die Plugins in ein Verzeichnis in dem Liferay Docker Container kopiert, der von Liferay überwacht wird und bei darf per hot deploy Bundles startet. In den Logs konnte man während des Startvorgangs auch erkennen das sie verarbeitet werden. So weit, so gut. Aber in den Logs tauchten Einträge auf, dass das Plugin für die Fertigstellung der Installation einen Neustart des Osgi Containers benötigt. Das ist eigentlich nicht die Philisofie von Osgi.

Marketplace Verzeichnis

Neben dem bereit gennanten Verzeichnis gibt es ein weiteres Verzeichnis, welches Bundles verarbeitet. Es ist das Verzeichis marketplace. Dieses wird beim Starten von Liferay gesondert behandlet, so dass kein Neustart von Liferay nötig ist.

Rückwärtssuche

Wie viele Wissen, kann man mit STRG + r Suchbegriff in der Historie der Shell danach Suchen. Durch erneutes drücken von STRG + r springt zum vorherigen usw.

Vorwärtssuche

Damit man die Suchrichtung ändern kann, muss man STRG + s verwenden. Falls es nicht funktioniert, dann muss die Suspension der Shell mit

stty -ixon

abgeschaltet werden. Nun kann man mit STRG + r rückwärts und mit STRG + s vorwärts suchen in der Historie.

JSON Inhalte semantisch vergleichen

Wenn man mal in die Situation kommt JSON Dateien zu vergleichen, dann kann es sein, dass dieses JSON unterschiedlich strukturiert sind. Dabei versagen naturgemäß normale Diff Programme wie zum Beispiel Meld oder ähnliche.

Hier kommt jsondiff.com zur hilfe. Es wird hierbei ein semantischer Vergleich vorgenommen und somit lassen sich auch anders strukturierte JSON Dokumente einfach miteinander vergleichen.

Parallel Download

Wer bereits einen lokalen Maven Proxy im Einsatzt hat (siehe Nexus OSS Proxy), der kann Maven beschleunigen. Wenn zum Beispiel das .m2/repository Verzeichnis geleert wurde, dann kann man mit dem Parameter -Dmaven.artifact.threads=30 den Vorgang bei Artefakten aus unterschiedlichen Gruppen IDs verbessern.

Alternativ kann man auch die Umgebungsvariable MAVEN_OPTS setzen:

export MAVEN_OPTS=-Dmaven.artifact.threads=3

Ein echter paralleler Download ist das noch nicht. Es besteht aber ein Ticket in https://issues.apache.org/jira/browse/MRESOLVER-7, aber gelöst ist das Problem aktuell noch nicht.

Drone

Drone im Zusammenspiel mit Gitea kann als CI/CD Pipeline eingesetzt werden. Dank zahlreicher Plugins, lässt sich so auch ein Continuous Delivery Pipeline für das Deployment aufbauen. Hier in diesem Beispiel soll es aber vielmehr um die Installation und Konfiguration gehen. Es wird ein Java Programm, das mit Gradle als Buildtool übersetzt wird, einen Status in Gitea als sogenanntes Badge anzeigen. Dazu wird nach jedem Commit ein Docker Image als Grundlage verwendet, um das Programm mit Gradle zu bauen und testen.

Vorbereitung

Zunächst habe ich einen DNS Eintrag drone.XXXX.org erstellt, damit der Dienst hinter dem Reverse Proxy (NginX) aus dem Netz erreichbar ist.

1. eine OAuth2 Application erstellen

Damit OAuth2 mit Drone und Gitea funktuiniert, muss man in Gitea eine „Anwendung“ anlegen. Dieser Anwendung wird später die Erlaubnis gegeben, Gitea als Basis für die Git Repositories zu dienen. In den Einstellungen unter Settings –> Applications –> Manage OAuth2 Applications wird nun eine neue Anwendung erstellt.

Der Anwendung geben wir den Namen drone, damit eine Zuordnung später möglich ist. Die redirect URL setzt sich aus der Domain plus dem Path /login zusammen.

Feld Wert
Name drone
Redirect URL https://drone.XXXX.org/login

Mit einem Klick auf create application wird nun die Anwendung in Gitea angelegt.

Notieren Sie sofort die angezeigten Werte, da das Secret später nicht mehr angezeigt wird und bei Verlust ein neues Secret erstellt werden muss. Hier beispielhafte Werte die dann angezeigt werden:

Var Value
ClientID 3fdd3921-22f4-49ab-bcb1-2b15854e936f
Client Secret 6neDCDDVXya5eVCb4JJhNZGGGdG-nSoA3f8QKYyjamk=

Beenden Sie nun die Eingabe mit einem Klick auf den Button Save, um die Anwendung endgültig anzulegen.

2. Secret für die Kommunikation zwischen Drone und und dem Runner erstellen

Damit sich der Docker Runner mit Drone unterhält, muss ein zuvor generiertes Secret ausgetauscht werden. Mit openssl lässt sich ein Secret sehr einfach auf der Kommandozeile generieren. Der Aufruf von

openssl rand -hex 16

spuckt etwas wie

c014d553037b2ab672374684bed79fa0

aus. Dieses Secret muss dem Docker Container als RPC_SECRET übergeben werden (siehe unten).

3. Drone Container starten

Als Vorbereitung laden wir den Container mit docker pull runter.

docker pull drone/drone:1

Konfiguration

Der Docker Container benötigt einige Angaben, damit Drone mit dem Gitea zusammenarbeitet. Es werden die ClientID, ClientSecret und das Secret für den Docker Runner benötigt. Die Adresse des Gitea Server, sowie die Server Host Adresse und das Protokoll müssen angegeben werden. Alle weiteren Parameter sind Standard und bedürfen hier keiner weiteren Erklärung.

Die gesamte Konfiguration sieht dann wie folgt aus:

docker run \
  --volume=/var/lib/drone:/data \
  --env=DRONE_AGENTS_ENABLED=true \
  --env=DRONE_GITEA_SERVER=https://git.XXXX.org \
  --env=DRONE_GITEA_CLIENT_ID=3e2f5dd2-2704-11ea-9f11-00248cbd6e48 \
  --env=DRONE_GITEA_CLIENT_SECRET=6neDCDDVXya5eVCb4JJhNZGGGdG-nSoA3f8QKYyjamk= \
  --env=DRONE_RPC_SECRET=c014d553037b2ab672374684bed79fa0 \
  --env=DRONE_SERVER_HOST=drone.XXXX.org \
  --env=DRONE_SERVER_PROTO=https \
  --publish=80:80 \
  --restart=always \
  --detach=true \
  --name=drone \
  drone/drone:1

Achtung: Auch wenn über Port 80 nur HTTP geht, so muss als Protokoll HTTPS angegeben werden, da sonst die Redirect URI nicht korrekt ist und OAuth2 Login nicht funktioniert und eine Fehlermeldung innerhalb von Gitea angezeigt wird.

Grant Access

Durch Aufruf der Seite https://drone.XXXX.org wird man per Redirect auf den Gitea Server weitergeleitet. Hier muss man jetzt noch der Anwendung „drone“ den Zugriff gewähren. Danach wird man auf die Drone Seite weitergeleitet, wo jetzt alle Repositories des Gitea Servers gelistet sein sollten.

4. Docker Runner

Drone benötigt, wie bei GitLab auch, Runner. Es gibt verschiedene Runner, die man nutzen kann, um ein Build durchzuführen. Wie unter https://docker-runner.docs.drone.io/installation/install_linux/ beschrieben, installieren wir nun noch einen Runner auf Docker Basis. Zunächst pullen wir den Runner mit

docker pull drone/drone-runner-docker:1

Den Runner konfigurieren

Der Runner benötigt nicht ganz so viele Parameter wie der Drone Container. Einige werden jedoch dennoch benötigt. Es muss der Host und das Protokoll für den Drone Server angegeben werden. Zusätzlich muss das vorher generierte Secret übergeben werden, so dass sich folgender Aufruf ergibt:

docker run -d \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e DRONE_RPC_PROTO=https \
  -e DRONE_RPC_HOST=drone.XXXX.org \
  -e DRONE_RPC_SECRET=e16578d8ae6306175e49df94ad2c75e4 \
  -e DRONE_RUNNER_CAPACITY=2 \
  -e DRONE_RUNNER_NAME=${HOSTNAME} \
  -p 3000:3000 \
  --restart always \
  --name runner \
  drone/drone-runner-docker:1

Nach dem erfolgreichen Start pollt der Runner den Server https://drone.XXXX.org, welches mit docker logs runner sichtbar wird.

[test@manjaro-server ~]$ docker logs runner
time="2019-12-19T11:06:44Z" level=info msg="starting the server" addr=":3000"
time="2019-12-19T11:06:45Z" level=info msg="successfully pinged the remote server"
time="2019-12-19T11:06:45Z" level=info msg="polling the remote server" arch=amd64 capacity=2 endpoint="https://drone.XXXX.org" kind=pipeline os=linux type=docker

Nun steht der Runner bereit und wartet auf Aufträge die er abarbeiten kann.

Die Projektkonfiguration

Repository aktivieren

In den Settings des Repository muss dieses aktiviert werden, damit Drone auf Events reagieren kann.

Ein Drone YAML Skript erstellen

Drone ließt die Datei .drone.yml im Rootverzeichnis des Repositories aus und handelt nach den dort hinterlegten Anweisungen.

Hier ein sehr einfaches Skript, welches bei jeden Commit einen Test mit Gradle durchführt. Das Skript verwendet ein Archlinux als Basis und installiert Java nach, damit der Gradle Wrapper in dem Repository

kind: pipeline
name: default

steps:
- name: setup
  image: archlinux/base:latest
  commands:
    - echo 'Server = http://cache.XXXX.org:8080/$repo/os/$arch/' > /etc/pacman.d/mirrorlist
    - pacman -Sy --noprogressbar --noconfirm jdk11-openjdk
    - JAVA_HOME=/usr/lib/jvm/java-11-openjdk/ ./gradlew clean build test

Wichtig: –noprogressbar muss angegeben werden, da sonst der Drone Runner sofort das Skript mit SUCCESS beendet. Dieses scheint ein Fehler von Drone zu sein.

Für eine schnellere Verarbeitung der Kommandos habe ich einen lokalen Cache für Pacman eingerichtet. Der Cache ist unter der Domäne cache.XXXX.org auf dem Port zu erreichen. Das Docker Image ist bereits lokal von Docker gecacht und daher ist nun eine Installation der Java und Gradle Pakete innerhalb kurzer Zeit erledigt.

Nun wird Drone beim jedem Commit in das Repository einen eigenständigen Build anstoßen und das Badge entsprechend in Gitea aktualisieren.

Plugins

Für Drone.io gibt es jede Menge Plugins unter https://plugins.drone.io/

Alternativen

Es gibt bereits einen Fork von Drone, der im Wesentlichen eine Erweiterung für Windows Programme mit Cygwin darstellt. Der Fork tea-ci ist unter https://docs.tea-ci.org/usage/overview/ zu finden.

Den JOOQ Parser verwenden

Hier ein praktisches Beispiel wie man den Parser von JOOQ verwenden kann. Gegeben sei ein String der einen Select enthält.

select name from books

Dieser soll aber mit Hilfe vom der JOOQ DSL um ein LIMIT und ein OFFSET von jeweils 10 erweitert werden.

Zunächst muss der Parser den String in DSL Objekt parsen, welches dann mit der DSL entsprechend modifiziert werden kann.

dsl.selectFrom(dsl.parser().parse("select name from books"))
  .limit(10)
  .offset(10)
  .fetch();

Hinweis: Ein kleiner Nachteil ist, dass der Parser den SQL String verstehen muss. Zur Zeit werden noch nicht alle Feinheiten der diversen Dialekte unterstützt.

Weitere Einsatzmöglichkeiten

Da der Parser viele Dialekte versteht, kann man das SQL mit JOOQ transpellieren, dass heißt von den einem Dialekt in einen anderen transformieren.

Wireguard Netzwerk

Die prinzipielle Einrichtung von Wireguard habe ich in dem Artikel Wireguard beschrieben. Es ging um die die Point to Point Einrichtung mehrerer Clients die auf einen PC, der als Server fungiert, zugreifen. Die Clients konnten sich untereinander nicht sehen.

Im folgenden möchte ich beschreiben, wie man ein VPN Netz aufbaut in dem sich die Clients untereinander verbinden können. Damit Clients in dem privaten Netzwerk sich über Hostname ansprechen können, wird ein zentraler DNS Server eingerichtet. Hierfür verwende ich einen vorhandenen OpenWRT Router.

Aufbau des Netzwerkes

Das Netzwerk ist auf mehrere Standorte verteilt. Es gibt einen zentralen Linux PC der die Rolle des Wireguard Servers einnimmt. Die Rolle einnimmt, weil es per se keinen Wireguard Server gibt. Es ist die Konfiguration die ihn zur Zentrale werden lässt. Damit dieser erreichbar ist, ist ein DynDNS Dienst oder eine feste IP Adresse von Nöten. Dieses ist aber nicht Bestandteil dieses Artikels. Hier verwaise ich zum Beipsiel auf den Artikel DynDNS mit Duck DNS.

Der Server bekommt in dem VPN die Adresse 10.0.0.1. Der Server ist für das Routing unter den Clients verantwortlich. Das heißt er leitet eingehende Pakete an die anderen Clients weiter. Hierfür muss das IP Forwarding aktiviert und einfache Regeln für die FORWARD Chain von IPTABLES angelegt werden.

Die Clients stellen eine Reihe von Laptops, Workstations und weiteren Servern da. Die Client erhalten durchnummerierte IP Adressen beginnend mit 10.0.0.2/32. In meinem Setup sind es aktuell 6 weitere PCs die in dem VPN vorhanden sind.

Konfiguration von Wireguard

Im Folgenden werde ich das Schema wie Clients und der Server einzurichten sind erläutern. Wenn das Schema bekannt ist, dann ist es leicht weitere Clients hinzuzufügen.

Einrichtung auf dem Server

Das Schema ist eigentlich recht einfach. Es muss allerdings auf die Subnetzmaske bei der Angabe der IP Adressen genau geachtet werden. Die Server Adresse ist mit /24 und die Clients mit /32 anzugeben.

[Interface]
PrivateKey = PrivateKeyDesServers
ListenPort = 32768
Address = 10.0.0.1/24

# Allow routing between clients
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT

#
# Client 1
#
[Peer]
PublicKey = PublicKeyDesClient
AllowedIPs = 10.0.0.2/32

#
# Client 2
#
[Peer]
PublicKey = PublicKeyDesClient
AllowedIPs = 10.0.0.3/32

#
# Client 3
#
[Peer]
PublicKey = PublicKeyDesClient
AllowedIPs = 10.0.0.4/32

.
.
.

#
# Client 7
#
[Peer]
PublicKey = PublicKeyDesClient
AllowedIPs = 10.0.0.7/32

Einrichtung der Clients

Es ist hierbei wichtig zu wissen, dass nur ein Client das gesamte Subnetz beanspruchen darf! Sonst funktioniert das ganze nicht. Das heißt auf den Clients sind explizit die Adresse einzutragen mit denen der Client kommunizieren darf. Dieses macht aber nur bei kleineren Netzen einen Sinn.

[Interface]
PrivateKey = PrivateKeyDesClients
Address = 10.0.0.3/24
DNS = 10.0.0.7

[Peer]
PublicKey = PublicKeyDesServers
AllowedIPs = 10.0.0.1/32, 10.0.0.2/32, 10.0.0.5/32, 10.0.0.6/32, 10.0.0.7/32
EndPoint = myname.dyndns.org:32222
PersistentKeepalive = 25

Wichtig ist das alle Clients mit 10.0.0.X/32 angegeben werden.

IP Forwarding Aktivierung

Das allgemeine IP Forwarding bzw. auf Geräteebene aktivieren habe ich bereits in dem Wireguard Artikel beschreiben.

Firewall Regeln

Damit die Pakete nun auch an die Client weitergeleitet werden, muss in der FORWARD Chain das In-/Output auf dem Wireguard Interface zulassen. Dieses kann mit dem PostUp in der Konfiguration automatisch nach dem Starten der Verbindung durchgeführt werden.

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT

Verbindungsaufbau

Für den automatischen Verbindungsaufbau muss die Option PersistentKeepalive gesetzt werden, damit ein Paket Verbindung öffnet.

Einrichtung von DNS

Auf dem Client habe ich die Konfiguration mit dem KDE NetworkManager durchgeführt. Bei der Wireguard Konfiguration habe ich nun die Adresse des DNS Servers eingetragen, der für das interne Netzt zuständig ist. Die Konfiguration der statische Hostnames beschriebt ein andere Artikel.

Testen der Namesauflösung

Auf http://openwrt/cgi-bin/luci/admin/network/dhcp unter Local Server mit /XXXX.duckdns.org/ Anfrage an die Domain nach außen unterbinden, da diese sonst von DuckDNS beantwortet werden würden und somit die IPV6 Adresse genommen wird, was zu Fehlern führt.