Archiv des Autors: Jörg Kastning

Updates auf ein spezifisches RHEL-Minor-Release beschränken

Wenn man einen Anwendungs-Dienst betreibt, welcher nur für ein bestimmtes Release von Red Hat Enterprise Linux wie bspw. RHEL 8.4 freigegeben ist, gilt es effektiv zu verhindern, dass bei Updates Pakete installiert werden, die zu einem folgenden Release wie z.B. RHEL 8.5 gehören. Andernfalls verliert man bestenfalls die Unterstützung vonseiten des Herstellers der Anwendung. Im schlimmsten Fall ist die Anwendung nicht mehr lauffähig und man muss das Upade zurückrollen.

Hinweis von Steffen Frömer (Senior Technical Account Manager bei Red Hat): Um Updates für ein spezifisches Minorrelease zu bekommen, auch wenn wie im Beispiel RHEL 8.5 bereits verfügbar ist, müssen Repositories mit verlängertem Support (z.B. Extended Update Support, EUS) verwendet werden. Andernfalls bekommt man keine Paketupdates.

Weiterführende Informationen zum Thema Extended Update Support bietet der Link unter [3].

Der folgende Code-Block zeigt, wie man Updates für ein RHEL-8-System auf das Release 8.4 beschränkt:

# subscription-manager release --set=8.4
# rm -rf /var/cache/dnf

Das Kommando in der letzten Zeile, geht auf den Wissensartikel [1] zurück, welcher darauf hinweist, dass nur so der Paket-Cache sicher geleert wird. Dies ist notwendig, da der Paketmanager andernfalls fälschlicherweise Paketversionen eines höheren Release aus dem lokalen Cache installieren könnte, was zu Abhängigkeitsproblemen führt.

Mit folgendem Befehl lässt sich die Beschränkung wieder entfernen:

# subscription-manager release --unset
   Release preference has been unset

Das war auch schon alles.

  1. How to tie a system to a specific update of Red Hat Enterprise Linux? — https://access.redhat.com/solutions/238533 (Login erforderlich)
  2. How to limit updates a [sic] specific version of Red Hat Enterprise Linux? — https://access.redhat.com/solutions/2761031 (Login erforderlich)
  3. Red Hat Enterprise Linux (RHEL) Extended Update Support (EUS) Overview — https://access.redhat.com/articles/rhel-eus (Login erforderlich)

Meine Antwort auf die Frage: „Verliert die Free-Software-Community ihre Werte?“

Dieser Blogpost enthält meine Antwort auf den Meinungsartikel von Niklas auf GNU/Linux.ch: „Verliert die Free-Software-Community ihre Werte?“

Niklas weist in seinem Artikel auf den Umstand hin, dass zur Bereitstellung von, Verteilung von, Beteiligung an und Diskussion um Freie-Software-Projekte vermehrt Werkzeuge genutzt werden, welche einer proprietären Lizenz unterliegen. Er kritisiert, dass dies die Freiheit Nr. 3 einschränkt:

Freiheit 3: Die Freiheit, das Programm zu verbessern und diese Verbesserungen der Öffentlichkeit freizugeben, damit die gesamte Gemeinschaft davon profitiert.

https://gnulinux.ch/verliert-die-free-software-community-ihre-werte

Aus Niklas‘ Sicht werden durch die Verwendung proprietärer Werkzeuge/Plattformen wie z.B. GitHub und Discord Nutzer davon abgehalten bzw. daran gehindert, sich an der Entwicklung freier Software zu beteiligen. Niklas schließt seinen Artikel mit folgenden Fragen, die ich in diesem Beitrag gern beantworten möchte.

… Habt ihr selbst Projekte? Werdet ihr etwas verändern? Beteiligt ihr euch an Projekten? Werdet ihr eure Bedenken weitergeben? War der Artikel hilfreich?…

https://gnulinux.ch/verliert-die-free-software-community-ihre-werte

Ja, ich habe einige Projekte. Einige habe ich auf GitHub veröffentlicht. Andere werden in der GitLab-Instanz der Universität Bielefeld gepflegt. Damit verwende auch ich ein proprietäres Werkzeug für meine eigenen Projekte.

Darüber hinaus nutze ich GitHub auch, um mich an diversen anderen Projekten zu beteiligen. Und es gefällt mir, weil es mir die (Mit-)Arbeit und Beteiligung so einfach macht. Hier sind viele Projekte, die mich interessieren. Hier suchen viele Nutzer nach interessanten Projekten. Mit dieser Plattform erreiche ich mit meinen Projekten viele potenzielle Nutzer. Ich finde es praktisch, den Issue-Tracker und die Verwaltung der Pull Requests dabei zu haben. Und nicht zuletzt ist das Hosting meiner Projekte hier kostenfrei.

Dass es sich bei GitHub nicht um Freie Software handelt, hat mich bisher nicht gestört. Ich habe allerdings auch noch nicht bewusst darüber nachgedacht.

Da ich IRC nicht mag, es mich eher stört, wenn jedes Projekt sein eigenes Forum betreibt, für das ich mich erst registrieren muss, finde ich es praktisch, dass ich mich mit einem GitHub-Account an so vielen Projekten beteiligen und mich über den Issue-Tracker mit ihnen austauschen kann. Daneben schätze ich noch, wenn die Möglichkeit besteht, mit einem Projekt via E-Mail in Kontakt zu treten, da dies für mich persönlich die geringste Hürde darstellt.

Allerdings kann ich Niklas auch gut folgen. Vermutlich würde ich mich nicht bei Discord registrieren, um mich an einem Projekt beteiligen zu können. Dass ich mit einigen Projekten ausschließlich über Google-Groups kommunizieren kann, finde ich ebenfalls doof, ist hierfür doch ein Google-Konto Voraussetzung.

Ich besitze auch noch einige Zugänge zum Bugzilla von Red Hat (https://bugzilla.redhat.com) und bin dort hin und wieder aktiv. Bugzilla steht unter einer Open-Source-Lizenz. Der Bugtracker wird in diesem Fall von einem profitorientierten Unternehmen betrieben (Red Hat). Macht es das schon besser als GitHub, eine proprietäre Anwendung in den Händen eines profitorientierten Unternehmens (Microsoft)? Ich weiß es nicht.

In beiden Fällen (Red Hat Bugzilla und GitHub) finde ich persönlich meine Freiheit Nr. 3 nicht beschränkt. Im Gegenteil. Empfinde ich es doch als Erleichterung, mich an Projekten beteiligen zu können.

Niklas hat in seinem Artikel Codeberg erwähnt, welches ich bisher noch nicht kannte. Es handelt sich dabei um eine Kollaborationsplattform Git-Hosting für Freie- und Open-Source-Software. Auf den ersten Blick bietet das Projekt Codeverwaltung, Issue-Tracker und Pull-Request-Verwaltung. Alles unter einer freien Lizenz. Betrieben wird die Plattform vom gemeinnützigen Verein Codeberg e.V., dessen Satzung hier eingesehen werden kann. Die Idee und Motivation des Vereins gefällt mir und ich halte diese für unterstützenswert.

Codeberg bietet scheinbar die Funktionalität, welche ich für meine Projekte benötige. Werde ich jetzt etwas verändern? Nun, ich kann mir gut vorstellen, mein nächstes Projekt auf Codeberg zu hosten. Erst wenn ich die Plattform einige Zeit selbst genutzt habe, kann ich mir ein Urteil darüber bilden.

An Niklas gerichtet: Ja, ich finde deinen Artikel hilfreich. Er regt zum Nachdenken an und ich habe dadurch eine Plattform kennengelernt, die ich bisher noch nicht kannte und welche auf den ersten Blick einen guten Eindruck macht.

Nun habe ich noch eine Frage an meine Leser hier. Wenn ein Projekt seinen Code nicht auf GitHub hostet, stellt dies für euch eine Hürde dar, die Software zu verwenden oder euch am Projekt zu beteiligen? Oder senkt dies eure Hemmschwelle sogar?

VMware ESXi: VMDK-Datei einer Gast-VM mit virt-sysprep bereinigen

Soll eine virtuelle Maschine (VM) als Vorlage (engl. template) für weitere VMs dienen, so ist es in der Regel ausreichend, eine VM mit dem gewünschten Betriebssystem zu installieren und zukünftig als Vorlage zu verwenden. Anschließend kann diese VM über die Werkzeuge im ESXi-Host- bzw. vSphere-Client geklont werden. Die dabei erzeugte VM kann während dieses Vorgangs mithilfe einer Gast-Anpassungsspezifikation angepasst werden, um z.B. einen neuen Hostnamen oder eine abweichende IP-Adresse zu vergeben.

Klont man nach dem beschriebenen Verfahren eine Linux-VM, enthält diese noch die Historie des Originals. So werden z.B. bash-history, crontabs, ssh-hostkeys, ssh-userdirs, etc. vom Original übernommen und bestehen in der neuen VM fort. Um dies zu verhindern, sind diese Informationen zuvor aus der VM, welche als Vorlage dient, zu entfernen. Dazu kann man sich eigener Skripte bedienen oder auf das Programm virt-sysprep zurückgreifen, welches genau für diese Aufgabe geschaffen wurde.

Im Folgenden dokumentiere exemplarisch, wie man mit virt-sysprep eine VMDK-Datei bearbeiten kann, die im Datenspeicher eines ESXi-Hosts abgelegt ist.

Warnung: Folgende Schritte werden von VMware nicht unterstützt. Es besteht die Gefahr des Datenverlusts durch beschädigte VMDK-Dateien. Wer diesem Tutorial folgt, tut dies auf eigene Gefahr. Zuvor sollte geprüft werden, ob ein aktuelles Backup existiert, welches bei Bedarf wiederhergestellt werden kann.

Umgebung

Für dieses Tutorial wird ein Linux-Arbeitsplatz verwendet, auf dem die Pakete libguestfs-tools und sshfs zu installieren sind.

Die zu bearbeitende VMDK-Datei heißt in diesem Beispiel vmname-flat.vmdk und liegt im Datenspeicher eines ESXi-Hosts.

Vom Linux-Arbeitsplatz aus kann via SSH auf den Root-Account des ESXi-Hosts zugegriffen werden.

Ein virt-sysprep-wrapper-Skript

Ich möchte auf meine VMDK-Dateien die Standard-Operationen von virt-sysprep, mit Ausnahme der Operation ssh-userdir anwenden (siehe OPERATIONS in virt-sysprep(1)). Dazu habe ich ein kurzes Wrapper-Skript erstellt, welches eine notwendige Umgebungsvariable setzt, den Pfad zur zu bearbeitenden VMDK-Datei als Argument übergeben bekommt und die gewünschten Operationen darauf ausführt. Das Skript ist im Folgenden dargestellt. Die eigentliche Aktion passiert in den letzten beiden Zeilen.

#!/bin/bash
# Author: Joerg Kastning
# Description:
# Sysprep RHEL vSphere templates using `virt-sysprep` from `libguestfs-tools`.

usage()
{
  cat << EOF
  usage: $0 OPTIONS $1

  This script use virt-sysprep to reset, unconfigure or customize a virtual machine so clones can be made (virt-sysprep(1)).

  The path to the file VMNAME-flat.vmdk has to be provided as $1.

  OPTIONS:
  -h Shows this help message.
EOF
}

export LIBGUESTFS_BACKEND=direct
virt-sysprep --operations defaults,-ssh-userdir -a $1

Das Skript liegt im Verzeichnis bin, im HOME-Verzeichnis meines Benutzers. Damit befindet sich das Skript im PATH und kann ohne den vollqualifizierten Pfad aufgerufen werden.

Der Ablauf

Wichtig: Die VM, deren VMDK-Datei bearbeitet werden soll, MUSS ausgeschaltet sein.

Zuerst müssen die Pakete libguestfs-tools und sshfs auf dem Linux-Arbeitsplatz installiert werden:

sudo [apt|yum|dnf] install libguestfs-tools sshfs

Alle weiteren Schritte werden auf dem Linux-Arbeitsplatz ausgeführt:

$ mkdir vmfs
$ sshfs root@esxi-host.beispiel.de:/vmfs vmfs
$ cd vmfs/pfad/zum/verzeichnis/der/VM/
$ virt-sysprep-wrapper.sh vmname-flat.vmdk
[   0,0] Examining the guest ...
[  15,1] Performing "abrt-data" ...
[  15,3] Performing "backup-files" ...
[  24,4] Performing "bash-history" ...
[  24,5] Performing "blkid-tab" ...
[  24,7] Performing "crash-data" ...
[  24,7] Performing "cron-spool" ...
[  24,8] Performing "dhcp-client-state" ...
[  25,0] Performing "dhcp-server-state" ...
[  25,0] Performing "dovecot-data" ...
[  25,0] Performing "logfiles" ...
[  28,2] Performing "machine-id" ...
[  28,3] Performing "mail-spool" ...
[  28,3] Performing "net-hostname" ...
[  28,6] Performing "net-hwaddr" ...
[  28,8] Performing "pacct-log" ...
[  28,9] Performing "package-manager-cache" ...
[  30,5] Performing "pam-data" ...
[  30,5] Performing "passwd-backups" ...
[  30,6] Performing "puppet-data-log" ...
[  30,7] Performing "rh-subscription-manager" ...
[  30,8] Performing "rhn-systemid" ...
[  30,9] Performing "rpm-db" ...
[  31,0] Performing "samba-db-log" ...
[  31,1] Performing "script" ...
[  31,1] Performing "smolt-uuid" ...
[  31,1] Performing "ssh-hostkeys" ...
[  31,2] Performing "sssd-db-log" ...
[  31,3] Performing "tmp-files" ...
[  31,8] Performing "udev-persistent-net" ...
[  31,9] Performing "utmp" ...
[  31,9] Performing "yum-uuid" ...
[  32,0] Performing "customize" ...
[  32,2] Setting a random seed
[  32,3] Setting the machine ID in /etc/machine-id
[  32,9] Performing "lvm-uuids" ...
$ cd
$ fusermount -u vmfs

Damit ist die VM von ihrer Geschichte befreit und kann nun als bereinigte Vorlage für weitere VMs dienen.

Quellen und weiterführende Links

GnuPG: Web Key Directory (WKD) für My-IT-Brain

Ein Web Key Directory (WKD) stellt einen einfachen Weg bereit, um öffentliche GnuPG-Schlüssel für E-Mail-Adressen über eine HTTPS-Verbindung abzurufen. Es ist dazu gedacht, die Benutzererfahrung zur Nutzung verschlüsselter E-Mail-Kommunikation zu vereinfachen.

Ich bin dem ausführlichen Artikel „GnuPG: Web Key Directory (WKD) einrichten“ von Mike Kuketz gefolgt und habe ein WKD für E-Mail-Adressen unter meiner Domain „my-it-brain.de“ konfiguriert. Denn ich teile seine Auffassung:

WKD ist nach meiner Auffassung eine benutzerfreundliche Alternative für den Austausch von Schlüsseln, da Clients wie Thunderbird/Enigmail diesen Standard bereits verwenden, um beim Verfassen einer E-Mail automatisch den öffentlichen Schlüssel eines Benutzers abzurufen. Insgesamt wird der Schlüsseltausch mit WKD stark vereinfacht – das steigert insgesamt die Nutzerfreundlichkeit der E-Mail-Verschlüsselung.

https://www.kuketz-blog.de/gnupg-web-key-directory-wkd-einrichten

Probiert es doch selbst einmal aus. Verschlüsselte E-Mail-Kommunikation wird dadurch deutlich vereinfacht.

Quellen und weiterführende Links

Network Bound Disk Encryption im Überblick

In diesem Artikel gebe ich euch einen Überblick, was Network Bound Disk Encryption (NBDE) ist und beschreibe einen konkreten Anwendungsfall. Am Ende des Artikels führe ich einige Verweise auf, mit deren Hilfe ihr NBDE bei Interesse selbst implementieren könnt.

Linux Unified Key Setup (LUKS)

Bevor ich auf NBDE eingehe, möchte ich kurz ein paar Worte zu LUKS verlieren.

Bei LUKS handelt es sich um das Standardverfahren zur Festplattenverschlüsselung unter Linux (siehe 1). Dieses erweitert dm-crypt um einen Header, welcher Slots zum Speichern von bis zu acht Schlüsseln bietet (siehe 2).

Ich benutze dieses Verfahren auf nahezu all meinen Rechnern. Ich möchte damit erreichen, dass meine Daten bei Diebstahl des Rechners bzw. der Festplatte möglichst lange vor unberechtigtem Zugriff geschützt sind.

Typischerweise wird zur Entschlüsselung einer Festplatte bzw. Partition während des Boot-Vorgangs die Eingabe eines Kennworts benötigt. Die Sicherheit des Verfahrens hängt dabei direkt von der Stärke des verwendeten Passworts ab (siehe 1).

Steht der Rechner im Büro und man ist täglich vor Ort, ist es kein Problem, bei Neustart des Rechners das LUKS-Kennwort einzugeben. Wenn man allerdings im Homeoffice arbeitet und Zugriff auf seinen Büro-Rechner braucht, sieht die Sache anders aus.

Möchte man den entfernten Rechner neustarten, z.B. nach der Installation von Updates, muss man dafür extra ins Büro fahren. Alternativ kann man ein zweites Kennwort einrichten, dieses einem Kollegen mitteilen und diesen bitten, es vor Ort einzugeben. Beides ist nicht komfortabel. Und hier kommt NBDE ins Spiel.

LUKS an Netzwerkressource binden

Network Bound Disk Encryption heißt auf Deutsch in etwa netzwerkgebundene Festplattenverschlüsselung und bedeutet, dass die Verschlüsselung an eine oder mehrere Ressourcen im Netzwerk gebunden ist.

Das Prinzip ist ganz einfach. Wenn ein Rechner mit einer verschlüsselten Festplatte oder Partition startet, sucht er nach einer bestimmten Ressource im Netzwerk. Kann der Rechner diese Netzwerkressource erreichen, wird die Festplatte bzw. Partition entschlüsselt und der Startvorgang fortgesetzt. Folgende Abbildung soll dies veranschaulichen.

nbde-network
Clevis-Client und Tang-Server zur Nutzung von NBDE im LAN

Im eigenen LAN werden zwei sogenannte Tang-Server positioniert (siehe 4 und 6). Diese stellen die Netzwerk-Ressource dar, welche erreichbar sein muss, damit ein an Tang gebundenes Gerät entschlüsselt werden kann. In diesem Beispiel werden zwei Tang-Server betrieben, um die Verfügbarkeit des Dienstes zu gewährleisten, wenn ein Server gewartet wird.

Auf dem Client kommt die Anwendung Clevis zum Einsatz (siehe 5, 6 und 7), bei welcher es sich um die Client-Komponente zum Tang-Server handelt. Diese empfängt einen Schlüssel vom Tang-Server und verwendet diesen, um einen Token in einem LUKS-Slot zu speichern (Details siehe 3, 6 und 7). Beim Start eines Rechners wird nun versucht, einen der Tang-Server zu erreichen, an die man sich gebunden hat.

Wird der Rechner bzw. seine Festplatte gestohlen, sind die Tang-Server nicht erreichbar und die Daten werden nicht automatisch entschlüsselt. Der Dieb muss nun die Verschlüsselung bzw. das verwendete Kennwort brechen.

Steht der Rechner jedoch an seinem Platz, kann er aus der Ferne neugestartet werden und den Startvorgang beenden, ohne dass jemand vor Ort ein LUKS-Kennwort eingeben muss.

Damit diese Konfiguration Sinn macht, dürfen die Tang-Server nicht weltweit erreichbar sein. Ihr Standort und die Netze, aus denen sie erreichbar sind, sind daher sorgfältig zu planen.

Zusammenfassung

Ohne NBDE muss an einem Rechner mit LUKS-Verschlüsselung bei jedem Startvorgang das LUKS-Kennwort eingegeben werden, was einen Neustart aus der Ferne enorm erschwert.

NBDE ist leicht zu implementieren und löst dieses Problem. Gleichzeitig bleiben die Daten im gleichen Maße bei einem Diebstahl des Rechners geschützt.

  1. LUKS im Wiki von Ubuntuusers.de. URL: https://wiki.ubuntuusers.de/LUKS/
  2. https://de.wikipedia.org/wiki/Dm-crypt#LUKS
  3. Automatic data encryption and decryption with Clevis and Tang. ADMIN 43/2018. URL: https://www.admin-magazine.com/Archive/2018/43/Automatic-data-encryption-and-decryption-with-Clevis-and-Tang
  4. https://github.com/latchset/tang
  5. https://github.com/latchset/clevis
  6. RHEL 8 Security Hardening Chapter 12. Configuring automated unlocking of encrypted volumes using policy-based decryption. URL: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/configuring-automated-unlocking-of-encrypted-volumes-using-policy-based-decryption_security-hardening
  7. RHEL 7 Security Guide 4.10.1. Network-Bound Disk Encryption. URL: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/sec-policy-based_decryption#sec-Using_Network-Bound_Disk_Encryption
  8. How to set up Network-Bound Disk Encryption with multiple LUKS devices (Clevis+Tang unlocking). URL: https://access.redhat.com/articles/4500491. (Login erforderlich)

Der Umwelt und mir gefällt es am besten, wenn „ihr“ mich „remote“ arbeiten lasst.

Themen wie der Klimawandel, Maßnahmen zum Schutz des Klimas, nachhaltige Lebensweise und der sparsame Umgang mit den Ressourcen unseres Planeten sind die letzten Monate in unseren Medien omnipräsent.

In den letzten Tagen machen Nachrichten über steigende Benzinpreise und Preissteigerungen bei der Bahn Schlagzeilen. In den Kommentarspalten treffen nun wieder die Freunde des Individualverkehrs und die Liebhaber des ÖPNV aufeinander und streiten über Vor- und Nachteile und die sinnvollste Verknüpfung der letzteren.

An dieser Stelle folgt nun keine Rechnung für oder wider das Auto. Sondern ein Appell, das beizubehalten, was in der Pandemie gut funktioniert hat. Das Homeoffice nämlich.

Meine Dienststelle liegt ca. 33 km von meinem Wohnort entfernt. Vor der Pandemie bin ich fünf Tage in der Woche gependelt. Dabei benötige ich mit dem Auto für eine Strecke je nach Verkehrslage 40-50 Minuten.

Möchte ich auf das Auto verzichten, verlängert sich die einfache Fahrzeit auf 96-150 Minuten, je nach Verbindung. Das ist für mich inakzeptabel, denn ich möchte ja auch noch etwas vom Tag und meiner Familie haben. Die Fahrzeit lässt sich auf 69 Minuten reduzieren, wenn ich die ersten 12 km mit dem Auto bis zu einer günstigen Haltestelle fahre. Da fahre ich die restlichen 21 km lieber auch noch selbst und spare mir die Zeit.

Seit die Pandemie über uns kam, arbeite ich von daheim. Die Dienststelle suche ich jetzt eher an 5 Tagen im Quartal auf. Nämlich immer dann, wenn Arbeiten nicht von daheim ausgeführt werden können, keine Remote-Hands verfügbar sind, ich meine Post abholen muss oder ich einfach mal mit einem Kollegen essen gehen möchte.

Damit spare ich mir täglich 1,5 Std. auf der Straße und meinem Auto und der Umwelt ca. 14.000 km im Jahr.

Für mich und viele meines Berufsstandes funktioniert dieses Modell sehr gut. Mir ist bewusst, dass dieses Modell nicht für alle Erwerbstätigen möglich oder wünschenswert ist, doch ist es, denke ich, für ebenso viele ein Segen.

Daher wünsche ich mir, dass die Pandemie schnell enden möge und all jene, denen es so geht wie mir, im Homeoffice bleiben dürfen.

Update 2022-08-26: Mit der Dienstvereinbarung FlexWork hat meine Dienststelle die Möglichkeit geschaffen, bis zu 60 % der geschuldeten Arbeitszeit aus dem Heimbüro zu erbringen. Nach diesem Modell arbeite ich nun schon einige Monate und bin sehr zufrieden damit. Etwas Raum für Verbesserung gibt es noch. Ich würde mir 80 % FlexWork wünschen oder eine Regelung nur noch in die Dienststelle kommen zu müssen, wenn es mir beliebt bzw. Arbeiten nicht remote ausgeführt werden können.

GNU/LinuxDay in Vorarlberg – am 16. Okt. 2021 (nur online)

Am 16. Oktober 2021 findet zum zweiten Mal ein reiner Online-LinuxDay AT statt.

LinuxDay 2021 am 16. Oktober

Noch immer hat uns die Covid-Pandemie im Griff und so findet auch dieser LinuxDay wieder online statt.

Dennoch hat sich die Linux User Group Vorarlberg wieder tüchtig ins Zeug gelegt und ein abwechslungsreiches Programm mit 12 Vorträgen zusammengestellt. Informationen für Besucherinnen und Besucher stellt die LUG unter „Was wie wo – 2021“ bereit.

Ich freue mich, wenn wir uns im virtuellen Raum treffen und einen schönen LinuxDay verbringen. Hoffentlich können wir uns im nächsten Jahr wieder vor Ort treffen und ein schönes Wochenende in Dornbirn verbringen.

Zwei Bash-Skripte zur Analyse der NGINX Access Logs

Beim Durchwühlen des Internets bin ich auf eine Perle gestoßen, die ich hier festhalten möchte. In „Bash Script to Parse and Analyze Nginx Access Logs“ stellt Ruan Bekker ein kurzes Bash-Skript vor, welches die NGINX Access Logs analysiert, um einen Bericht mit folgenden Sektionen auszugeben:

  • Top 10 Request IPs (aus dem aktuellen Access Log)
  • Top Request Methods (aus dem aktuellen Access Log)
  • Top 10 Request Pages (aus dem aktuellen Access Log)
  • Top 10 Request Pages (aus dem aktuellen und Gzipten Logs)
  • Top 10 HTTP 404 Page Responses (aus dem aktuellen und Gzipten Logs)

Ich selbst nutze aktuell den Fork von Marc Brunet, welchen ich meinen My-IT-Scripts hinzugefügt habe:

#!/bin/bash

# URL: https://github.com/Tronde/My-IT-Scripts/blob/master/bash/analyze_nginx_access_logs.sh

# variables
LOGFILE="/var/www/jkastning/sites/logs/www.my-it-brain.de_access.log"
LOGFILE_GZ="/var/www/jkastning/sites/logs/www.my-it-brain.de_access.log.*"
RESPONSE_CODE="200"

# functions
filters(){
grep -w $RESPONSE_CODE \
| grep -v "\/rss\/" \
| grep -v robots.txt \
| grep -v "\.css" \
| grep -v "\.jss*" \
| grep -v "\.png" \
| grep -v "\.ico"
}

filters_404(){
grep -w "404"
}

request_ips(){
awk '{print $1}'
}

request_method(){
awk '{print $6}' \
| cut -d'"' -f2
}

request_pages(){
awk '{print $7}'
}

wordcount(){
sort \
| uniq -c
}

sort_desc(){
sort -rn
}

return_kv(){
awk '{print $1, $2}'
}

request_pages(){
awk '{print $7}'
}

return_top_ten(){
head -10
}

## actions
get_request_ips(){
echo ""
echo "Top 10 Request IP's:"
echo "===================="

cat $LOGFILE \
| filters \
| request_ips \
| wordcount \
| sort_desc \
| return_kv \
| return_top_ten
echo ""
}

get_request_methods(){
echo "Top Request Methods:"
echo "===================="
cat $LOGFILE \
| filters \
| request_method \
| wordcount \
| return_kv
echo ""
}

get_request_pages_404(){
echo "Top 10: 404 Page Responses:"
echo "==========================="
zgrep '-' $LOGFILE $LOGFILE_GZ\
| filters_404 \
| request_pages \
| wordcount \
| sort_desc \
| return_kv \
| return_top_ten
echo ""
}


get_request_pages(){
echo "Top 10 Request Pages:"
echo "====================="
cat $LOGFILE \
| filters \
| request_pages \
| wordcount \
| sort_desc \
| return_kv \
| return_top_ten
echo ""
}

get_request_pages_all(){
echo "Top 10 Request Pages from All Logs:"
echo "==================================="
zgrep '-' --no-filename $LOGFILE $LOGFILE_GZ \
| filters \
| request_pages \
| wordcount \
| sort_desc \
| return_kv \
| return_top_ten
echo ""
}

# executing
get_request_ips
get_request_methods
get_request_pages
get_request_pages_all
get_request_pages_404

Selbstverständlich erhalte ich damit keine genauen Statistiken, da meine Logs nach einem Monat automatisch gelöscht werden. Für einen kurzen Rückblick und der Erstellung eines monatlichen Berichts scheint das kleine Skript jedoch gut geeignet zu sein. Ich probiere es gerade aus, um zu sehen, wie gut es mir auf Dauer gefällt.

Auf Basis des ersten Skripts habe ich ein zweites geschrieben, mit dessen Hilfe ich die Requests für einen spezifischen Beitrag abfragen kann (Quelle):

#!/bin/bash

# variables
LOGFILE="/var/www/jkastning/sites/logs/www.my-it-brain.de_access.log"
LOGFILE_GZ="/var/www/jkastning/sites/logs/www.my-it-brain.de_access.log.*"
RESPONSE_CODE="200"
ARG1=$1

# functions
filters(){
grep -w $RESPONSE_CODE \
| grep -v "\/rss\/" \
| grep -v robots.txt \
| grep -v "\.css" \
| grep -v "\.jss*" \
| grep -v "\.png" \
| grep -v "\.ico"
}

request_ips(){
awk '{print $1}'
}

request_page(){
awk '{print $7}' \
| grep -w $ARG1
}

wordcount(){
sort \
| uniq -c
}

return_kv(){
awk '{print $1, $2}'
}

get_request_page(){
echo "Page requests in current log:"
echo "====================="
cat $LOGFILE \
| filters \
| request_page \
| wordcount \
| return_kv
echo ""
}

get_request_page_all(){
echo "Page requests in all logs (last month):"
echo "==================================="
zgrep '-' --no-filename $LOGFILE $LOGFILE_GZ \
| filters \
| request_page \
| wordcount \
| return_kv
echo ""
}

# execute
get_request_page
get_request_page_all

Der folgende Code-Block zeigt ein Beispiel, wie das Skript angewendet wird. Dabei wird der Permalink als Argument übergeben:

:~/bin$ sh get_page_requests_from_nginx_access_logs.sh kommentar-linux-container-spreu-und-weizen
Page requests in current log:
=====================
262 /wordpress/kommentar-linux-container-spreu-und-weizen/
6 /wordpress/kommentar-linux-container-spreu-und-weizen/feed/

Page requests in all logs (last month):
===================================
5124 /wordpress/kommentar-linux-container-spreu-und-weizen/
49 /wordpress/kommentar-linux-container-spreu-und-weizen/feed/
2 /wordpress/wp-json/oembed/1.0/embed?url=https://www.my-it-brain.de/wordpress/kommentar-linux-container-spreu-und-weizen/

Noch nicht schön, aber zweckmäßig.

Was haltet ihr davon? Falls ihr beim Drübergucken zufällig noch einen Fehler in den Skripten entdeckt, freue ich mich, wenn ihr mir einen Kommentar hinterlasst.

In-Place-Upgrade für Red Hat Enterprise Linux (RHEL)

In diesem Beitrag beschreibe ich exemplarisch, wie ein In-Place-Upgrade von RHEL 7 auf RHEL 8 durchgeführt werden kann. Dabei beschreibe ich zuerst, was ein In-Place-Upgrade ist und in welchen Fällen es sinnvoll sein kann, bevor ich im Hauptteil anhand einer Test-VM die Durchführung demonstriere.

Was ist ein In-Place-Upgrade?

Als In-Place-Upgrade wird der Vorgang bezeichnet, bei dem ein Betriebssystem auf ein neues Major-Release aktualisiert wird, ohne das System dabei neuinstallieren zu müssen. Statt dessen werden alle zum Betriebssystem gehörenden Dateien gegen die entsprechende Version des neuen Release ausgetauscht.

Nutzer von Debian und Ubuntu kennen dieses Verfahren unter dem Begriff Distributions-Upgrade.

In-Place-Upgrade vs. Neuinstallation

Grundsätzlich bevorzuge ich die Neuinstallation eines Systems. Da man sich üblicherweise mit Backups und Deployment-Skripten darauf vorbereitet hat, einen Dienst bzw. eine Anwendung nach einem Verlust des laufenden Systems wiederherstellen zu können, kann man sich dies auch zu Nutze machen und den Dienst bzw. die Anwendung auf einem frisch installierten System wiederherzustellen. Auf diese Weise werden keine Altlasten über mehrere Betriebssystemversionen mitgeschleppt.

Gleichzeitig kann man die Downtime verkürzen, indem das neue System parallel zum alten aufgebaut wird und man nach dem Abschluss aller Arbeiten und Tests umschaltet. Das Altsystem kann im Nachgang in Ruhe abgebaut werden.

Es gibt jedoch auch Gründe, die für ein In-Place-Upgrade sprechen. Verfügt man nur über einen einzigen Host und kann kein Parallelsystem aufbauen, kann ein In-Place-Upgrade die Lösung sein.

Evtl. verfügt man selbst zwar über ausreichend Berechtigungen, um das vorhandene System zu aktualisieren, für die Provisionierung neuer Systeme ist man jedoch auf die Unterstützung weiterer Stellen angewiesen. Die Abhängigkeitskette lässt sich hier zum Teil deutlich reduzieren.

Dabei muss stets bedacht werden, dass bei einem In-Place-Upgrade auch ein katastrophaler Fehler eintreten kann, welcher zum Verlust des Systems führt. Es ist daher dringend angeraten, eine Datensicherung zu haben, aus welcher das System wiederhergestellt werden kann. Besitzt man ein Backup, auf das man sich verlassen kann, kann es auch schon losgehen.

Das Upgrade von RHEL 7 auf RHEL 8

Laut Kapitel 1 der unter [0] verlinkten Dokumentation stellt das In-Place-Upgrade den von Red Hat unterstützten und empfohlenen Weg dar, um auf das nächste Major-Release zu aktualisieren. Dabei kann man stets nur von der letzten Verfügbaren RHEL 7 Version auf das jeweils letzte gerade RHEL 8 Release (z.B. 8.4) aktualisieren. Details hierzu können im Artikel unter [1] nachgelesen werden.

Die folgenden Abschnitte können die Dokumentation unter [0] nicht ersetzen. Sie sollen lediglich einen kompakten Überblick über den Prozess geben.

Limitierungen

Zum Zeitpunkt der Artikelerstellung , kann das In-Place-Upgrade nicht auf Systemen mit verschlüsselten Dateisystemen durchgeführt werden.

Netzwerkspeicher, wie z.B. iSCSI oder NAS, werden nicht unterstützt und müssen während des Upgrades ausgehängt werden. Die dazugehörigen Dienste, wie z.B. autofs müssen vorübergehend deaktiviert werden.

Weitere bekannte Probleme sind Kapitel 8 in [0] zu entnehmen.

Vorbereitung

Bevor man mit dem Upgrade beginnen kann, sind folgende Voraussetzungen zu schaffen:

  • Das System erfüllt die minimalen Systemvoraussetzungen für RHEL 8 (siehe [2]).
  • Zugriff auf Repos mit aktuellen Paketen für RHEL 7.9 und RHEL 8.4.
  • Korrekte Registrierung des Systems am Red Hat Content Delivery Network (CDN) oder den Red Hat Satellite Server mittels Red Hat Subscription Manager (RHSM).

Wichtig: Ich empfehle ausdrücklich, vor Beginn der Arbeiten ein aktuelles Backup bzw. einen Snapshot zu erstellen, um auf den Ausgangszustand vor der Upgrade-Prozedur zurückkehren zu können.

Kapitel 2 in [0] bietet eine ausführliche Schritt-für-Schritt-Anleitung zur Vorbereitung des Upgrades. Der folgende Codeblock bietet eine kompakte Übersicht der einzelnen Schritte. Als Zielsystem dient eine aktuelle RHEL 7.9 Minimal-Installation.

[tronde@rhel7-t1 ~]$ # Überprüfung, ob eine RHEL-Subskription abonniert wurde
[tronde@rhel7-t1 ~]$ sudo subscription-manager list --installed
[sudo] password for tronde: 
+-------------------------------------------+
    Installed Product Status
+-------------------------------------------+
Product Name:   Red Hat Enterprise Linux Server
Product ID:     69
Version:        7.9
Arch:           x86_64
Status:         Subscribed
Status Details: 
Starts:         06.10.2020
Ends:           06.10.2021

[tronde@rhel7-t1 ~]$ # Aktivierung des RHEL 7 Basis- und Extras-Repo
[tronde@rhel7-t1 ~]$ sudo subscription-manager repos --enable rhel-7-server-rpms
Repository 'rhel-7-server-rpms' is enabled for this system.
[tronde@rhel7-t1 ~]$ sudo subscription-manager repos --enable rhel-7-server-extras-rpms
Repository 'rhel-7-server-extras-rpms' is enabled for this system.

[tronde@rhel7-t1 ~]$ # Ist locale auf en_US.UTF-8 gesetzt?
[tronde@rhel7-t1 ~]$ cat /etc/locale.conf
LANG="en_US.UTF-8"

[tronde@rhel7-t1 ~]$ sudo yum install leapp leapp-repository
# Ausgabe gekürtzt
Transaction Summary
================================================================================
Install  2 Packages (+24 Dependent packages)

Total download size: 5.3 M
Installed size: 19 M
Is this ok [y/d/N]: y
# Ausgabe gekürtzt

Pre-Upgrade-Bericht erstellen

Bevor das eigentliche Upgrade durchgeführt wird, führe ich auf meinem Testsystem das Kommando leapp preupgrade aus. Dieses sammelt Informationen über das System, um die Upgradefähigkeit zu bewerten und erstellt einen detaillierten Bericht, welcher im Pfad /var/log/leapp/leapp-report.txt abgelegt wird.

[tronde@rhel7-t1 ~]$ sudo leapp preupgrade
# Ausgabe gekürzt
============================================================
                           ERRORS                           
============================================================

2021-08-31 06:33:26.035495 [ERROR] Actor: repository_mapping
Message: Data file /etc/leapp/files/repomap.csv is invalid or could not be retrieved.
Summary:
    Details: Could not fetch repomap.csv from https://cert.cloud.redhat.com/api/pes/repomap.csv (unreachable address).
    Hint: Read documentation at: https://access.redhat.com/articles/3664871 for more information about how to retrieve the file.
2021-08-31 06:35:22.415297 [ERROR] Actor: restricted_pcis_scanner
Message: Data file /etc/leapp/files/unsupported_driver_names.json is invalid or could not be retrieved.
Summary:
    Details: Could not fetch unsupported_driver_names.json from https://cert.cloud.redhat.com/api/pes/unsupported_driver_names.json (unreachable address).
    Hint: Read documentation at: https://access.redhat.com/articles/3664871 for more information about how to retrieve the file.
2021-08-31 06:35:47.800140 [ERROR] Actor: pes_events_scanner
Message: Data file /etc/leapp/files/pes-events.json is invalid or could not be retrieved.
Summary:
    Details: Could not fetch pes-events.json from https://cert.cloud.redhat.com/api/pes/pes-events.json (unreachable address).
    Hint: Read documentation at: https://access.redhat.com/articles/3664871 for more information about how to retrieve the file.

============================================================
                       END OF ERRORS                        
============================================================


Debug output written to /var/log/leapp/leapp-preupgrade.log

============================================================
                           REPORT                           
============================================================

A report has been generated at /var/log/leapp/leapp-report.json
A report has been generated at /var/log/leapp/leapp-report.txt

============================================================
                       END OF REPORT                        
============================================================

Answerfile has been generated at /var/log/leapp/answerfile
[tronde@rhel7-t1 ~]$

Dem obigen Codeblock ist zu entnehmen, dass der Pre-Upgrade-Check Fehler festgestellt hat, die behoben werden müssen, bevor ein In-Place-Upgrade durchgeführt werden kann. Dankenswerter Weise ist sowohl in der Ausgabe auf STDOUT als auch in /var/log/leapp/leapp-report.txt der Knowledge-Base-Artikel [3] verlinkt, welcher die Lösung parat hält.

Ist dieser Fehler behoben, lässt man leapp preupgrade ein weiteres Mal laufen und prüft die Ausgabe erneut. Auf meinem Testsystem erhalte ich nun folgende Ausgabe:

[root@rhel7-t1 ~]# leapp preupgrade
# Ausgabe gekürzt
============================================================
                     UPGRADE INHIBITED                      
============================================================

Upgrade has been inhibited due to the following problems:
    1. Inhibitor: Missing required answers in the answer file
Consult the pre-upgrade report for details and possible remediation.

============================================================
                     UPGRADE INHIBITED                      
============================================================


Debug output written to /var/log/leapp/leapp-preupgrade.log

============================================================
                           REPORT                           
============================================================

A report has been generated at /var/log/leapp/leapp-report.json
A report has been generated at /var/log/leapp/leapp-report.txt

============================================================
                       END OF REPORT                        
============================================================

Answerfile has been generated at /var/log/leapp/answerfile

Diesmal weist die Ausgabe darauf hin, dass ein Upgrade durch fehlende Antworten in /var/log/leapp/answerfile verhindert wird. Die genannte Datei kann mit einem Editor geöffnet und entsprechend bearbeitet werden:

[remove_pam_pkcs11_module_check]
# Title:              None
# Reason:             Confirmation
# =================== remove_pam_pkcs11_module_check.confirm ==================
# Label:              Disable pam_pkcs11 module in PAM configuration? If no, the upgrade process will be interrupted.
# Description:        PAM module pam_pkcs11 is no longer available in RHEL-8 since it was replaced by SSSD.
# Type:               bool
# Default:            None
# Available choices: True/False
# Unanswered question. Uncomment the following line with your answer
confirm = True

Die Datei enthält direkt eine Erklärung, warum das erwähnte Modul zu entfernen ist und wie dies zu geschehen hat.

Anschließend empfiehlt sich ein Blick in den Bericht unter /var/log/leapp/leapp-report.txt, um zu prüfen, ob einem Upgrade evtl. weitere Gründe entgegen stehen. Auf die Ausgabe des Berichts in diesem Artikel wird aus Platzgründen verzichtet. Da der Inhalt auf jedem System unterschiedlich ausfallen kann, ist sein Nutzen an dieser Stelle ohnehin stark begrenzt.

Durchführung des In-Place-Upgrade

An dieser Stelle wird es ernst. Man sollte sich noch einmal vergewissern, dass man einen Snapshot bzw. ein geeignetes Backup des Systems hat. Dann wird das Upgrade mit folgendem Befehl gestartet:

# leapp upgrade
# Ausgabe gekürzt
============================================================
                           REPORT                           
============================================================

A report has been generated at /var/log/leapp/leapp-report.json
A report has been generated at /var/log/leapp/leapp-report.txt

============================================================
                       END OF REPORT                        
============================================================

Answerfile has been generated at /var/log/leapp/answerfile

Dieser Vorgang kann mehrere Minuten dauern. Leapp lädt notwendige Daten herunter und bereitet die RPM-Transaktionen für das Upgrade vor. Dabei wird erneut geprüft, ob Gründe vorliegen, die ein Upgrade verhindern können. Sollte dies der Fall sein, bricht leapp den Vorgang ab und erzeugt einen neuen Bericht.

Ist das Upgrade erfolgreich durchgelaufen, muss das System manuell neugestartet werden. Das System startet anschließend in eine RAM-Disk und aktualisiert alle Pakete des Systems. Anschließend wird automatisch ein Neustart ausgeführt. Dieser Vorgang lässt sich am besten an einer (virtuellen) Konsole beobachten.

Nachdem das Upgrade abgeschlossen ist, kann man sich wieder am System anmelden und mit folgenden Kommandos prüfen, ob das System den gewünschten Status hat (vgl. Kapitel 5 in [0]):

[root@rhel7-t1 ~]# cat /etc/redhat-release 
Red Hat Enterprise Linux release 8.4 (Ootpa)

[root@rhel7-t1 ~]# uname -r
4.18.0-305.12.1.el8_4.x86_64

[root@rhel7-t1 ~]# subscription-manager list --installed
+-------------------------------------------+
    Installed Product Status
+-------------------------------------------+
Product Name:   Red Hat Enterprise Linux for x86_64
Product ID:     479
Version:        8.4
Arch:           x86_64
Status:         Subscribed
Status Details: 
Starts:         06.10.2020
Ends:           06.10.2021

[root@rhel7-t1 ~]# subscription-manager release
Release: 8.4

Hier sieht alles gut aus.

Post-Upgrade-Tasks

Kapitel 6 in [0] beschreibt detailliert, welche Aufgaben nach einem erfolgreichen In-Place-Upgrade noch auszuführen sind, um ein möglichst sauberes System zu erhalten.

Auf meinem Testsystem sind einige RHEL 7 Pakete zurückgeblieben, welche ich mit folgendem Kommando entferne:

# dnf remove `rpm -qa | grep -e '\.el[67]' | grep -vE '^(gpg-pubkey|libmodulemd|katello-ca-consumer)' | sort`
Updating Subscription Management repositories.
Dependencies resolved.
===============================================================================
 Package              Arch       Version                     Repository   Size
===============================================================================
Removing:
 doxygen              x86_64     1:1.8.5-4.el7               @System      15 M
 kernel               x86_64     3.10.0-1160.31.1.el7        @System      64 M
 kernel               x86_64     3.10.0-1160.36.2.el7        @System      64 M
 leapp                noarch     0.12.1-1.el7_9              @System      93 k
 leapp-repository     noarch     0.14.0-4.el7_9              @System     1.7 M
 python2-leapp        noarch     0.12.1-1.el7_9              @System     618 k
 ustr                 x86_64     1.0.4-16.el7                @System     279 k

Transaction Summary
===============================================================================
Remove  7 Packages

Freed space: 146 M
Is this ok [y/N]:

# cd /lib/modules && ls -d *.el7*
3.10.0-1160.25.1.el7.x86_64  3.10.0-1160.36.2.el7.x86_64
3.10.0-1160.31.1.el7.x86_64

# /bin/kernel-install remove 3.10.0-1160.36.2.el7.x86_64 /lib/modules/3.10.0-1160.36.2.el7.x86_64/vmlinuz
# /bin/kernel-install remove 3.10.0-1160.25.1.el7.x86_64 /lib/modules/3.10.0-1160.25.1.el7.x86_64/vmlinuz
# /bin/kernel-install remove 3.10.0-1160.31.1.el7.x86_64 /lib/modules/3.10.0-1160.31.1.el7.x86_64/vmlinuz

Damit ist es geschafft. Das System wurde erfolgreich auf RHEL 8 aktualisiert.

Fazit

Dieser Artikel stellt das RHEL-In-Place-Upgrade vor und nennt kurz einige Gründe, wann dies gegenüber einer Neuinstallation Vorteile bietet. Anschließend wurde das Upgrade an einem Testsystem demonstriert mit dem Ziel, einen Überblick über den Upgrade-Prozess zu geben.

Für In-Place-Upgrades von Produktionssystemen ist ein Blick in die Hersteller-Dokumentation, Backups und sorgfältige Planung unerlässlich.

Das für diesen Artikel verwendete Testsystem besteht lediglich aus einer Minimal-Installation ohne Anwendungen von Dritten. Ob ein In-Place-Upgrade auch mit installierten Anwendungen Dritter funktioniert, hängt vom Einzelfall ab und ist sorgfältig zu prüfen und zu testen.

Erste Versuche mit Web- und Anwendungsservern aus unserer Umgebung konnten mit positivem Ergebnis abgeschlossen worden.

Es gibt Anwendungsfälle, wo ein In-Place-Upgrade vorteilhaft ist. Ich persönlich bevorzuge, wenn möglich und vom Aufwand vertretbar, jedoch die Neuinstallation inkl. Migration der Daten auf einem neuen System. So kann sichergestellt werden, dass keine unentdeckten Altlasten mitgeschleppt werden.

[0] Upgrading from RHEL 7 to RHEL 8. Instructions for an in-place upgrade from Red Hat Enterprise Linux 7 to Red Hat Enterprise Linux 8. Red Hat Enterprise Linux 8. Red Hat Customer Content Services.

[1] Supported in-place upgrade paths for Red Hat Enterprise Linux (Login required)

[2] Red Hat Enterprise Linux technology capabilities and limits

[3] Data required by the Leapp utility for an in-place upgrade from RHEL 7 to RHEL 8 (Login required)