<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>MueSLi Tech-Blog</title><link href="http://www.mueslihq.de/techblog/" rel="alternate"/><link href="http://www.mueslihq.de/blog.xml" rel="self"/><id>urn:uuid:435846e1-d090-345b-aeb8-fd77cc6ca4f7</id><updated>2026-02-01T00:00:00Z</updated><author><name/></author><entry><title>Digitale Unabhängigkeit - der Digital Independence Day</title><link href="http://www.mueslihq.de/techblog/digital_independence_day/" rel="alternate"/><updated>2026-02-01T00:00:00Z</updated><author><name>Robin Schubert</name></author><id>urn:uuid:b8efc660-ec96-3446-b0f9-7e964a6815c4</id><content type="html">&lt;p&gt;&lt;img src="https://di.day/wp-content/uploads/2025/12/Logo_BG-4_so.svg" /&gt;&lt;/p&gt;
&lt;p&gt;Wer schon länger Linux nutzt, hat in der Regel seine Gründe. Nicht selten ist das der Wunsch nach Freiheit; die Freiheit die Apps zu installieren die man nutzen möchte oder braucht, und nicht die vom Hersteller genehmigten. Die Freiheit seine Software zu verändern und anzupassen und vor allem auch die Freiheit die eigene Privatsphäre zu schützen anstatt auf Gedeih und Verderb den Nutzungsbedingungen von Big Tech ausgeliefert zu sein.&lt;/p&gt;
&lt;p&gt;Das Thema ist uns nicht neu. Neu ist aber, dass sich seit kurzem auch eine wesentlich breitere Masse dafür interessiert; Nicht nur Hobbyisten und Nerds sondern auch Eltern die sich fragen wie sie ihre Kinder im Netz vor rechter Hetze schützen können, Politiker:innen die Angst haben aus ihren Outlook-Konten und anderen Microsoft Diensten ausgesperrt zu werden, Queere Personen die sich auf Sozialen Plattformen ausgeschlossen oder sogar verfolgt fühlen, Unternehmer:innen die Betriebsspionage fürchten oder einfach anständige Menschen die die Nase voll haben von einer digitalen Abhängigkeit die ihnen KI generierten &lt;em&gt;Slop&lt;/em&gt; in jeder möglichen Art aufdrängt.&lt;/p&gt;
&lt;h2&gt;So hilflos sind wir nicht&lt;/h2&gt;
&lt;p&gt;Die gute Nachricht ist: So hilflos sind wir nicht. Wir können direkt etwas ändern. Es reicht wenn es kleine Schritte sind; Stück für Stück, aber immer weiter. Das ist die Idee vom &lt;a href="https://di.day/"&gt;Digitalen Unabhängigkeitstag&lt;/a&gt; oder auch Digital Independence Day (oder kurz DID). Den Startschuss hatte &lt;a href="https://media.ccc.de/v/39c3-die-kanguru-rebellion-digital-independence-day"&gt;Marc-Uwe Kling auf dem 39. Chaos Communication Kongress&lt;/a&gt; gegeben.&lt;/p&gt;
&lt;p&gt;Der &lt;em&gt;DID&lt;/em&gt; soll jeden ersten Sonntag im Monat stattfinden, mit der Idee dass man sich für jeden DID eine weitere Kleinigkeit vornimmt mit der man sich digital etwas unabhängiger macht. Das könnten Dinge sein wie die Standard Suchmaschine auf dem Handy zu wechseln, von Google weg zu einer datenschutzfreundlicheren Alternative. Oder den Messenger von WhatsApp zu Signal zu wechseln. Natürlich ist es auch völlig okay erst ein mal die Alternative auszuprobieren und eine Zeit lang Zweigleisig zu fahren.&lt;/p&gt;
&lt;p&gt;Auf &lt;a href="https://di.day/category/rezepte/"&gt;https://di.day&lt;/a&gt; gibt es dazu einige &lt;em&gt;Wechselrezepte&lt;/em&gt; die das Wechseln erleichtern und &lt;em&gt;schmackhaft&lt;/em&gt; machen sollen.&lt;/p&gt;
&lt;p&gt;Zuletzt darf man voller Stolz mit seinem Wechsel angeben; ob in sozialen Netzwerken oder bei Freunden und Verwandten ;-) Unter den Hashtags &lt;a href="https://mastodon.social/tags/diday"&gt;#diday&lt;/a&gt;, &lt;a href="https://mastodon.social/tags/didit"&gt;#DIDit&lt;/a&gt; oder &lt;a href="https://mastodon.social/tags/dutgemacht"&gt;#DUTgemacht&lt;/a&gt; findet man schon jetzt etliche Nachrichten von Menschen die die Nase voll hatten und den Digitalen Unabhängigkeitstag mit einem eigenen Schritt in Richtung ihrer eigenen Unabhängigkeit feiern.&lt;/p&gt;
&lt;h2&gt;Zusammen feiern macht mehr Spaß&lt;/h2&gt;
&lt;p&gt;Es war schon immer so; zusammen feiern macht mehr Spaß. Deshalb entstehen gerade in vielen Städten &lt;a href="https://termine.di.day/"&gt;überall offene Treffs&lt;/a&gt;. Wer Fragen oder Bedenken hat oder sich einfach nur austauschen will; die Menschen kommen zusammen um ihre kleinen und großen Schritte zu machen um langsam aber sicher eine Bewegung weg von Big Tech zu freien und unabhängigen Alternativen zu machen. Auch in Münster wollen wir regelmäßig in präsenz zum ersten Sonntag im Monat ein offenes Treffen anbieten, um dieses Projekt zu unterstützen. Zum ersten mal wird das am 01.02.2026 &lt;a href="https://www.warpzone.ms/perma/digital-independence-day-am-01-02/3339/"&gt;in der Warpzone&lt;/a&gt; stattfinden. Mitglieder der Warpzone e.V. und MüSLi aber auch aus anderen Gruppierungen aus Münster werden auch zur Beratung und Beantwortung von Fragen vor Ort sein oder einfach feiern.&lt;/p&gt;
&lt;p&gt;Also kommt vorbei, teilt eure Erfolge und Erfahrungen, macht mit und feiert mit uns!&lt;/p&gt;
</content></entry><entry><title>Workaround für Kernel Panic auf ThinkPad T410 unter Debian Trixie</title><link href="http://www.mueslihq.de/techblog/kernel_panic_T410_trixie/" rel="alternate"/><updated>2025-05-18T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:09314b2a-77bc-3a8c-b2f4-0a0fe92e3498</id><content type="html">&lt;p&gt;Im Mail 2025 habe ich Testinstallationen von Debian Trixie (Testing) auf zwei unterschiedlichen ThinkPad T410 vorgenommen.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Rechner: Intel(R) Core(TM) i5 CPU M 580  @ 2.67GHz, BIOS Version: 1.36 &lt;/li&gt;
&lt;li&gt;Rechner: Intel(R) Core(TM) i5 CPU M 520  @ 2.40GHz ,BIOS Version: 1.45 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Beide Rechner stürtzen unvermittelt ab. In den Logfiles war kein relevanter Eintrag zu finden. Zufälligerweise ist ein Absturz passiert als von der graphischen Oberfläche auf die Console gewechselt wurde.  Hier stand dann:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Kernel panic - not syncing: DMAR hardware is malfunctioning
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="kernel_panic_t410.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Die Internetrecherche ergab, dass der Boot-Parameter &lt;code&gt;intel_iommu=igfx_off&lt;/code&gt; das Problem behebt. Dem ist in der Tat so! Abstürze sind danach nicht mehr aufgetreten.&lt;/p&gt;
&lt;p&gt;Der Boot-Parameter kann durch Eintrag in die &lt;code&gt;/etc/default/grub&lt;/code&gt; persistiert werden.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@t410:~# grep igfx_off /etc/default/grub 
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=igfx_off"
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://thinkwiki.de/T410"&gt;https://thinkwiki.de/T410&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/22867061/intel-iommu-what-is-it"&gt;https://stackoverflow.com/questions/22867061/intel-iommu-what-is-it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/questions/19486/how-do-i-add-a-kernel-boot-parameter"&gt;https://askubuntu.com/questions/19486/how-do-i-add-a-kernel-boot-parameter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>In Memory Datenbank mit Umgebungsvariablen</title><link href="http://www.mueslihq.de/techblog/inMemoryDB/" rel="alternate"/><updated>2024-04-26T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:dff27001-6323-36a1-af01-e40abf582592</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Manchmal benötigt man eine einfache und generische Variante um Daten zwischen
Anwendungen auszutauschen welche zu dem nur für eine gewisse Zeit gültig sind.
Außerdem sollte der Dienst keine weiteren Abhängigkeiten benötigen um den
Betrieb und die leichte Verteilung zu ermöglichen und auf allen Systemen
laufen.&lt;/p&gt;
&lt;h2&gt;Server-Umsetzung&lt;/h2&gt;
&lt;p&gt;Realisieren kann man dies einfach und sicher z.B. mit der Programmiersprache
&lt;a href="https://nim-lang.org"&gt;Nim&lt;/a&gt; und einem Web-Framework. Die Datenspeicherung
selbst wird in den Umgebungsvariablen der Anwendung realisiert und die
Schlüssel entsprechen Pfaden die intern mit base64-Kodierung umgesetzt
werden. So lassen sich einfach auch größere Datenmengen schnell teilen. Eine
Beispielumsetzung ist im Projekt &lt;a href="https://pf4sh.eu/git/pulux/envmw"&gt;envmw&lt;/a&gt; zu
finden.&lt;/p&gt;
&lt;h2&gt;Client&lt;/h2&gt;
&lt;p&gt;Als Client kann jede http-fähige Anwendung eingesetzt werden. Hier ein Beispiel
auch in Nim:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import os
import std/[times, asyncdispatch, strformat, strutils]
import httpclient, httpcore
import jsony

type
  KV = object
    key: string
    value: string
    expire: float

var
  data: KV
  t1, t2: float
  n = 500
  client: HttpClient

proc twrite(data: KV) {.async.} =
  let client = newAsyncHttpClient()
  #client.headers = newHttpHeaders({"Content-Type": "application/json"})
  discard await client.postContent("http://127.0.0.1:6380/set",
      body = data.toJson())
  client.close()


proc main() {.async.} =
  while true:
    t1 = epochTime()
    for i in 1 .. n:
      data.key = fmt"/app/part1/subpart3/key{i}"
      data.expire = i/10
      data.value = fmt"{epochTime()=}, {i=}"
      await twrite(data)
    t2 = epochTime()

    echo fmt"{(t2-t1)/n.toFloat() * 1000} ms/req"
    client = newHttpClient()
    let key = "/app/part1/subpart3/key10"
    echo client.getContent(fmt"http://127.0.0.1:6380/get{key}").strip()
    sleep(500)
    echo client.getContent(fmt"http://127.0.0.1:6380/get{key}").strip()
    sleep(600)
    assert client.getContent(fmt"http://127.0.0.1:6380/get{key}") == "\n"
    client.close()


when isMainModule:
  waitFor main()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Zusatzfunktionen&lt;/h2&gt;
&lt;p&gt;In &lt;code&gt;envmw&lt;/code&gt; steht noch eine ping-Funktion zur Verfügung und mit &lt;code&gt;/keys&lt;/code&gt; können
alle verfügbaren Schlüssel erfragt werden.&lt;/p&gt;
&lt;h2&gt;Datenspeicherung&lt;/h2&gt;
&lt;p&gt;Es ist natürlich auch möglich die Daten auf dem Server, z.B. durch ein Signal
an diesen zu speichern. Hier könne man die Key-Value Paare z.B. als Symlink in
base64 Kodierung effizient im Dateisystem abspeichern. Hier ein Beispiel in
shell-script&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ln -s $(echo $VALUE | base64) $KEY
RVALUE = $(readlink $KEY | base64 -d)
&lt;/code&gt;&lt;/pre&gt;
</content></entry><entry><title>Zentrale Schlüsselverwaltung für ssh</title><link href="http://www.mueslihq.de/techblog/ssh_central_keys/" rel="alternate"/><updated>2023-10-30T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:38e90ac9-045f-315d-8d94-8b7a57f4647f</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Wenn man mehr als einen Server und mehrere Nutzer hat, die evtl. auch noch nur
eingeschränkt auch die verteilten Dienste zugreifen dürfen, ist die manuelle
Schlüsselverwaltung aufwendig. Hier bietet sich eich zentraler Server mit allen
Schlüsseln incl. deren Konfiguration z.B. &lt;code&gt;command&lt;/code&gt; an.&lt;/p&gt;
&lt;p&gt;Um diese Schlüssel nutzen zu können bietet der &lt;code&gt;sshd&lt;/code&gt; die Möglichkeit den
Nutzerschlüssel per Anwendung zu erhalten &lt;code&gt;AuthorizedKeysCommand&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Server-Baum&lt;/h2&gt;
&lt;p&gt;Am einfachsten ist es wenn man einen Dienst hat auf den alle Server zugreifen
können, z.B. die eigene Webseite. Damit die Konfiguration wie auch die Server
und die Nutzer nicht enthüllt werden werden wir hier mit den Hashwerten und
asynchron verschlüsselten Dateien arbeiten. Der Dateibaum auf dem Server ist im
Klartext wie folgt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;keys/
├── user1
│   ├── host1
│   └── host2
├── user2
│   └── host2
└── user3
    ├── host1
    └── host3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;nur das statt der Klarnamen die Hash-Werte verwendet werden.&lt;/p&gt;
&lt;h2&gt;Schlüsseldaten für den Server&lt;/h2&gt;
&lt;p&gt;Da die Dateien mit den öffentlichen Nutzerschlüsseln evtl. auch die Namen und
andre Daten enthalten, die andere nicht angehen, ist es sinnvoll diese zu
verschlüsseln. Hier biete sich &lt;code&gt;age&lt;/code&gt; an. Zuerst wird ein neues Schlüsselpaar
mit &lt;code&gt;age-keygen -o /etc/ssh/key.txt &amp;amp;&amp;amp; chown nobody /etc/ssh/key.txt&lt;/code&gt; erzeugt.&lt;/p&gt;
&lt;p&gt;Mit dem so erzeugten Public-Key kann der Inhalt, z.B. der ursprünglichen Nutzer
"authorized_keys"-Datei, mit:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh

if [ $# -eq 1 ]; then
    grep public /etc/ssh/key.txt | awk -F': ' '{print $2}' &amp;gt; /tmp/pub_key
    UK=$1
    U=$(echo user1 | sha256sum | awk '{print $1}')
    H=$(echo hostname | sha256sum | awk '{print $1}')
    mkdir -p keys/$U
    cat $UK | age -a -R /tmp/pub_key &amp;gt; keys/$U/$H
else
    echo $0 user_keys_file
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;für den zentral Server erzeugt werden.&lt;/p&gt;
&lt;p&gt;Diese müssen dann noch in den passenden Serverordner kopiert oder
synchronisiert werden.&lt;/p&gt;
&lt;h2&gt;Script zum holen der Schlüssel&lt;/h2&gt;
&lt;p&gt;Die Script wird mit Nutzername des sich anmeldenden von &lt;code&gt;sshd&lt;/code&gt; aufgerufen,
zusätzlich fragen wir noch den Hostnamen ab. In der &lt;code&gt;sshd_config&lt;/code&gt; ist
folgendes einzutragen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;AuthorizedKeysCommand /usr/local/bin/get_key %u
AuthorizedKeysCommandUser nobody
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;und der Dienst ist nach der Änderung neu zu starten.&lt;/p&gt;
&lt;p&gt;Das ausführbare Script selbst ist recht einfach:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh

H=$(hostname | sha256sum | awk '{print $1}')
U=$(echo $1 | sha256sum | awk '{print $1}')
logger "get central key for: $1"
curl -sf https://my_website.host/keys/$U/$H | age -d -i /etc/ssh/key.txt || echo "$U/$H"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So kann man es auch in der Shell aufrufen und testen.&lt;/p&gt;
&lt;h1&gt;Zusammenfassung&lt;/h1&gt;
&lt;p&gt;Mit dem hier gezeigten lassen sich die Berechtigungen für verschiedene Nutzer
und Server zentral und sicher Verwalten und es werden keine weiteren
Informationen preisgegeben, denn nur der Besitzer des privaten Schlüssels ist
in der Lage die Schlüsselinformationen der Nutzer zu lesen.&lt;/p&gt;
&lt;p&gt;Alle Scripte sind auch in &lt;a href="https://pf4sh.eu/git/pulux/zentral_keys"&gt;1&lt;/a&gt; zu
finden.&lt;/p&gt;
</content></entry><entry><title>Backup bei Anschluss des USB-Laufwerks</title><link href="http://www.mueslihq.de/techblog/restic_by_plugin/" rel="alternate"/><updated>2023-08-23T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:417d533c-a8bc-3911-81fe-af7257e0d48e</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Da moderne Laptops oft keine Netzwerk-Buchse mehr haben und die WLAN Verbindung
meist langsamer als einen Kabelverbindung ist, man aber doch ein Backup
zügig durch führen möchte, bietet es sich an hierfür eine Wechseldatenträger
via USB zu verwenden. Weiterhin wäre es natürlich sehr schön wenn man dies
nicht noch explizit anstoßen muss. Mit ein wenig Skripting und der passenden
udev-Regel ist das einfach möglich.&lt;/p&gt;
&lt;h2&gt;Vorbereitung&lt;/h2&gt;
&lt;p&gt;Um den Vorgang nur bei den richtigen Datenträger auszulösen kann man die
&lt;code&gt;idVendor&lt;/code&gt; und &lt;code&gt;idProduct&lt;/code&gt; Nummern des Backuplaufwerks nutzen. Ein Eintrag in
&lt;code&gt;/etc/udev/rules.d/test_backup.rules&lt;/code&gt; mit folgendem Inhalt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ATTRS{idVendor}=="152d", ATTRS{idProduct}=="3234", KERNEL=="sd*", RUN+="/usr/local/bin/bktest.sh"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;wobei die Werte z.B. mit &lt;code&gt;lsusb&lt;/code&gt; ermittelt werden können, ein dazu passendes
Skript aus. Das Skript selbst schreibt das neue Gerät in eine FiFo-Datei, so
das andere ohne zu pollen davon erfahren können.&lt;/p&gt;
&lt;p&gt;Hier ein Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;#!/bin/sh

if [ &amp;quot;${ACTION}&amp;quot; = add -a -d &amp;quot;/sys${DEVPATH}&amp;quot; ]; then
    date &amp;gt; /tmp/usbdev.log
    if [ -p &amp;quot;/tmp/usbdev&amp;quot; ]; then
        echo &amp;quot;${DEVPATH}&amp;quot; | awk -F&amp;#39;block&amp;#39; &amp;#39;{print $2}&amp;#39; | awk -F&amp;#39;/&amp;#39; &amp;#39;{print &amp;quot;connected /dev/&amp;quot;$3}&amp;#39; &amp;gt;&amp;gt; /tmp/usbdev
    else
        echo &amp;quot;pipe not found&amp;quot; &amp;gt; /tmp/usbdev.log
    fi
    echo &amp;quot;${DEVPATH}&amp;quot; | awk -F&amp;#39;block&amp;#39; &amp;#39;{print $2}&amp;#39; | awk -F&amp;#39;/&amp;#39; &amp;#39;{print &amp;quot;connected /dev/&amp;quot;$3}&amp;#39; &amp;gt;&amp;gt; /tmp/usbdev.log
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dabei muss die FiFo-Datei dem lesenden Nutzer gehören.&lt;/p&gt;
&lt;p&gt;Das Script was dann das eigentliche Backup durchführt erstellt die FiFo-Datei
und wartet dort auf Nachrichten.&lt;/p&gt;
&lt;p&gt;Hier ein Beispiel mit &lt;code&gt;restic&lt;/code&gt; als normaler Nutzer.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

backup()
{
    REPO="$1/rbk"
    export RESTIC_REPOSITORY="$REPO"
    if [ ! -d "$REPO" ]; then
        echo "$REPO not found" &amp;gt;&amp;amp;2
        return 1
    else
        echo mkdir -p "$REPO"
        # restic init
    fi
    restic forget --keep-last 365 --prune
    restic -q backup --exclude={$HOME/.cache} --one-file-system $HOME
    restic stats
    echo "done"
    logger "backup for $USER done"
}

trap "rm -f /tmp/usbdev" EXIT


if [ ! -p /tmp/usbdev ]; then
     mkfifo /tmp/usbdev
fi

echo "start waching"
if [ -z "$RESTIC_PASSWORD" ]; then
    RESTIC_PASSWORD=$(pass path/to/your/password)
    export RESTIC_PASSWORD
fi

while true; do
    if read -r line &amp;lt; /tmp/usbdev; then
        if echo "$line" | grep "connected" | grep "sd" &amp;gt; /dev/null; then
            USB="${line//connected /}"
            M="${USB//\/dev/\/media/}"
            if [ -f "$M" ] &amp;amp;&amp;amp; echo "$USB" | grep -v "1" &amp;gt; /dev/null; then
                echo "ignore $USB" &amp;gt;&amp;amp;2
            else
                pmount "$USB"
                backup "$M" || echo "please check your setup"
                pumount "$USB"
            fi
        fi
    fi
done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Durch ausführen dies Skripts im Hintergrund, z.B. beim starten der grafischen
Oberfläche, wird ein Backup durchgeführt, sobald der passende Datenträger
verfügbar ist.&lt;/p&gt;
&lt;h3&gt;Anmerkung&lt;/h3&gt;
&lt;p&gt;Die externe Platten muss nicht wie sonst üblich verschlüsselt sein, denn die
Daten werden durch &lt;code&gt;restic&lt;/code&gt; selbst verschlüsselt.&lt;/p&gt;
&lt;h3&gt;Anmerkung 2&lt;/h3&gt;
&lt;p&gt;Bei USB-Adaptern wird nur der Adapter selbst eindeutig erkannt, nicht aber die
die daran angeschlossene Platte. Durch einen Test z.B. auf eine bestimmte Datei
und/oder deren Inhalt kann die notwendige Aktion darüber gesteuert werden.&lt;/p&gt;
&lt;h3&gt;Anmerkung 3&lt;/h3&gt;
&lt;p&gt;Um ein Sytem-Backup als normaler Nutzer durchführen zu können, gibt es unter
&lt;a href="https://restic.readthedocs.io/en/latest/080_examples.html#backing-up-your-system-without-running-restic-as-root"&gt;systembackup&lt;/a&gt;
eine Anleitung.&lt;/p&gt;
&lt;p&gt;Der entscheidende Punkt ist hier die Anwendung vom &lt;code&gt;setcap
cap_dac_read_search=+ep&lt;/code&gt;, dabei ist aber zu beachten, das die erzeugten Dateien
im Backup-Repo dem normalen User gehören.&lt;/p&gt;
</content></entry><entry><title>Erfahrungen mit dem Upgrade auf Debian 12 (Bookworm)</title><link href="http://www.mueslihq.de/techblog/debian-12_upgrade/" rel="alternate"/><updated>2023-07-27T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:dddaa8b3-e0dd-364b-acf3-4189e094a807</id><content type="html">&lt;p&gt;Seit dem  10.06.2023 ist nun Debian 12 die stabile Debian Distribution. Ich möchte in einem lebenden Dokumente beschreiben was funktioniert hat und auch was nicht mehr funktioniert (wenn etwas nicht mehr funktioniert, so muß das nicht unbedingt an Debian, sondern kann auch ein meiner Mißkonfiguration liegen.)&lt;/p&gt;
&lt;p&gt;Aktuell habe ich &amp;gt; 20 Rechner auf Debian 12 geupdated&lt;/p&gt;
&lt;h2&gt;Allgemeines Vorgehen&lt;/h2&gt;
&lt;p&gt;Die Vorgehensweise ist detailliert in der &lt;a href="https://www.debian.org/releases/bookworm/amd64/release-notes/ch-upgrading.de.html"&gt;offiziellen Debian Dokumentation&lt;/a&gt; beschrieben.&lt;/p&gt;
&lt;p&gt;Ich habe mich zum großen Teil daran gehalten.&lt;/p&gt;
&lt;p&gt;Zuerst alle Nicht-Libraries deinstallieren (mit &lt;code&gt;apt purge&lt;/code&gt;), die man nicht explizit selbst installiert hat.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt-forktracer  |sort | grep -v ^lib | egrep -v "net.downloadhelper.coapp|signal-desktop|zoom"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In meinem Falle war das z.B.:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;matrix-mirage (0.6.4~dfsg+~hsluv1.0.0-4)
python3-matrix-nio (0.16.0-1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn einem die Ausgabe gefällt kann man eingeben:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt purge $(apt-forktracer  |sort | grep -v ^lib | egrep -v "net.downloadhelper.coapp|signal-desktop|zoom" | awk '{print $1 " "}')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann Deinstallation der Libraries nach Augenmaß&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt purge $(apt-forktracer  |sort | grep  ^lib  |awk '{print $1 " "}')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn einem das Ergebnis gefällt 'y' drücken.&lt;/p&gt;
&lt;p&gt;Pakete, die nicht mehr installiert sind und deren Config noch enthalten ist, können gelöscht werden.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dpkg -l | awk '/^rc/ { print $2 }'
apt purge $(dpkg -l | awk '/^rc/ { print $2 }')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn einem das Ergebnis gefällt 'y' drücken.&lt;/p&gt;
&lt;p&gt;Dann Deinstallation der nicht mehr benötigten Pakete&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt autoremove 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn einem das Ergebnis gefällt 'y' drücken.&lt;/p&gt;
&lt;p&gt;Nach dieser Vorbereitung kann man mit dem eigentlichen Update fortfahren.
Die &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; ändern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sed  -i 's/bullseye/bookworm/g' /etc/apt/sources.list
sed  -i 's/non-free/non-free-firmware/g' /etc/apt/sources.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann der Dreiklang&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt update 
apt upgrade --without-new-pkgs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn einem das Ergebnis gefällt 'y' drücken.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  apt full-upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn einem das Ergebnis gefällt 'y' drücken.&lt;/p&gt;
&lt;p&gt;Nach dem Reboot sollte man noch ein bisschen aufräumen, um für das nächste Upgrade vorbereitet zu sein&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt autoremove
apt-forktracer  |sort | grep -v ^lib | egrep -v "net.downloadhelper.coapp|signal-desktop|zoom"
apt purge $(apt-forktracer  |sort | grep -v ^lib | egrep -v "net.downloadhelper.coapp|signal-desktop|zoom" | awk '{print $1 " "}')
apt autoremove

dpkg -l | awk '/^rc/ { print $2 }'
    apt purge $(dpkg -l | awk '/^rc/ { print $2 }')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;fertig.&lt;/p&gt;
&lt;h2&gt;Was klappt ohne Nacharbeiten&lt;/h2&gt;
&lt;p&gt;Folgende Programme/Pakte wurden nach dem Upgrade getestet und liefen ohne Beanstandung konfiguriert weiter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;apache2&lt;ul&gt;
&lt;li&gt;Konfiguration mit Client Zertifikaten&lt;/li&gt;
&lt;li&gt;Subversion im apache&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;postfix&lt;ul&gt;
&lt;li&gt;einfache Mail Konfiguration&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;gitolite&lt;/li&gt;
&lt;li&gt;gitweb&lt;/li&gt;
&lt;li&gt;gnome mit evolution, rhythmbox, libreoffice, ...&lt;/li&gt;
&lt;li&gt;epson Drucker läuft &lt;/li&gt;
&lt;li&gt;lektor für die MueSLI-Seiten &lt;/li&gt;
&lt;li&gt;mysql&lt;/li&gt;
&lt;li&gt;icinga client&lt;/li&gt;
&lt;li&gt;icinga server&lt;/li&gt;
&lt;li&gt;KVM-Server &lt;/li&gt;
&lt;li&gt;BackupPC&lt;/li&gt;
&lt;li&gt;X2GO&lt;/li&gt;
&lt;li&gt;gome3 Desktop environment (inklusive dem Restore  des "vertical desktops")&lt;/li&gt;
&lt;li&gt;mate environment (Workaround für ssh-agent Problem &lt;a href="https://forums.debian.net/viewtopic.php?t=143134"&gt;https://forums.debian.net/viewtopic.php?t=143134&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NFS-Server und Client &lt;/li&gt;
&lt;li&gt;Firefox keine Probleme mit Mediatheken&lt;/li&gt;
&lt;li&gt;letsencrypt mit cryptsetup&lt;/li&gt;
&lt;li&gt;pass, gpg, git-crypt, etc&lt;/li&gt;
&lt;li&gt;apt-cacher-ng&lt;/li&gt;
&lt;li&gt;Upgrade von Rechnern mit verschlüsselten Festplatten erfolgreich&lt;/li&gt;
&lt;li&gt;python-Skripte laufen&lt;/li&gt;
&lt;li&gt;unterschiedliche Soundkarten wie: Beyerdynamic Phonum Voice, RME Fireface UCX II&lt;/li&gt;
&lt;li&gt;komplexere Mailkonfigurationen mit postfix, dovecot und opendkim&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Was klappt mit kleinen Nacharbeiten&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PHP&lt;ul&gt;
&lt;li&gt;manchmal ist ein &lt;code&gt;a2enmod php8.2&lt;/code&gt; notwendig&lt;/li&gt;
&lt;li&gt;Natürlich müssen die Anwendungen unter PHP8 lauffähig sein. Ein Aufruf von: &lt;code&gt;mktime()&lt;/code&gt; führt nun, richtigerweise, zu einem fatalen Fehler.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;python. Kleine Nacharbeiten beim der Verwendung von &lt;code&gt;pymysql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;TeVii Technology Ltd. DVB-S2 S660&lt;/h2&gt;
&lt;p&gt;Nach Installation der Firmware ist diese TV-Karte unter Debian 11 lauffähig. Die Firmware Dateien &lt;code&gt;dvb-fe-ds3000.fw&lt;/code&gt; und  &lt;code&gt;dvb-usb-s660.fw&lt;/code&gt; findet man im Git-Repository:  &lt;a href="https://github.com/OpenELEC/dvb-firmware/tree/master/firmware/"&gt;https://github.com/OpenELEC/dvb-firmware/tree/master/firmware/&lt;/a&gt;. Diese sind einfach in das Verzeichnis: &lt;code&gt;/lib/firmware/&lt;/code&gt; zu kopieren.&lt;/p&gt;
&lt;p&gt;Leider ist die Karte mit dem Standard Debian 12 Kernel (aktuell 6.1.0-12-amd64) nicht mehr lauffähig. Man erhält folgenden Fehler:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@musix:~# dmesg  |grep DVB
[    2.752010] usb 2-1.1: Product: DVBS2BOX
[    7.431405] dvbdev: DVB: registering new adapter (TeVii S660 USB)
[    8.013135] DVB: Unable to find symbol ds3000_attach()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hier handelt es sich anscheinend um einen BUG im Kernel (&lt;a href="https://lore.kernel.org/lkml/2023090719-virtuous-snowflake-d015@gregkh/"&gt;https://lore.kernel.org/lkml/2023090719-virtuous-snowflake-d015@gregkh/&lt;/a&gt;). Dieser ist in einer neueren Kernel Version behoben.&lt;/p&gt;
&lt;p&gt;Es kann sinnvoll sein den Kernel auf einer anderen Maschine mit genügend Festplattenspeicher und einer schnellen CPU zu kompilieren und daraus ein Paket für das Zielsystem zu bauen. Die Schritte dazu sind detailliert unter &lt;a href="https://wiki.debian.org/BuildADebianKernelPackage"&gt;BuildADebianKernelPackage&lt;/a&gt; und &lt;a href="https://kernel-team.pages.debian.net/kernel-handbook/ch-common-tasks.html#s-common-official"&gt;Chapter 4. Common kernel-related tasks&lt;/a&gt; beschrieben.&lt;/p&gt;
&lt;p&gt;Folgende Schritte habe ich ausgeführt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@bookworm03:/usr/src
tar xvaf linux-6.5.5.tar.xz # Sourcen von kernel.org
apt-get install build-essential
apt-get build-dep linux
cd linux-6.5.5
cp /boot/config-6.1.0-12-amd64  .config
make oldconfig # Alle Fragen im Default
export MAKEFLAGS=-j$(nproc)
make bindeb-pkg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Transferiert man diesen Kernel auf das Zielsystem und installiert ihn mit &lt;code&gt;apt install&lt;/code&gt; ist die Karte wieder lauffähig.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@musix:~# dmesg |grep DVB
[    2.384082] usb 2-1.2: Product: DVBS2BOX
[    4.718138] dvbdev: DVB: registering new adapter (TeVii S660 USB)
[    5.036477] usb 2-1.2: DVB: registering adapter 0 frontend 0 (Montage Technology DS3000)..
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Was klappt (noch) nicht&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Behringer XR-18 läuft nicht als Standard-Soundkarte in Gnome: zu viele Kanäle für GNOME? (Test mit M-Audio PCI Soundkarte läuft)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scanner "Hp Officejet Pro 6830"  nun als AD Scanner erkannt. AD funktioniert jedoch nicht -&amp;gt; scanner mit simplescan etc. funktioniert nicht&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kleine Nachkonfiguration&lt;/h2&gt;
&lt;p&gt;Wer lieber vertikal gestapelte Workspaces mag, wie sie unter Debian 11 Standard waren, kann diese auch unter Debian 12 wiederherstellen.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt install gnome-shell-extension-vertical-overview
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;über die &lt;code&gt;gnome-extensions-app&lt;/code&gt; kann die Option "Vertical Overview (Bring back vertically stacked workspaces."&lt;/p&gt;
&lt;h2&gt;3rd Party software&lt;/h2&gt;
&lt;h3&gt;Nexcloud 25.0.13&lt;/h3&gt;
&lt;p&gt;Nach dem Upgrade auf Debian 12 meldet die Nextcloud-Installation, dass diese Version nicht mit PHP 8.2 lauffähig ist. 
In die Datei &lt;code&gt;lib/versioncheck.php&lt;/code&gt; im Nextcloud-DOCUMENT_ROOT kann jedoch die benötigte Version geändert werden (&lt;code&gt;(PHP_VERSION_ID &amp;gt;= 80300&lt;/code&gt; statt &lt;code&gt;PHP_VERSION_ID &amp;gt;= 80200&lt;/code&gt;). Danach kann problemlos auf Version 27.x.x geupated werden.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.debian.org/releases/bookworm/amd64/release-notes/ch-upgrading.de.html"&gt;Chapter 4. Upgrades von Debian 11 (Bullseye)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forums.debian.net/viewtopic.php?t=143134"&gt;ssh-agent under Mate does not remember the keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.nextcloud.com/t/php8-2-with-nextcloud-25-0-2/151769/26"&gt;PHP 8.2 with Nextcloud 25.0.2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>HOME Verzeichnis nach ssh-login</title><link href="http://www.mueslihq.de/techblog/merge_home/" rel="alternate"/><updated>2023-03-04T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:fa3346b9-f980-392f-b058-e6c9d5c447cd</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Wäre es nicht praktisch wenn ich auf einem entfernten System auch meine lokalen
Dateien verfügbar hätte. Diese Idee hatten auch die Plan9 Entwickler, weshalb
jedes Program seinen eigenen Namensraum bekommt. Dies kann man, wenn auch
nicht so elegant wie dort, auch mit ein paar Werkzeugen &lt;code&gt;iproute2, ssh, sshfs, mergerfs&lt;/code&gt;
unter Linux nachbauen.&lt;/p&gt;
&lt;h2&gt;Vorbereitung&lt;/h2&gt;
&lt;p&gt;Auf dem lokalen und dem entfernten System muss &lt;code&gt;sshd&lt;/code&gt; laufen, es werden jeweils
User mit dem gleichen Namen benötigt und auf dem entfernten System muss &lt;code&gt;sshfs&lt;/code&gt;
und &lt;code&gt;mergerfs&lt;/code&gt; installiert sein.&lt;/p&gt;
&lt;p&gt;Weiterhin müssen die Dateien &lt;code&gt;.bash_profile&lt;/code&gt; und &lt;code&gt;.bash_logout&lt;/code&gt; entsprechend
auf dem entfernten Host wie folgt angepasst werden.&lt;/p&gt;
&lt;p&gt;Hier die zusätzlichen Zeilen für profile:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;ss -lnt | grep 2222 &amp;gt; /dev/null &amp;amp;&amp;amp;\
    test -d /tmp/n_$USER || mkdir -p /tmp/n_$USER &amp;amp;&amp;amp;\
    test -d $HOME/m || mkdir -p $HOME/m &amp;amp;&amp;amp;\
    echo &amp;quot;mount remote HOME at /tmp/n_$USER:&amp;quot; &amp;amp;&amp;amp;\
    sshfs -o Port=2222,UserKnownHostsFile=/dev/null,idmap=user $USER@localhost: /tmp/n_$USER &amp;amp;&amp;amp;\
    echo &amp;quot;merge remote and local HOME at $HOME/m:&amp;quot; &amp;amp;&amp;amp;\
    mergerfs /tmp/n_$USER=RO:$HOME $HOME/m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dies hängt das Heimatverzeichnis des lokalen Nutzers im entfernten Rechner
ein und führt beide zusammen.&lt;/p&gt;
&lt;p&gt;Damit auch beim Abmelden nichts übrig bleibt, wird vorher aufgeräumt. Hier die
Zeilen füt logout:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;mountpoint -q $HOME/m &amp;amp;&amp;amp; fusermount -zu $HOME/m
mountpoint -q /tmp/n_$USER &amp;amp;&amp;amp; fusermount -zu /tmp/n_$USER
rmdir $HOME/m
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Nutzung&lt;/h2&gt;
&lt;p&gt;Um das Konstrukt zu aktivieren vermindet man sich per ssh mit ein paar zusätzlichen Parametern:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;ssh -R 2222:localhost:22 user@remote
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn man den Host-Schlüssel akzeptiert und sich passend auf seinen Rechner
&lt;em&gt;rückwärts&lt;/em&gt; anmeldet, findet man seine lokalen Dateien in &lt;code&gt;/tmp/n_$USER&lt;/code&gt; und
die Kombination aus lokal und remote in &lt;code&gt;$HOME/m&lt;/code&gt;, wobei mit dem oberen Script
die lokalen Dateien nur lesend eingehängt sind.&lt;/p&gt;
&lt;p&gt;Ein &lt;code&gt;df -h&lt;/code&gt; gibt eine Überblick über die Mountpunkte und den Speicherplatz.&lt;/p&gt;
&lt;h2&gt;Verbesserungen&lt;/h2&gt;
&lt;p&gt;Sind die passenden Schlüssel hinterlegt und angegeben, kann der Anmeldevorgang
vereinfacht werden.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.cat-v.org/plan_9/"&gt;plan9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/libfuse/sshfs"&gt;sshfs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/trapexit/mergerfs"&gt;mergerfs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>Konfiguration Epson EcoTank ET-2820 unter Debian Bullseye und Mint Vanessa</title><link href="http://www.mueslihq.de/techblog/epson_et-2820__debian_bullseye/" rel="alternate"/><updated>2022-08-11T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:e1c5764e-7c30-3eee-b721-f0967e891273</id><content type="html">&lt;p&gt;Unter Debian Bullseye und Linux Mint 21 (Vanessa) ist leider kein Druckertreiber für den Epson EcoTank ET-2820 vorhanden. Epson bietet zwar auf seiner &lt;a href="https://download.ebz.epson.net/dsc/search/01/search/?OSC=LX"&gt;Treiberhomepage&lt;/a&gt; Treiber für Linux an. Leider lassen sich die Debian Pakete aufgrund fehlender Abhängigkeiten nicht installieren. Ebenfalls war aus den Sourcen, nicht wie angegeben, ein Paket zu bauen. 
Auch existiert auch kein Backport Paket für diesen Drucker.&lt;/p&gt;
&lt;p&gt;Es ist jedoch möglich den Drucker über ein paar Tricks in Betrieb zu nehmen.
Es ist möglich über den Umweg von Debian unstable die ppd-Datei zu diesem Drucker zu extrahieren und abzuspeichern. Diese kann dann im Bullseys und Vanessa verwendet werden.&lt;/p&gt;
&lt;h2&gt;Vorbereitungen mit Debian unstable&lt;/h2&gt;
&lt;p&gt;Der Drucker wird unter Debian unstable supported. Zuallererst ist der filter &lt;code&gt;epson-escpr-wrapper&lt;/code&gt;zu installieren.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt install printer-driver-escpr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sucht man den Drucker über "Neu Drucker suchen", so kann man den Drucker konfigurieren. Im Verzeichnis &lt;code&gt;/etc/cups/ppd&lt;/code&gt; entsteht dann eine ppd-Datei. Diese speichert man sich für die weitere Konfiguration ab und zippt sie mit gzip.&lt;/p&gt;
&lt;h2&gt;Konfiguration Bullseye oder Vanessa&lt;/h2&gt;
&lt;p&gt;Hier ist ebenfalls das Paket &lt;code&gt;printer-driver-escpr&lt;/code&gt; zu installieren.&lt;/p&gt;
&lt;p&gt;Nun ist die URL des Druckers zu bestimmen. Befindet man sich im gleichen Netzwerksegment, kann man diese mittels &lt;code&gt;ippfind&lt;/code&gt; bestimmen&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@tinkerbell:~# ippfind  --ls
ipp://EPSON09E721.local:631/ipp/print idle accepting-jobs none
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;De String &lt;code&gt;EPSON09E721.local&lt;/code&gt; kann durch die IP-Adresse des Druckers ersetzt werden um den Drucker auch aus anderen Netzwerksegmenten im Heimnetzwerk erreichbar zu machen.&lt;/p&gt;
&lt;p&gt;Nun startet man die CUPS-Administrationsseite über &lt;a href="http://localhost:631"&gt;http://localhost:631&lt;/a&gt; und:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fügt einen neuen Drucker hinzu&lt;/li&gt;
&lt;li&gt;verwendet das  "Internet Printing Protocol (ipps)"&lt;/li&gt;
&lt;li&gt;wählt als Verbindung &lt;code&gt;ipps://IP-DES-DRUCKERS:631/ipp/print&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;gibt Name, Beschreibung und Ort an.&lt;/li&gt;
&lt;li&gt;fügt die bereitgestellte ppd.gz-Datei hinzu.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Danach ist der Drucker auch unter Bullseye oder Vanessa betriebsbereit.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://localhost:631"&gt;CUPS-Adminseite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://download.ebz.epson.net/dsc/search/01/search/?OSC=LX"&gt;https://download.ebz.epson.net/dsc/search/01/search/?OSC=LX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://debianforum.de/forum/viewtopic.php?t=175581"&gt;https://debianforum.de/forum/viewtopic.php?t=175581&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxquestions.org/questions/linux-hardware-18/using-printer-epson-xp-205-cups-says-filter-failed-4175611247/"&gt;https://www.linuxquestions.org/questions/linux-hardware-18/using-printer-epson-xp-205-cups-says-filter-failed-4175611247/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serverfault.com/questions/222706/how-do-i-enable-cups-browsing-across-a-network"&gt;https://serverfault.com/questions/222706/how-do-i-enable-cups-browsing-across-a-network&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://debianforum.de/forum/viewtopic.php?t=135777"&gt;https://debianforum.de/forum/viewtopic.php?t=135777&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>ssh-keygen als Werkzeug zum signieren</title><link href="http://www.mueslihq.de/techblog/ssh_sign/" rel="alternate"/><updated>2022-04-09T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:8fd5dd3f-48db-3739-b069-db8b7275d90d</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Um die Unversehrtheit einer Nachricht/Datei zu überprüfen zu können, kann man
diese digital unterschreiben (signieren). Diese Signatur wird aus dem privaten
Schlüssel des Senders und der Nachricht selbst vom Sender erstellt. Der
Empfänger dieser Nachricht kann dann mit dem öffentlichen Schlüssel des Senders
die Unversehrtheit prüfen. Klassisch wird hier &lt;code&gt;gnupg&lt;/code&gt; oder ssl als Quelle der
Schlüssel verwendet, was aber nicht immer zur Verfügung steht. Alternativ ist
nun auch openssh in der Lage, die ssh-Schlüssel dafür zu verwenden. Dies ist
sehr vorteilhaft, denn ssh ist quasi überall in der Standardinstallation
vorhanden und der Schlüsselaustausch ist erprobt.&lt;/p&gt;
&lt;h2&gt;Vorbereitung&lt;/h2&gt;
&lt;p&gt;Als erstes benötigt man natürlich das Schlüsselmaterial. Dies lässt sich mit
&lt;code&gt;ssh-keygen -t ed25519&lt;/code&gt; leicht erzeugen, bzw. kann natürlich das für die
normale &lt;code&gt;ssh&lt;/code&gt; Nutzung vorhandene Material verwendet werden.&lt;/p&gt;
&lt;p&gt;Die Dateien werden, wenn nicht anders angegeben, im Verzeichnis &lt;code&gt;.ssh&lt;/code&gt; des
Heimatverzeichnisses des Nutzers erstellt.&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;ls .ssh

id_ed25519
id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Signieren&lt;/h2&gt;
&lt;p&gt;Für das Signieren wie auch später für das Überprüfen wird auch &lt;code&gt;ssh-keygen&lt;/code&gt;
verwendet. Im folgenden Script ist die Verwendung beispielhaft dargelegt.&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;#!/bin/sh

if [ $# -ne 2 ]; then
    echo &amp;quot;$0 privkey file&amp;quot;
    exit 1
else
    ssh-keygen -Y sign -f &amp;quot;$1&amp;quot; -n file &amp;quot;$2&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Es werden zwei Parameter erwartet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;der Pfad zum privaten Schlüssel, mit dem signiert werden soll&lt;/li&gt;
&lt;li&gt;die Datei, von welcher die Signatur erstellt werden soll&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hier ein Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./sshsign ~/.ssh/id_ed25519 ~/eine_datei
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nach dem der Aufruf erfolgt ist, wird eine neue Datei mit der Endung &lt;code&gt;.sig&lt;/code&gt; und
dem ursprünglichen Dateipfad und Namen erzeugt. Im Fall des Beispiels also
&lt;code&gt;~/eine_datei.sig&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Diese beiden Dateien können nun dem Empfänger zur Verfügung gestellt werden und
dieser kann die Echtheit mit unseren öffntlichen Schlüssel überprüfen.&lt;/p&gt;
&lt;h2&gt;Überprüfen der Signatur&lt;/h2&gt;
&lt;p&gt;Um die Signatur überprüfen zu können, ist noch etwas Vorbereitungsarbeit auf der
Empfängerseite notwendig, denn es muss eine Datei vorhanden sein, wo die
zulässigen Unterzeichner von Nachrichten mit ihren öffentlichen Schlüsseln
hinterlegt sind. Als Beispiel verwenden wir hier die Datei
&lt;code&gt;~/.ssh/allowed_signers&lt;/code&gt;. Der Aufbau ist einfach und auch in den man-Seiten von
&lt;code&gt;ssh-keygen&lt;/code&gt; mit Beispielen beschrieben.&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-bash"&gt;
cat ~/.ssh/allowed_signers

# ein Komentar
alice@local.local ssh-ed25519 AAAA...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Im Prinzip steht hier eine Zuordnung: Name öffentlicher Schlüssel. Mit dem
folgenden Script kann nun die Echtheit überprüft werden.&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-shell"&gt;#!/bin/sh

if [ $# -ne 2 ]; then
    echo &amp;quot;$0 email content-file&amp;quot;
    exit 1
else
    ssh-keygen -Y verify -f ~/.ssh/allowed_signers -I &amp;quot;$1&amp;quot; -n file -s &amp;quot;$2.sig&amp;quot; &amp;lt; &amp;quot;$2&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Auch hier sind zwei Parrameter nötig:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;eine Email, dies ist der Name, der in der Datei &lt;code&gt;~/.ssh/allowed_signers&lt;/code&gt;
verwendet wird (Schlüsselzuordnung)&lt;/li&gt;
&lt;li&gt;die Datei, mit dem Inhalt des Senders&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Das Script erwartet auch die Datei mit der Signatur an dem Ort, wo die
eigentliche Datei zu finden ist, das sie den gleich Namen trägt und die Endung
&lt;code&gt;.sig&lt;/code&gt; hat.&lt;/p&gt;
&lt;p&gt;Hier wieder ein Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./sshverify alice@local.local ~/eine_datei
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Je nach dem ob die Signatur gültig ist oder nicht, kommt nun die passende
Nachricht.&lt;/p&gt;
</content></entry><entry><title>ssh Zugang via Keycloak absichern</title><link href="http://www.mueslihq.de/techblog/ssh-keycloak/" rel="alternate"/><updated>2021-12-27T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:6dac4f73-bea6-36f1-96d8-493f4e8a5c65</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Für den sicheren ssh Zugang zu einem Server im Internet ist die
Authentifizierung via PublicKey angeraten. Jeder User kann die berechtigten
Schlüssel erst einmal selbst verwalten, womit es jedoch für den Admin schwer zu
kontrollieren ist, wer hier Zugang hat. Zwar kann man dies durch eine zentrale
Schlüssel-Verwaltung umgehen, muss dies dann aber für jeden Host separat
pflegen.&lt;/p&gt;
&lt;p&gt;Das hier vorgestellte Verfahren nutzt zusätzlich zum Schlüssel eine externe
Web-Applikation, um einen weitern Faktor zu erzeugen. Dies Web-Applikation
authentifiziert nun ihrerseits den User über Keycloak. Damit steht eine
zentrale Quelle für die Authentifizierung verschiedener Dienste zur Verfügung.
Die Quellen für Server und Client stehen unter
&lt;a href="https://pf4sh.eu/git/pulux/c1r1r"&gt;1&lt;/a&gt; zur Verfügung&lt;/p&gt;
&lt;h2&gt;Keycloak&lt;/h2&gt;
&lt;p&gt;Das grundlegende Setup will ich hier nicht weiter erläutern.&lt;/p&gt;
&lt;p&gt;Für die Web-App benötigen wir einen neuen Client mit der Rücksprungadresse der
Web-App z.B. &lt;code&gt;https://my.c1r1-server.de/cr/kc/callback/*&lt;/code&gt; und den
Credentials. Diese sind für die Serverkonfiguration nötig.&lt;/p&gt;
&lt;h2&gt;Server Setup&lt;/h2&gt;
&lt;p&gt;Der Server &lt;code&gt;r1.py&lt;/code&gt; sollte über eine TLS geschützte Verbindung mit einem
gültigen Domain-Namen eingerichtet werden. Hier bietet sich z. B. &lt;code&gt;nginx&lt;/code&gt; als
proxy an.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;location /cr {
proxy_pass http://127.0.0.1:5000;
proxy_read_timeout 90;

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;

proxy_http_version 1.1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Server selbst kann als normaler User betrieben werden. Dafür
werden die Dateien &lt;code&gt;r1.py&lt;/code&gt;, &lt;code&gt;static\*&lt;/code&gt;, &lt;code&gt;telmplates\*&lt;/code&gt; und &lt;code&gt;keycloak.json&lt;/code&gt;
benötigt. Da die Software in Python geschrieben ist, werden die Module &lt;code&gt;Flask&lt;/code&gt;,
&lt;code&gt;gevent&lt;/code&gt; und &lt;code&gt;keycloak&lt;/code&gt; benötigt.&lt;/p&gt;
&lt;p&gt;In die Datei &lt;code&gt;keycloak.json&lt;/code&gt; wird der Keycloak-Server, die Rücksprung-Adresse
der Web-App, die Credentials und der Token für die Client Authentifizierung
eingetragen.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
    "realm": "apps",
    "auth-server-url": "https://a-keycloak-server.org/auth",
    "resource": "ssh-c1r1-auth",
    "verify-token-audience": true,
    "callback_uri": "https://my.c1r1-server.de/cr/kc/callback",
    "ptoken": "the-client-token",
    "credentials": {
      "secret": "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
    },
    "confidential-port": 0,
    "policy-enforcer": {}
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Danach kann der Server gestartet werden und stellt seinen Dienst
unter dem angegebenen Port bzw. unter der SubUrl &lt;code&gt;/cr&lt;/code&gt; des Servers zur
Verfügung.&lt;/p&gt;
&lt;h2&gt;Client Setup&lt;/h2&gt;
&lt;p&gt;Der Client ist hier der ssh-Server, auf den man sich einloggen möchte.&lt;/p&gt;
&lt;p&gt;Die Quellen gibt es wieder unter &lt;a href="https://pf4sh.eu/git/pulux/c1r1r"&gt;1&lt;/a&gt;.
Nach dem Übersetzen des Clients &lt;code&gt;c1&lt;/code&gt; wird dieser mit der Konfiguration in das
passende Verzeichnis kopiert und die Konfiguration angepasst.&lt;/p&gt;
&lt;p&gt;Hier muss der bei Server-Konfiguration verwendete Token und die Adresse der
Web-App angegeben werden.&lt;/p&gt;
&lt;p&gt;Nun wird die Datei &lt;code&gt;/etc/pam.d/sshd&lt;/code&gt; um folgende Zeile erweitert:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;auth sufficient pam_exec.so expose_authtok seteuid quiet stdout /etc/c1s1/c1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Für die User, die sich so anmelden sollen, wird kein Passwort vergeben und
ihr public-key wird in die Datei &lt;code&gt;.ssh/authorized_keys&lt;/code&gt; eingetragen. Zusätzlich wird
die sshd Konfiguration um einen Mach-Block für den User erweitert.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ChallengeResponseAuthentication yes
Match User username1
        PasswordAuthentication yes
        AuthenticationMethods publickey,keyboard-interactive
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dem Server selbst wird die Challenge Response Authentifizierung erlaubt.&lt;/p&gt;
&lt;h2&gt;Betrieb&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Der User meldet sich mit seinem Schlüssel am ssh-Server an und bekommt den
Passwort-Promt gezeigt. Hier wird nichts eingegeben und nur mit Enter
bestätigt.&lt;/li&gt;
&lt;li&gt;Als Ausgabe erhält man die URI der Web-App mit dem Einmalschlüssel.&lt;/li&gt;
&lt;li&gt;Diese Adresse wird geöffnet. Hier wird man zu dem Keycloak-Server
weitergeleitet und nach erfolgreicher Anmeldung wieder zur Web-App zurück
geschickt. Dabei wird der nun einmalig gültige Token hinter dem : angezeigt.&lt;/li&gt;
&lt;li&gt;Dieser wird nun im erneut angezeigten Passwort-Prompt eingegeben.&lt;/li&gt;
&lt;li&gt;Wenn dieser gültig ist, wird der User angemeldet.&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>Mail Reputation (postfix, SPF, DKIM)</title><link href="http://www.mueslihq.de/techblog/mail_reputation/" rel="alternate"/><updated>2021-08-30T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:b731442e-53d1-3058-88f7-378068e44438</id><content type="html">&lt;p&gt;Wer einen eigenen Mailserver betreibt kennt das Problem. Einige Mailprovider lehnen die
Annahme der Mails dieses Mailservers ab. Oft werden E-Mails einfach anhand der IP-Adresse
gebounced. Ich habe die Erfahrung gemacht, dass anscheinend ganze Netzblöcke gebounced
werden, weil sich darin IP-Adressen befinden, von denen eventuell schon mal  SPAM versendet
wurde.&lt;/p&gt;
&lt;p&gt;Hier hilft es nur aufmerksam den Logfile des eigenen Mailservers zu beobachten und sich
bei Bounces an den Postmaster des anderen Mailserves zu wenden.&lt;/p&gt;
&lt;p&gt;Was man selbst machen kann ist die Reputation des eigenes Mailservers zu erhöhen. Hierzu gibt es ein Reihe
von Maßnahmen. Diese seien am Beispiel der Domain any2any.de hier erläutert. Der
MTA (MailTransportAgent) dieser Domain ist ein  postfix unter Debian 11.&lt;/p&gt;
&lt;h2&gt;Einfache Maßnahmen&lt;/h2&gt;
&lt;p&gt;Der zu konfigurierende Mailserver sollte natürlich im Nameservice als Mailexchanger
eingetragen sein:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@heinzelmann:~$ dig +short any2any.de  MX
10 mail.hottemax.org.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die IP-Adressen sind reverse zum gleichen Namen aufzulösen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@heinzelmann:~$ dig +short -t A mail.hottemax.org
94.130.57.108

rocholl@heinzelmann:~$ dig +short -t AAAA mail.hottemax.org
2a01:4f8:c0c:81d7::1

rocholl@heinzelmann:~$ dig +short -x  94.130.57.108
mail.hottemax.org.

rocholl@heinzelmann:~$ dig +short -x  2a01:4f8:c0c:81d7::1
mail.hottemax.org.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Mailname des Mailsserver sollte ebenfalls der des Mailsexchangers sein&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ehli8:~# cat /etc/mailname 
mail.hottemax.org

root@ehli8:~# grep myorigin /etc/postfix/main.cf
myorigin = /etc/mailname
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ein transportverschlüssltes Versenden der E-Mail kann bei gewissen "Gegenstellen"
ebenfalls erforderlich sein. Ich verwende einfach letsencrypt Zertifikate. Die notwendigen
Einstellungen in der &lt;code&gt;/etc/postfix/main.cf&lt;/code&gt; sind&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;smtpd_tls_cert_file=/etc/letsencrypt/live/mail.hottemax.org/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.hottemax.org/privkey.pem
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Konfiguration kann man testen mit&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;openssl s_client -crlf -connect mail.hottemax.org:465
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;SPF - Sender Policy Framework&lt;/h2&gt;
&lt;p&gt;Die Verwendung von SPF ist für die Verbesserung der Reputation sehr zu empfehlen.&lt;/p&gt;
&lt;p&gt;Hierzu ist im DNS-Zone der Domain ein Record vom Type TXT zu erstellen, der die IP-Adressen des Mailserver enthält.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@heinzelmann:~$ dig +short TXT any2any.de 
"v=spf1 mx ip4:94.130.57.108 ip6:2a01:4f8:c0c:81d7::1 -all
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;DKIM - DomainKeys Identified Mail&lt;/h2&gt;
&lt;p&gt;Etwas aufwändiger ist die Konfiguration von DKIM. Diese soll an der Beispieldoman any2any.de gezeigt werden.
Zuerst erfolgt die Installation der opendkim-Pakete&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt install opendkim opendkim-tools
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann sind die Schlüssel zu erstellen. Eigentümer sollte der opendkim-Nutzer sein. Wenn mehrere Domains mit DKIM versorgt werden sollen, ist es m.E. sinnvoll eigene Verzeichnisse zu erstellen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir  /etc/dkimkeys/any2any.de
chown opendkim:opendkim /etc/dkimkeys/any2any.de
chmod 700 /etc/dkimkeys/any2any.de

Dann können die Zertifikate erstellt werden. Als Zahl kann eine beliebige Zahl gewählt werden z.B. die alte PLZ von Münster:

sudo -u opendkim opendkim-genkey -D /etc/dkimkeys/any2any.de -d any2any.de -s 4400
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Man erhält ein Schlüsselpaar. Der öffentliche Teil des Schlüssels sieht wie folgt aus:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat dkimkeys/any2any.de/4400.txt 
4400._domainkey IN  TXT ( "v=DKIM1; h=sha256; k=rsa; "
      "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx5vnqsfJyWKKnTtHviUJqrBF6jDDGe81S+UFli5s50epu4m1YWD27wE1MFABWk2M6LfZCKdYG8VT5SDHBRtPv/W4cWvr+0UfZpmwh6/D8gYTgtZi1Eqyg9c1uhYbZTsw6iBZ147+x1K7ciaKy4naU1lRvqzLRjTSFSjtP2dD8kLE/NhGpE5D8ZPcCq2fu+5u9ZV6aoU1ZbEaEm"
      "n7vRx148oZekG8AaqbDPNlm2dDiXQBRpoXTZbLKwj3IAv/y2ejWVi5mtZdGARsvzzwOrJoTJImGV6zdgDMi3M0x9ADAUpvCEkNjEVjSpaksSFB5xmUw2eutv739eyGO+r3yShL2QIDAQAB" )  ; ----- DKIM key 4400 for any2any.de
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dieser ist im Nameservice einzutragen. Es gibt einige Checker im Internet mit denen das Format des Eintrages gecheckt werden kann (z.B. &lt;a href="https://mxtoolbox.com/dkim.aspx"&gt;https://mxtoolbox.com/dkim.aspx&lt;/a&gt;). Es hat sich gezeigt, dass der Check nur erfolgreich war, wenn der Eintrag in einer Zeile als ein String angegeben wurde:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@heinzelmann:~$ dig +short TXT 4400._domainkey.any2any.de
"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx5vnqsfJyWKKnTtHviUJqrBF6jDDGe81S+UFli5s50epu4m1YWD27wE1MFABWk2M6LfZCKdYG8VT5SDHBRtPv/W4cWvr+0UfZpmwh6/D8gYTgtZi1Eqyg9c1uhYbZTsw6iBZ147+x1K7ciaKy4naU1lRvqzLRjTSFSjtP2dD8kLE/NhGpE5D8ZP" "cCq2fu+5u9ZV6aoU1ZbEaEmn7vRx148oZekG8AaqbDPNlm2dDiXQBRpoXTZbLKwj3IAv/y2ejWVi5mtZdGARsvzzwOrJoTJImGV6zdgDMi3M0x9ADAUpvCEkNjEVjSpaksSFB5xmUw2eutv739eyGO+r3yShL2QIDAQAB"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn die Konfiguration im Nameservice abgeschlossen ist, kann man sich an die opendkim/postfix Konfiguration machen. 
In &lt;code&gt;/etc/opendkim.conf&lt;/code&gt; sind folgende Einträge anzupassen bzw. hinzuzufügen.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;KeyTable                /etc/dkimkeys/keytable
SigningTable refile:/etc/dkimkeys/signingtable
InternalHosts refile:/etc/dkimkeys/trustedhosts


# Socket for the MTA connection (required). If the MTA is inside a chroot jail,
# it must be ensured that the socket is accessible. In Debian, Postfix runs in
# a chroot in /var/spool/postfix, therefore a Unix socket would have to be
# configured as shown on the last line below.
#Socket                 local:/run/opendkim/opendkim.sock
Socket                  inet:8891@localhost
#Socket                 inet:8891
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In der keytable wird der Pfad zu den Schlüsseln konfiguriert:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ehli8:~# head /etc/dkimkeys/keytable  
4400._domainkey.any2any.de any2any.de:4400:/etc/dkimkeys/any2any.de/4400.private
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die signingtable konfiguriert&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ehli8:~# /etc/dkimkeys/signingtable 
# Domain yourdomain.org
*@any2any.de 4400._domainkey.any2any.de
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In trustedhostd habe ich die IP-Adresse des Mailservers angeben:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ehli8:~# /etc/dkimkeys/trustedhosts
==&amp;gt; /etc/dkimkeys/trustedhosts &amp;lt;==
127.0.0.1
94.130.57.108/32
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In postfix ist opendkim wie folgt einzubinden:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ehli8:~# tail -n 5 /etc/postfix/main.cf
## DKIM configuration
milter_default_action = accept
milter_protocol   = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = $smtpd_milters
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nach Restart der Dienste werden die ausgehende Mails signiert. Im Maillogfile findet sich:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Aug 30 11:15:20 ehli8 opendkim[658]: B3F551F7B4: DKIM-Signature field added (s=4400, d=any2any.de)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Es ist zu empfehlen zu checken, ob auch korrekt signiert wurde. Hier leistet der &lt;a href="https://www.appmaildev.com/de/dkim"&gt;Checker von appmaildev&lt;/a&gt; gute Dienste.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.appmaildev.com/de/dkim"&gt;Check der mit DKIM-signierten Mail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mxtoolbox.com/dkim.aspx"&gt;DKIM-Record-Check&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arnowelzel.de/dkim-mit-postfix-und-opendkim"&gt;https://arnowelzel.de/dkim-mit-postfix-und-opendkim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://de.wikipedia.org/wiki/DomainKeys"&gt;https://de.wikipedia.org/wiki/DomainKeys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://de.wikipedia.org/wiki/Sender_Policy_Framework"&gt;https://de.wikipedia.org/wiki/Sender_Policy_Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dmarcian.com/dkim-inspector/"&gt;https://dmarcian.com/dkim-inspector/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kofler.info/dkim-konfiguration-fuer-postfix/"&gt;https://kofler.info/dkim-konfiguration-fuer-postfix/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.google.com/a/answer/174124?hl=de"&gt;https://support.google.com/a/answer/174124?hl=de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/opendkim"&gt;https://wiki.debian.org/opendkim&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.dialog-mail.com/email-blog/2017/20170902_spf-und-dkim-schritt-fuer-schritt.php"&gt;https://www.dialog-mail.com/email-blog/2017/20170902_spf-und-dkim-schritt-fuer-schritt.php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.heise.de/ct/artikel/E-Mails-signieren-mit-DKIM-221505.html?seite=all"&gt;https://www.heise.de/ct/artikel/E-Mails-signieren-mit-DKIM-221505.html?seite=all&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxbabe.com/mail-server/setting-up-dkim-and-spf"&gt;https://www.linuxbabe.com/mail-server/setting-up-dkim-and-spf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.netways.de/blog/2017/11/15/postfix-spf-dkim-und-dmarc/"&gt;https://www.netways.de/blog/2017/11/15/postfix-spf-dkim-und-dmarc/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.postfix.org/MILTER_README.html"&gt;http://www.postfix.org/MILTER_README.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mediatemple.net/community/products/dv/115003098072/how-do-i-add-a-dkim-txt-record-to-my-domain"&gt;Länge des Eintrages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://superuser.com/questions/1042496/linux-tool-to-check-dkim-signed-emails"&gt;Check der DKIM-Signatur im Client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mail-tester.com"&gt;Neuer schöner Mailtrester&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://de.ssl-tools.net/mailservers"&gt;SSL-Check von Mailservern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>ssh als VPN Tool</title><link href="http://www.mueslihq.de/techblog/ssh_vpn/" rel="alternate"/><updated>2021-04-07T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:a1c402ab-6c7d-3e5a-9919-0612e23a3df1</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Manchmal möchte man auf einen entfernten Rechner sicher zugreifen, dafür gibt
es natürlich &lt;code&gt;ssh&lt;/code&gt;. Was aber tun, wenn die IP-Adresse des Rechners nicht bekannt
und dieser hinter einer Firewall und/oder zusätzlich einem NAT-Gateway steckt?
Dann könnte man natürlich über einen externen Anbieter eine Verbindung aufbauen
z.B. ein VPN, aber dafür muss normalerweise UDP-Trafik erlaubt sein und man
muss dem Anbieter vertrauen. Gut wäre eine Lösung, wo auf einem Remote-Rechner
keine Geheimnisse hinterlegt sein müssen.&lt;/p&gt;
&lt;h2&gt;Die Idee&lt;/h2&gt;
&lt;p&gt;Da &lt;code&gt;ssh&lt;/code&gt; ein flexibles Werkzeug ist und auch für das Weiterleiten von TCP-Ports
verwendet werden kann, kann ich auch entfernte Dienste an anderen Orten
verfügbar machen. Durch die sichere Authentifizierung mittels Schlüssel ist auch
Fremden der Zugriff nicht möglich und diese Schlüssel können mit den
eingebauten Funktionen selbst erzeugt und verteilt werden.&lt;/p&gt;
&lt;p&gt;Dafür läuft auf dem Remote-Client ein "Service", der den für den Dienst nötigen
Port an einen Server mit dem festen Namen oder IP weiterleitet. Wenn wir nun
diesen Port des Servers nutzen oder selbst weiterleiten, dann haben wir Zugriff
auf den Dienst des Remote-Client.&lt;/p&gt;
&lt;h2&gt;Server Setup&lt;/h2&gt;
&lt;p&gt;Auf den Server ist eigentlich keine weitere Einstellung nötig, außer um das
System robuster zu gestalten, sollten in der Datei &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; die
folgenden Parameter gesetzt werden:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ClientAliveInterval 60
ClientAliveCountMax 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dies bewirkt, dass erst nach 180s die Verbindung abgebaut würde, womit kurze
Netzunterbrechungen toleriert werden.&lt;/p&gt;
&lt;p&gt;Sinnvoll ist evtl. auch ein separater Nutzer, der für die Anmeldung der
Remote-Clients verwendet wird. Damit kann man dann später gezielt nach der
Verbindung suchen und diese z.B. abbauen, falls doch mal etwas nicht wie
gewünscht funktioniert. Hierzu ein Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Match User emrcall
    AllowTcpForwarding yes
    X11Forwarding no
    PermitTunnel no
    GatewayPorts no
    AllowAgentForwarding no
    ClientAliveInterval 60
    ClientAliveCountMax 3
    ForceCommand date
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dieser User benötigt noch nicht einmal ein Passwort, da ja die Anmeldung
ausschließlich per ssh-key erfolgt. Je nach System ist dies aber für User ohne
Passwort gesperrt. Eine Änderung im 2. Feld der Datei &lt;code&gt;/etc/shadow&lt;/code&gt; von ! auf x
behebt dies.&lt;/p&gt;
&lt;h2&gt;Remote Client Setup&lt;/h2&gt;
&lt;p&gt;Dieser Rechner soll einen oder mehrere Dienste auf dem Server anbieten. Dafür
nutzen wir &lt;code&gt;ssh&lt;/code&gt; mit der Option &lt;code&gt;-R&lt;/code&gt; (Remote Port Forwarding). Das Programm
sollte in einer Dienstüberwachung wie z. B. &lt;code&gt;runit&lt;/code&gt; laufen, denn die Verbindung
kann durch verschiedene Situationen abbrechen und damit endet auch die
Programmausführung.&lt;/p&gt;
&lt;p&gt;Zuerst erstellen wir ein neues ssh-Schüsselpaar für diese Aufgabe, wobei wir
den Öffentlichen-Schüssel in die Datei &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; des für diesen
Zweck verwendeten Users eintragen. Die Datei darf nur vom User beschreibbar
sein (0600).&lt;/p&gt;
&lt;p&gt;Mit dem oben angegebenen Beispiel-Setup sollte eine ssh-Verbindung mit dem
gerade erzeugten Key die Uhrzeit des Servers liefern.&lt;/p&gt;
&lt;p&gt;Um unsere Portweiterleitung als Dienst laufen zu lassen, bietet es sich an, die
Parameter in ein kleines Script zu schreiben, z. B. nach &lt;code&gt;/etc/rpfs.sh&lt;/code&gt;. Hier
ein Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh

ssh -q -o ConnectTimeout=45 -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
    -N -R 4022:localhost:22 -i /home/user/.ssh/id_rsa_ermcall \
    ermcall@server_ip_or_name
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dieses Script machen wir mit &lt;code&gt;chmod +x /etc/rpfs.sh&lt;/code&gt; ausführbar. Wenn wir dies
nun direkt starten, können wir auf den Server über Port 4022 auf den ssh-Server
des Remote-Clients zugreifen. Eine Anmeldung sollte aber nicht möglich sein, da
auf dem Server nicht die notwendigen Schlüssel verfügbar sind und auch nicht
sein sollten (Private Schlüssel sollten auch Privat bleiben).&lt;/p&gt;
&lt;p&gt;Damit dies auch immer zur Verfügung steht, erstellen wir dafür einen Dienst,
bei runit mit:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /etc/sv/emrcall
cd /etc/sv/emrcall
echo -en '#!/bin/sh\n\nexec /etc/rpfs.sh' &amp;gt; run
chmod +x run
ln -s /run/runit/supevrise-emrcall supervise
cd
ln -s /etc/sv/emrcall /var/service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Je nach System können die Pfade etwas anders sein, schaut einfach in die
Dokumentation.&lt;/p&gt;
&lt;p&gt;Frank hat stattdessen eine Service-Definition erstellt, was natürlich auch
funktioniert.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=Keeps a tunnel to 'server_ip_or_name' open
After=network-online.target ssh.service

[Service]
User=user
Environment="AUTOSSH_PORT=0"
Environment="AUTOSSH_GATETIME=0"
RestartSec=30
Restart=always

ExecStart=/usr/bin/autossh -NT -o "ExitOnForwardFailure=yes" \
        -R 4022:localhost:22 -p 22 -l ermcall server_ip_or_name \
        -i /home/user/.ssh/id_rsa_ermcall
ExecStop=killall -s KILL autossh
TimeoutStopSec=10

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Client Setup&lt;/h2&gt;
&lt;p&gt;Auf dem Rechner, wo wir diesen Dienst nutzen wollen, benötigen wir das
Schlüsselmaterial, um auf unseren Remote-Client zugreifen zu können. Der
passende Öffentliche Schlüssel muss auf dem Remote-Client eingetragen sein.
Sind diese Vorarbeiten erledigt, bietet es sich an, in der lokalen ssh
Konfiguration, normalerweise unter &lt;code&gt;~/.ssh/config&lt;/code&gt; dafür einen eignen Eintrag zu
erstellen. Hier ein Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Host server1
Hostname server_ip_o_name
IdentityFile ~/.ssh/id_rsa_for_server_access
User server_user_account

Host rhost1
Hostname localhost
Port 4022
IdentityFile ~/.ssh/id_rsa_for_remote_client
ProxyCommand ssh -W %h:%p server1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun ist mit &lt;code&gt;ssh rhost1&lt;/code&gt; ein Zugriff auf den entfernten Rechner möglich und
wir haben nirgends auf dem Weg Geheimnisse hinterlegen müssen.&lt;/p&gt;
&lt;h3&gt;Bemerkung&lt;/h3&gt;
&lt;p&gt;Es können über eine Verbindung natürlich auch mehre Ports freigegeben oder
auch bezogen werden.&lt;/p&gt;
&lt;p&gt;In sehr seltenen Fällen und bei einer nach jetzigen Erfahrungen sehr schlechten
Netzverbindung, geht evtl. die Weiterleitung kaputt und die Client-Seite
beendet nicht das Programm. Dann ist es notwendig, den passenden &lt;code&gt;sshd&lt;/code&gt; Prozess
serverseitig zu beenden.&lt;/p&gt;
</content></entry><entry><title>ssh Zugang via totp absichern</title><link href="http://www.mueslihq.de/techblog/ssh_totp/" rel="alternate"/><updated>2021-02-27T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:f052b740-61a1-3c50-a068-e9e246eacda0</id><content type="html">&lt;h1&gt;Einleitung&lt;/h1&gt;
&lt;p&gt;Für den sicheren ssh Zugang zu einem Server im Internet ist die
Authentifizierung via PublicKey empfehlenswert. Was aber, wenn man nicht nur
selbst Zugang benötigt, sondern auch anderen diesen gewähren muss? Mann könnte
dafür auch mehrere Authentifizierungsmethoden in Reihe schalten mit
&lt;code&gt;AuthenticationMethods publickey,keyboard-interactive&lt;/code&gt; in der
&lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;, was aber bedeutet, dass man das UserPassword teilen
muss. Auch die Vartiante mit dem &lt;a href="https://github.com/google/google-authenticator-libpam"&gt;totp-pam
Modul&lt;/a&gt; erfordert dies.&lt;/p&gt;
&lt;h2&gt;Lösung&lt;/h2&gt;
&lt;p&gt;Die publickey Authentifizierungsmethode bietet die Möglichkeit jedem Schlüssel
weitere Optionen mitzugeben. Auch kann angegeben werden, welches Programm
auszuführen ist. Hier kann z.B. ein Wrapper stehen, welcher zuerst nach
erfolgreicher Prüfung eine Shell öffnet. Wenn dieses Programm nun zuerst ein
z.B. zeitabhängigens Einmalpasswort prüft und dieser abhängig vom Schlüssel ist,
muss kein Geheimnis mehr geteilt werden.&lt;/p&gt;
&lt;h2&gt;Client Setup&lt;/h2&gt;
&lt;p&gt;Auf der Client-Seite benötigen wir eine Anwendung, welche aus dem
Server-Geheimnis einen zeitabhängiges Einmalpasswort berechnet. Unter einem
Linux-System ist dies das Program &lt;code&gt;oathtool&lt;/code&gt;. Für aktuelle Mobilgeräte gibt es
dafür Apps, die dies ermöglichen.&lt;/p&gt;
&lt;p&gt;Um eine sichere Speicherung unter Linux zu ermöglichen, bietet sich das Programm
&lt;code&gt;pass&lt;/code&gt; an, was auf &lt;code&gt;gnupg&lt;/code&gt; aufbaut. Ein &lt;code&gt;pass insert totp/servise/user&lt;/code&gt; sichert
das Geheimnis. Um das Einmalpasswort zu erhalten, reicht dann ein &lt;code&gt;watch -n 10
"oathtool --totp -b $(pass totp/service/user)"&lt;/code&gt; aus.&lt;/p&gt;
&lt;h2&gt;Server Setup&lt;/h2&gt;
&lt;p&gt;Um das Geheimnis zu erzeugen, verwenden wir &lt;code&gt;google-authenticator&lt;/code&gt; aus dem
Paket &lt;code&gt;google-authenticator-libpam&lt;/code&gt;. Dieses speichert die Einstellungen in
&lt;code&gt;$HOME\.google-authenticator&lt;/code&gt;. Weiterhin benötigen wir noch &lt;code&gt;oathtool&lt;/code&gt; aus dem
Paket &lt;code&gt;oath-toolkit&lt;/code&gt; und ein Shell-Script.&lt;/p&gt;
&lt;p&gt;Zuerst erzeugen wir das Geheimnis und verschieben dann die Datei z.B. nach
&lt;code&gt;$HOME/.key1&lt;/code&gt;. Das Geheimnis, welches sich in die erste Zeile befindet, bzw.
der erzeugte QR-Code oder die gesamte Ausgabe muss nun zu dem Client
transferiert werden.&lt;/p&gt;
&lt;p&gt;Dann muss das Script:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-bash"&gt;#!/bin/sh

SK=$1
if [ -x /bin/bash ]; then
    S=/bin/bash
else
    S=/bin/sh
fi
if [ -f $HOME/.$SK ]; then
    echo -n &amp;quot;key: &amp;quot;
    read key
    keyl=$(oathtool --totp -b $(head -1 $HOME/.$SK))
    if [ $key = $keyl ]; then
        exec $S -il
    else
        echo &amp;quot;auth failed&amp;quot;
        exit 1
    fi
else
    echo &amp;quot;secret not found&amp;quot;
    exit 2
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;nach &lt;code&gt;/usr/local/bin/bashWc&lt;/code&gt; kopiert und ausführbar gemacht werden.&lt;/p&gt;
&lt;p&gt;Der Zugangsschlüssel welcher nun zusätzlich mit dem TOTP Passwort geschützt
werden soll, wird durch bearbeiten der Datei &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; durch
folgenden Eintrag am Anfang der Zeile ergänzt (bis zu ssh-rsa):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;command="/usr/local/bin/bashWc key1" ssh-rsa AAA...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun wird bei jedem Anmelden mit diesem Schlüssel zusätzlich nach dem aktuell
gültigen Einmalpasswort gefragt.&lt;/p&gt;
&lt;h2&gt;Verbesserungen&lt;/h2&gt;
&lt;p&gt;Das Script erlaubt im Moment nicht das per ssh übergebene Kommandos ausgeführt
werden, was aber für diesen Zugang auch evtl. nicht nötig ist. Durch eine
Scriptanpassung ist dies aber möglich.&lt;/p&gt;
&lt;h3&gt;Bemerkung&lt;/h3&gt;
&lt;p&gt;Gegen Vandalismus hilft dies natürlich nicht, denn nach erfolgreichen Login,
kann der angemeldete natürlich auch Anpassungen vornehmen. Wenn dies ein
Problem ist, sollte z.B. eine zentral gesteuerte Authentifizierung in Betracht
gezogen werden.&lt;/p&gt;
&lt;h3&gt;Schlüsseldatei unter admin Kontrolle&lt;/h3&gt;
&lt;p&gt;Um ein manipulieren der ssh Authentifierungsdatei durch den User zu unterbinden,
kann diese durch anpassen der Datei &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; aus dem User-Verzeichnis
in ein zentrales Verzeichnis verlegt werden.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;AuthorizedKeysFile /etc/ssh/authorized_keys/%u&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;damit steht für jeden User weiterhin eine eigene Datei zur Verfügung, welche
nun aber z.B. root gehört. Hier sind die Rechte auf 644 zu setzen.&lt;/p&gt;
&lt;p&gt;Mit diesen Setup kann die Datei aber auch weiterhin dem entsprehenden User
gehören, womit er diese dann auch selbst abpassen kann.&lt;/p&gt;
</content></entry><entry><title>Kurznachricht Ende zu Ende verschüsselt mit ssh Schlüsseln</title><link href="http://www.mueslihq.de/techblog/msg_e2e/" rel="alternate"/><updated>2021-01-01T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:c8d079da-05a8-3c50-b819-5684dccc5d89</id><content type="html">&lt;h3&gt;Einleitung&lt;/h3&gt;
&lt;p&gt;Kennst du das auch, du möchtest mit jemanden sicher eine Nachricht austauschen
und dafür nur vorhandene und erprobte Programme verwenden. Hier gibt es
eine einfache Lösung die ssh-Schlüssel verwendet.&lt;/p&gt;
&lt;p&gt;Alles was dazu nötig ist, ist im allgemeinen schon installiert, &lt;code&gt;openssh&lt;/code&gt; und
&lt;code&gt;libressl&lt;/code&gt; oder &lt;code&gt;openssl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ihr braucht nun nur noch von dem vorhandenen Öffentlichen-Schlüssel eures
Kommunikationspartner einen Schlüssel im PEM-Format zu erzeugen und diesen für
die Verschlüsselung zu verwenden.&lt;/p&gt;
&lt;p&gt;Die Entschüsselung erfolgt mit dem Privaten-Schlüssel des Partners.&lt;/p&gt;
&lt;p&gt;Hier ein Beispiel-Script was das Vorgehen verdeutlicht. Es erzeugt die
pem-Datei und zeigt euch wie ver- und entschlüsselt wird.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh

if [ $# -lt 1 ]; then
    KEY=id_rsa
else
    KEY=$1
fi

if [ -f ~/.ssh/"$KEY".pub ]; then
    if [ ! -f ~/.ssh/"$KEY".pub.pem ]; then
        ssh-keygen -f ~/.ssh/"$KEY".pub -e -m PKCS8 &amp;gt; ~/.ssh/"$KEY".pub.pem
    fi
fi

if [ -f ~/.ssh/$KEY ] || [ -f ~/.ssh/$KEY.pub.pem ]; then
    echo "echo msg | openssl rsautl -encrypt -pubin -inkey ~/.ssh/$KEY.pub.pem &amp;gt; /tmp/emsg"
    echo "cat /tmp/emsg | openssl rsautl -decrypt -inkey ~/.ssh/$KEY"
else
    echo $KEY not found
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Einschränkung&lt;/h3&gt;
&lt;p&gt;Eine Einschränkung bei dieser Methode ist, dass die Nachricht recht kurz und
die maximale Nachrichtenlänge vom Schüsseltyp abhäbgig ist.&lt;/p&gt;
&lt;p&gt;Eine Nachrichtengröße von 244 Bytes sollten mit aktuellen Schlüsseln aber immer
gehen.&lt;/p&gt;
&lt;h3&gt;Erweiterung&lt;/h3&gt;
&lt;p&gt;Die Methode kann z.B. auch dafür verwendet werden um z.B. einen symetrichen
Schlüssel sicher auszutauschen, womit sich dann auch größere Blöcke ver- und
entschlüssel lassen.&lt;/p&gt;
&lt;h2&gt;UPDATE 2022&lt;/h2&gt;
&lt;p&gt;Es gibt &lt;a href="https://github.com/FiloSottile/age"&gt;age&lt;/a&gt; was auch ssh-Schlüssel
verwenden kann.&lt;/p&gt;
</content></entry><entry><title>Desaster-Recovery auf Dateibasis</title><link href="http://www.mueslihq.de/techblog/desaster-recovery/" rel="alternate"/><updated>2020-10-01T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:3530c825-9d82-3b67-8272-5e3ae374cc81</id><content type="html">&lt;p&gt;Irgendwann ist es soweit. Die alte Hardware ist kaputt gegangen und ist auch nicht mehr verfügbar. Oder man möchte seine gute alte normalo Festplatte gegen eine schicke neue SSD austauschen, ohne das System nochmal neu konfigurieren zu müssen.&lt;/p&gt;
&lt;p&gt;Daher muss ein Desaster Recovery aus dem Backup her. Auch hier gilt wieder: Kein Backup, keine Gnade.&lt;/p&gt;
&lt;p&gt;Waschzettel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatisiertes Backup auf einem anderen Rechner erstellen (z.B. mit backuppc)&lt;/li&gt;
&lt;li&gt;Booten der reparierten Hardware mit einem Linux-Live-Sytem (z.B. Ubuntu Studio)&lt;/li&gt;
&lt;li&gt;Benötigte Software in die Live-Distribution installieren (z.B. openssh-server)&lt;/li&gt;
&lt;li&gt;Partitionieren der neuen Festplatten, Anlegen von Filesystemen&lt;/li&gt;
&lt;li&gt;Zurückkippen des Filesystembackups&lt;/li&gt;
&lt;li&gt;Booten der Installation mit einem Rettungssystem&lt;/li&gt;
&lt;li&gt;Neuschreiben des grub bootloaders&lt;/li&gt;
&lt;li&gt;Neuerstellung des initrd&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Weitere Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Installation auf nicht identischer Hardware möglich&lt;/li&gt;
&lt;li&gt;Änderung des Filesystemlayouts möglich&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Restore in der Praxis&lt;/h2&gt;
&lt;p&gt;Ich nutze einen Lenovo X220 als Home-Theatre-PC. Betriebssystem ist Debian Sid. Dieser soll nun eine schnelle SSD bekommen.&lt;/p&gt;
&lt;p&gt;Generell ist jedes Live-System der gleichen Prozessorarchitektur geeignet den Restore vorzunehmen. Idealerweise sollte man im Live-System Pakete nachinstallieren können, falls was fehlt. Ich habe meinen Praxistest mit Ubuntu Studio gemacht.&lt;/p&gt;
&lt;h3&gt;Vorbereitung des Systems&lt;/h3&gt;
&lt;p&gt;Natürlich baut man zuallererst die neue Festplatte ein.&lt;/p&gt;
&lt;p&gt;Dann erstellt man aus dem ISO-Image einen bootfähigen USB-Stick. Dazu steckt man einen neuen Stick in eine USB-Buchse; so kann man unter /var/log/messages den Gerätenamen ablesen, die der USB-Stick auf dem lokalen Gerät hat. Hat das Betriebssystem den Stick schon gemountet, so ist der erst zu umounten. Also z.B.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;umount /dev/sdd1
dd if=ubuntustudio-20.04.1-dvd-amd64.iso of=/dev/sdd BS=4M &amp;amp;&amp;amp; sync
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mit dem Stick kann nun der zu restoredende PC ins Live-System gebootet werden. Der PC sollte am Netz sein.&lt;/p&gt;
&lt;p&gt;Um einen Zugriff von außen zu ermöglichen, ist der sshd nach zu installieren:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt install openssh-server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun kann man sich ein neues Passwort setzen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo passwd ubuntu-studio
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die notwendigen ssh-keys des backuppc Users sind nun in /root/.ssh/authorized_keys abzulegen.&lt;/p&gt;
&lt;p&gt;Nun kann die neue Festplatte mit fdisk analog zur alten partitioniert werden. Dabei können die Partitionen auch größer sein. Das Ergebnis war bei mir z.B.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ubuntu-studio:~# fdisk  -l /dev/sda
Festplatte /dev/sda: 340 GiB, 365072220160 Bytes, 713031680 Sektoren
Festplattenmodell: QEMU HARDDISK
Einheiten: Sektoren von 1 * 512 = 512 Bytes
Sektorgröße (logisch/physikalisch): 512 Bytes / 512 Bytes
E/A-Größe (minimal/optimal): 512 Bytes / 512 Bytes
Festplattenbezeichnungstyp: dos
Festplattenbezeichner: 0x1da5c32d

Gerät      Boot    Anfang      Ende  Sektoren Größe Kn Typ
/dev/sda1            2048 104859647 104857600   50G 83 Linux
/dev/sda2       104859648 121636863  16777216    8G 82 Linux Swap / Solaris
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jetzt werden Swap-Bereich und Filesystem angelegt. Die UUID brauchen wir später für die Konfiguration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkfs.ext4  /dev/sda1
root@ubuntu-studio:~# blkid  /dev/sda1
/dev/sda1: UUID="8949eac2-7675-4795-b0cd-d1b5d63f7eef" TYPE="ext4" PARTUUID="79b53b8c-01"


mkswap  /dev/sda2
Auslagerungsbereich Version 1 wird angelegt, Größe = 9,8 GiB (10511405056 Bytes)
keine Bezeichnung, UUID=922eaf0e-06cf-4480-9dc6-53b78b66037e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann kann die neue Partition gemounted werden:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir /restore
mount /dev/sda1 /restore
mkdir /restore/proc /restore/sys /restore/run
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nach dem Mounten erfolgt ein Restore vom backuppc Server auf diese Partition.&lt;/p&gt;
&lt;p&gt;&lt;img src="BackupPC_Restore_Options_for_piepmatz_fritz_box.png" class="img-fluid" alt="BackupPC Restore Options"&gt;&lt;/img&gt;&lt;/p&gt;
&lt;h3&gt;Neuschreiben des Bootloaders&lt;/h3&gt;
&lt;p&gt;Nach beendetem Filetransfer ist die Datei /etc/fstab anzupassen. Es sind die UUIDs anzugeben, die man mittels &lt;code&gt;blkid&lt;/code&gt; ermittelt hat.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@ubuntu-studio:~# grep UUID /etc/fstab 
# device; this may be used with UUID= as a more robust way to name devices
UUID=8949eac2-7675-4795-b0cd-d1b5d63f7eef /               ext4    errors=remount-ro 0       1
UUID=922eaf0e-06cf-4480-9dc6-53b78b66037e none            swap    sw              0       0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann ist der Bootloader in einer chroot-Umgebung neu zu schreiben:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mount -o bind /dev /restore/dev
mount -o bind /sys /restore/sys
mount -t proc /proc /restore/proc
chroot /restore
grub-mkconfig &amp;gt; /boot/grub/grub.cfg
grub-install /dev/sda
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nach dem Reboot ins gerestorte System ist noch die Resume-UUID neu schreiben&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo "RESUME=UUID=922eaf0e-06cf-4480-9dc6-53b78b66037e" &amp;gt; /etc/initramfs-tools/conf.d/resume
update-initramfs -u
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Schon hat man ein schönes neues System und die Sicherheit, dass das Backup funktioniert. Ein Restore von LVM- und Crypted-LVM-Systemen ist ebenfalls möglich und auch getestet. Das wäre Themen für einen weiteren Tech-Post.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://ubuntustudio.org/"&gt;http://ubuntustudio.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://backuppc.github.io/backuppc"&gt;https://backuppc.github.io/backuppc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.ubuntuusers.de/LUKS/Partitionen_verschl%C3%BCsseln/"&gt;https://wiki.ubuntuusers.de/LUKS/Partitionen_verschl%C3%BCsseln/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.ubuntuusers.de/topic/swap-und-die-initramfs-tools/"&gt;https://forum.ubuntuusers.de/topic/swap-und-die-initramfs-tools/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>Worth Noting aka "Die Zettel" (1)</title><link href="http://www.mueslihq.de/techblog/worth-noting-1/" rel="alternate"/><updated>2020-09-23T00:00:00Z</updated><author><name>Simon Wilper</name></author><id>urn:uuid:61abbcbe-7449-3c79-aaeb-bd62d5267aec</id><content type="html">&lt;p&gt;Unter der Kategorie &lt;em&gt;Worth Noting aka "Die Zettel"&lt;/em&gt; fasse ich kleine Hilfen,
Shell-Einzeiler für Alltagsaufgaben zusammen, für die es nicht lohnt, einen
eigenenen Artikel zu schreiben.&lt;/p&gt;
&lt;h2&gt;SSH-Public-Key verloren?&lt;/h2&gt;
&lt;p&gt;Man hat irgendwo einen SSH-Key gefunden, hat aber den Public dazu verloren:&lt;/p&gt;
&lt;p&gt;Key prüfen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; ssh-keygen -l -f my_ssh_key
3072 SHA256:vRT5nxCugl0qFFGglWmPzGFeYLWBBB77GspSUvK8iuM reese@cyberdyne.net (RSA)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ausgabe in Public Key umleiten:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; ssh-keygen -y -f my_ssh_key &amp;gt; my_ssh_key.pub
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Alle Dateien im aktuellen Verzeichnis klein schreiben&lt;/h2&gt;
&lt;p&gt;Das &lt;code&gt;coreutils&lt;/code&gt;-Programm &lt;code&gt;tr&lt;/code&gt; bietet hier die praktischen Makros &lt;code&gt;[:upper:]&lt;/code&gt; und
&lt;code&gt;[:lower:]&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for i in *; do
  mv "$i" "$(echo $i | tr [:upper:] [:lower:])"
done
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Audio aus Video extrahieren&lt;/h2&gt;
&lt;p&gt;Und das ohne &lt;code&gt;ffmpeg&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mplayer -ao pcm:fast:file=audio.wav -vo null -vc null video.webm
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;vc&lt;/strong&gt; (video codec) und &lt;strong&gt;vo&lt;/strong&gt; (video output) wird hier auf &lt;code&gt;null&lt;/code&gt; gesetzt, da
wir nur am Audio interessiert sind.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ao&lt;/strong&gt; (audio output) wird auf PCM gesetzt, was die Audio-Spur auf direktem
Weg in die Datei &lt;code&gt;audio.wav&lt;/code&gt; umleitet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>QEMU Primer Part 1</title><link href="http://www.mueslihq.de/techblog/qemu_primer_pt1/" rel="alternate"/><updated>2020-09-20T00:00:00Z</updated><author><name>Simon Wilper</name></author><id>urn:uuid:09b6d16f-8cb9-392e-a162-5d2f07190435</id><content type="html">&lt;h2&gt;Darum geht es&lt;/h2&gt;
&lt;p&gt;QEMU, kurz für &lt;em&gt;Quick Emulator&lt;/em&gt; ist wohl eine der verbreitesten
Betriebssystemvirtualisierungslösungen für Linux.
Es gibt verschiedenste Gründe, warum man eine virtuelle Maschine einsetzen
möchte: Man ist Anbieter von vServern, der Kollege kommt mit einem Programm um
die Ecke, das &lt;em&gt;man sofort ausprobieren&lt;/em&gt; müsse, weil es ja so toll ist -- läuft aber nur
unter Windows, oder die &lt;a href="https://winfuture.de/news,89825.html"&gt;Wetter-App vom Pariser Flughafen läuft nur unter Windows
3.11&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;QEMU installieren&lt;/h2&gt;
&lt;p&gt;Da es sich ja hierbei um ein recht populäres Paket handelt, sollte es jedem
gängigen Paketmanager bekannt sein. Meistens heisst es &lt;code&gt;qemu&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Einfaches Beispiel: Alpine Linux installieren&lt;/h2&gt;
&lt;p&gt;Das schöne an QEMU ist ja, dass man sich mit zwei Befehlen eine komplette
Linux-Maschine erstellen kann. Wir nehmen hier im Beispiel mal ein x86_64 Alpine Linux, da
das Install-ISO nur 40M groß ist, einen Shell-Installer hat und ziemlich schnell
ist:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; wget http://dl-cdn.alpinelinux.org/alpine/v3.12/releases/x86_64/alpine-virt-3.12.0-x86_64.iso

2020-09-20 13:40:16 (9,81 MB/s) - ‘alpine-virt-3.12.0-x86_64.iso’ saved [41943040/41943040]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Virtuelle Festplatte erstellen:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; qemu-img create -f qcow2 alpine-vm.img 4G
Formatting 'alpine-vm.img', fmt=qcow2 cluster_size=65536 compression_type=zlib size=4294967296 lazy_refcounts=off refcount_bits=16
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Installation des Gast-Systems Starten:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;qemu-system-x86_64 --enable-kvm -m 2G \
  -cdrom alpine-virt-3.12.0-x86_64.iso -boot order=d \
  -drive file=alpine-vm.img,format=qcow2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Und es sollte automatisch vom ISO-Image gebootet werden, so dass man die
Installation ganz normal über &lt;code&gt;setup-alpine&lt;/code&gt; oder bei anderen Distributionen
über den grafischen Installer durchführen kann.&lt;/p&gt;
&lt;p&gt;Was haben die beiden obigen Befehle nun bewirkt?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;qemu-img create&lt;/code&gt; haben wir mitgeteilt, dass es ein Festplatten-Image der Größe
4GB mit dem Namen &lt;code&gt;alpine-vm.img&lt;/code&gt; anlegen soll. Dabei haben wir über den
Parameter &lt;code&gt;-f&lt;/code&gt; das Format &lt;code&gt;qcow2&lt;/code&gt; angegeben. Lässt man den Parameter weg, wird
&lt;code&gt;raw&lt;/code&gt; angenommen.&lt;/p&gt;
&lt;p&gt;Der offensichtlichste Unterschied zwischen den Formaten ist, dass bei &lt;code&gt;raw&lt;/code&gt; die
4GB schon vorher reserviert werden und der Platz vom Host-System nicht mehr
benutzt werden kann. Das klingt erstmal nach Platzverschwendung, kann aber zur
besseren IO-Performance führen. Bei &lt;code&gt;qcow2&lt;/code&gt; (Copy on Write) wird der Platz beim
Host erst belegt, wenn er auch wirklich benötigt wird.&lt;/p&gt;
&lt;p&gt;Ist man z.B. geneigt, seine VMs in der Azure-Cloud laufen zu lassen,
funktioniert dies nur mit dem Format &lt;code&gt;raw&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Der zweite Befehl startet nun die VM und bootet vom Install-ISO. Die
Kommandozeilenparameter bewirken dabei Folgendes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;enable-kvm&lt;/strong&gt; sorgt hier für Aktivierung der &lt;em&gt;kernel-bassed Virtual
Machine&lt;/em&gt;-Module in Form von &lt;code&gt;kvm&lt;/code&gt; und z.B. bei Intel-Prozessoren &lt;code&gt;kvm_intel&lt;/code&gt;.
Bei allen gängigen Distributionen sollten diese Module mit dem
Linux-Kernel-Paket kompiliert worden sein und der Einsatz dieser Option sollte
out-of-the-box funktionieren.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;m 2G&lt;/strong&gt; Hauptspeicher für den Gast auf 2GB setzen. Verzichtet man auf diese
Option, werden standardmäßig nur 128M zugeteilt. Das kann schonmal zu langen
Gesichtern führen, wenn der Installer die initramdisk entpacken möchte und sich
mit einer Kernel-Panic verabschiedet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cdrom alpine-virt-3.12.0-x86_64.iso&lt;/strong&gt; Ein CD-ROM-Device mit diesem ISO
simulieren&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;boot order=d&lt;/strong&gt; Von CD-ROM booten&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;drive file=alpine-vm.img,format=qcow2&lt;/strong&gt; Das oben angelegte Festplatten-Image
einbinden&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nach der Installation des Gastsystems sollte man die Optionen &lt;code&gt;boot order&lt;/code&gt; und
&lt;code&gt;cdrom&lt;/code&gt; weglassen, damit es auch von dem Festplatten-Image bootet.&lt;/p&gt;
&lt;p&gt;QEMU versucht, einige Dinge automatisch zu konfigurieren, damit man sofort
loslegen kann. So auch das Netzwerk. Es wird sofort eine Netzwerkkarte angelegt,
die vom internen DHCP-Server mit einer Adresse aus dem &lt;code&gt;10.0.2.0/24&lt;/code&gt;-Netz
versorgt wird und zum aktiven Host-NIC via NAT verbunden wird -- man kommt also
aus dem Gast direkt ins gleiche Netzwerk wie der Host. Mehr zur
Netzwerkkonfiguration, z.B. mit &lt;a href="https://github.com/virtualsquare/vde-2"&gt;VDE2&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;GUI&lt;/h2&gt;
&lt;p&gt;Jetzt ist das Ganze natürlich so schon lauffähig, nur bei einer Vielzahl von
virtuellen Maschinen ist das Handling und Management nur über
QEMU-Kommandozeilenparameter ziemlich umständlich. Dazu wollen wir uns in diesem
Teil den &lt;code&gt;virt-manager&lt;/code&gt; anschauen, einer grafischen Benutzeroberfläche, die auf
&lt;code&gt;libvirt&lt;/code&gt; aufbaut, etwa folgendermaßen:&lt;/p&gt;
&lt;p&gt;&lt;img src="libvirt.svg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;libvirt&lt;/code&gt;, von Redhat entwickelt, ist eine abstrahierende Bibliothek, um auf
verschiedene Virtualisierungsplattformen zuzugreifen, nicht nur KVM. Zudem
wartet sie mit jeder Menge Bindings für jede Menge verschiedener
Programmiersprachen auf.&lt;/p&gt;
&lt;p&gt;Auch hier sollte es für die gängigen Distributionen kein Problem sein, die
erforderlichen Pakete zu installieren:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;libvirt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;virt-manager&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Danach ist der Daemon &lt;code&gt;libvirtd&lt;/code&gt; zu starten. Je nach Distribution oder
Supervision-Daemon kann das unterschiedlich ausfallen. Bei &lt;code&gt;systemd&lt;/code&gt; z.B.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# &amp;gt; systemctl start libvirtd
# &amp;gt; systemctl status libvirtd
● libvirtd.service - Virtualization daemon
     Loaded: loaded (/usr/lib/systemd/system/libvirtd.service; disabled; vendor preset: disabled)
     Active: active (running) since Sun 2020-09-20 21:31:42 CEST; 19s ago
TriggeredBy: ● libvirtd-ro.socket
             ● libvirtd.socket
             ● libvirtd-admin.socket
       Docs: man:libvirtd(8)
             https://libvirt.org
   Main PID: 8940 (libvirtd)
      Tasks: 17 (limit: 32768)
     Memory: 10.6M
     CGroup: /system.slice/libvirtd.service
             └─8940 /usr/bin/libvirtd --timeout 120

Sep 20 21:31:42 archeus systemd[1]: Started Virtualization daemon.
# &amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jetzt sollte man den &lt;code&gt;virt-manager&lt;/code&gt; normal starten können und folgendes Fenster
zu sehen bekommen:&lt;/p&gt;
&lt;p&gt;&lt;img src="virt-manager-1.png" /&gt;&lt;/p&gt;
&lt;p&gt;Da wir eine vorhandene Maschine hinzufügen wollen -- und zwar jene, die wir
gerade im obigen Verlauf des Artikels erstellt haben -- müssen wir erst einen
Storage Pool anlegen. Dazu Rechtsklick auf den Eintrag &lt;em&gt;QEMU/KVM&lt;/em&gt; und dann auf
&lt;em&gt;Details&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="virt-manager-2-storage.png" /&gt;&lt;/p&gt;
&lt;p&gt;Unten über das &lt;em&gt;+&lt;/em&gt;-Symbol einen neuen Pool anlegen, Zielverzeichnis angeben und
schon sollte unser &lt;code&gt;alpine-vm.img&lt;/code&gt; in der Liste auftauchen.&lt;/p&gt;
&lt;p&gt;Nun können wir mit dem ersten Icon der Toolbar im Hauptfenster eine neue VM
hinzufügen. Ein Wizard sollte sich öffnen:&lt;/p&gt;
&lt;p&gt;&lt;img src="new-vm-step-1.png" /&gt;&lt;/p&gt;
&lt;p&gt;Option &lt;em&gt;Import existing Disk Image&lt;/em&gt; wählen und auf Weiter.&lt;/p&gt;
&lt;p&gt;&lt;img src="new-vm-step-2.png" /&gt;&lt;/p&gt;
&lt;p&gt;Image aus dem Pool auswählen und unten ein System eintragen.&lt;/p&gt;
&lt;p&gt;&lt;img src="new-vm-step-3.png" /&gt;&lt;/p&gt;
&lt;p&gt;Speicher und Anzahl CPUs zuweisen.&lt;/p&gt;
&lt;p&gt;Im nächsten Schritt vergeben wir nur noch einen aussagekräftigen Namen und
bestätigen mit &lt;em&gt;Finish&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Schon wird die VM automatisch gestartet:&lt;/p&gt;
&lt;p&gt;&lt;img src="virt-manager-vm-running.png" /&gt;&lt;/p&gt;
</content></entry><entry><title>Policykit</title><link href="http://www.mueslihq.de/techblog/policykit/" rel="alternate"/><updated>2020-09-16T00:00:00Z</updated><author><name>Simon Wilper</name></author><id>urn:uuid:887d3f4a-fca9-39c9-9877-8e4395039d26</id><content type="html">&lt;h2&gt;Policykit - sudo on Steroids&lt;/h2&gt;
&lt;p&gt;Wir kennen alle &lt;code&gt;sudo&lt;/code&gt; oder &lt;code&gt;doas&lt;/code&gt; -- Programme, die es erlauben,
Befehle als ein anderer Benutzer auf einem System, meist als root,
auszuführen.  Auf einem Einzelplatzsystem ist man
auch oft auch gerne geneigt, seinen Benutzer in die Gruppe "wheels" zu
packen und in der &lt;code&gt;/etc/sudoers&lt;/code&gt; der Gruppe das Attribut &lt;code&gt;:NOPASSWD&lt;/code&gt; zu
verpassen und man kann durch einfaches Hinzufügen von sudo alle Befehle
ausführen. "sudo make me a sandwich" halt.&lt;/p&gt;
&lt;p&gt;Jetzt ist es vielleicht notwendig, bestimmte Befehle nur mit bestimmten
Kommandozeilenargumenten zu für bestimmte Benutzer zu erlauben. Da kann
man mit sudo und doas bei komplexeren Setups schon an seine Grenzen
kommen.&lt;/p&gt;
&lt;h2&gt;Ein erstes einfaches Beispiel&lt;/h2&gt;
&lt;p&gt;Die Regeln ("rules") werden in &lt;code&gt;/etc/polkit-1/rules.d&lt;/code&gt; in
&lt;code&gt;*.rules&lt;/code&gt;-Dateien gespeichert. Die Regeln werden dort als
JavaScript-Programme -- ja, wirklich! -- abgespeichert.&lt;/p&gt;
&lt;p&gt;Für den Benutzer "john" wollen wir nun erlauben, alle Befehle als
Benutzer "root" auszuführen. Wir editieren die Datei
&lt;code&gt;/etc/pokit-1/rules.d/10-example.rules&lt;/code&gt; und fügen ein:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;polkit.addRule( function(action, subject) {
  if ( action.id == "org.freedesktop.policykit.exec" ) {

    if (subject.user == "john") {
      return polkit.Result.YES;
    }

  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun speichern wir und der PolicyKit-Dienst wird die Änderungen sofort
detektieren und sollte sie sofort aktivieren.&lt;/p&gt;
&lt;p&gt;In diesem Beispiel passiert nun Folgendes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Es wird die Funktion &lt;code&gt;addRule&lt;/code&gt; des globalen &lt;code&gt;polkit&lt;/code&gt;-Objektes
aufgerufen. &lt;code&gt;polkit&lt;/code&gt; muss nicht erstellt oder initialisiert werden,
es existiert bereits in diesem Kontext.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Eine anonyme Funktion mit zwei Parametern &lt;code&gt;action&lt;/code&gt; und &lt;code&gt;subject&lt;/code&gt;
wird übergeben.
&lt;code&gt;subject&lt;/code&gt; beinhaltet Informationen über den Prozess, der überprüft
werden soll. Darin gibt es z.B. das Attribut &lt;code&gt;user&lt;/code&gt;, das den
Benutzernamen hält. Dieser kann innerhalb der Funktion auf einen
bestimmten Wert überprüft werden.
&lt;code&gt;action&lt;/code&gt; beinhaltet nur ein Attribut &lt;code&gt;id&lt;/code&gt;, was das Zielprogramm
identifiziert, das ausgeführt werden soll, in diesem Fall
&lt;code&gt;policykit.exec&lt;/code&gt; was durch den Befehl &lt;code&gt;pkexec&lt;/code&gt; verkörpert wird.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Treffen also beide if-Anweisungen zu, wird der Wert polkit.Result.YES
zurückgegeben, andernfalls nichts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Probieren wir das Ganze einmal aus -- erst ohne die Einträge in der
rules-Datei. Wir versuchen, als User "john" den Inhalt des
Verzeichnisses &lt;code&gt;/root&lt;/code&gt; aufzulisten:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; pkexec ls /root
==== AUTHENTICATING FOR org.freedesktop.policykit.exec ====
Authentication is needed to run `/usr/bin/ls' as the super user
Authenticating as: John Connor (john)
Password:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wir werden nach einem Passwort gefragt. Fügen wir die obigen Zeilen einer
&lt;code&gt;rules&lt;/code&gt;-Datei in &lt;code&gt;/etc/polkit-1/rules.de&lt;/code&gt; hinzu:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; pkexec ls /root
dir1  dir2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das funktioniert schonmal.&lt;/p&gt;
&lt;h2&gt;Ein etwas komplexeres Beispiel&lt;/h2&gt;
&lt;p&gt;Jetzt möchten wir gerne die Befehle für den Butzer john auf einige wenige
einschränken. Z.B. auf &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt; und &lt;code&gt;less&lt;/code&gt;. Dazu kommt das &lt;code&gt;action&lt;/code&gt;-Object
mit einer Methode &lt;code&gt;lookup&lt;/code&gt;. Je nachdem was für eine action-Instanz wir hier
vorliegen haben, ist das interne Dictionary mit den entsprechenden Werten
befüllt. Hier, bei &lt;code&gt;action.id&lt;/code&gt; &lt;code&gt;org.freedesktop.policykit.exec&lt;/code&gt; hält der Key
&lt;code&gt;command_line&lt;/code&gt; die Zeichenkette des Befehls, die unmittelbar auf &lt;code&gt;pkexec&lt;/code&gt; folgt.
Somit können wir die erlaubten Befehle mit einem Zweizeiler eingrenzen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;polkit.addRule( function(action, subject) {
  if ( action.id == "org.freedesktop.policykit.exec" ) {
    let allowed_programs = ["/usr/bin/ls", "/usr/bin/cat", "/usr/bin/less"];
    let program = action.lookup("command_line").split(" ")[0]

    if (subject.user == "sxw" &amp;amp;&amp;amp; allowed_programs.includes(program)) {
      return polkit.Result.YES;
    } else {
      return polkit.Result.NO;
    }       
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hier sehen wir zudem noch, dass wir im &lt;code&gt;else&lt;/code&gt;-Zweig ein explizites
&lt;code&gt;polkit.Result.NO&lt;/code&gt; zurückgeben. Das verhindert, dass polkit den Passwort-Prompt
für Root-Authentifizierung anzeigt, so dass der Benutzer den Befehl bei Eingabe
des Passwortes dennoch ausführen könnte.&lt;/p&gt;
&lt;p&gt;Jetzt können wir das ganze auch nur zwischen 12 und 18 Uhr zulassen. Dank
JavaScript haben wir Zugriff auf die ganze Class-Library:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let hours = new Date().getHours();
if ( hours &amp;lt; 12 || hours &amp;gt;= 19 ) {
  return polkit.Result.NO;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das Ganze kann man dann auch je nach Programm nach Belieben anpassen.&lt;/p&gt;
&lt;p&gt;Beim Entwickeln kann es ganz hilfreich sein, Meldungen in den Log zu schreiben.
Das kann man mit &lt;code&gt;polkit.log("...")&lt;/code&gt; tun. Die Meldungen landen dann im Journal
und können in einer anderen Shell dann mit &lt;code&gt;journalctl -f -u polkit&lt;/code&gt; beobachtet
werden.&lt;/p&gt;
&lt;h2&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Ich weiß, die meisten werden mich jetzt lynchen für einen Artikel im
systemd-Umfeld und dann kommt auch noch JavaScript drin vor. Aber ich kann mir
schon den ein oder anderen Fall vorstellen -- gerade auf Systemen, die von einer
Vielzahl an Benutzern mit unterschiedlichen Admin-Aufgaben frequentiert werden.&lt;/p&gt;
</content></entry><entry><title>Pipman</title><link href="http://www.mueslihq.de/techblog/pipman/" rel="alternate"/><updated>2020-09-13T00:00:00Z</updated><author><name>Simon Wilper</name></author><id>urn:uuid:12aef6e7-63fe-36eb-94f0-8ca2cc8a7f92</id><content type="html">&lt;h2&gt;Darum geht es&lt;/h2&gt;
&lt;p&gt;Man kennt das: Man programmiert eine Python-Anwendung und benötigt
ur-plötzlich Funktionalität eines Python-Moduls, das so speziell ist,
dass es durch den Paketmanager der Distribution nicht bereitgestellt
wird.&lt;/p&gt;
&lt;p&gt;Jetzt gibt es mehrere Möglichkeiten:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;virtualenv aufsetzen, damit die Verwirrung größer wird, welche Pakete
man durch die Distribution nach &lt;code&gt;/usr/lib/.../site-packages&lt;/code&gt;
installiert hat und welche man lokal durch den Python-Paketmanager pip
installiert hat.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;als root pip ausführen, damit man sich &lt;code&gt;/usr/lib/.../site-packages&lt;/code&gt; mit Dateien
vollkantet, die nicht unter Kontrolle des Distributionspaketmanager
stehen...&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;$HOME/.local des Standard-PYTHONPATH nutzen, bringt aber das Gleiche
Ergebnis wie bei einer virtualenv&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Oder...&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Man setzt ein Tool ein, dass einem das Erstellen von
distributionsspezifischen Paketen von Python-Modulen vereinfacht.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Archlinux-User können hier auf das Programm
&lt;a href="https://aur.archlinux.org/packages/pipman-git/"&gt;&lt;code&gt;pipman&lt;/code&gt;&lt;/a&gt; aus dem AUR
zurückgreifen. Einfach den PKGBUILD-Snapshot herunterladen,
&lt;code&gt;makepkg -si&lt;/code&gt; ausführen und schon hat man:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/tmp/pipman-git] &amp;gt; pipman --version
Usage:
    pipman (-h | --help)
    pipman [options] &amp;lt;packages&amp;gt;...
    pipman [options]
[sxw@archeus] [~/tmp/pipman-git] &amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Python-Modul installieren&lt;/h2&gt;
&lt;p&gt;Jetzt kann man ganz entspannt das Python-Modul der Begierde
herunterladen und es wird automatisch ein PKGBUILD mit all den
Informationen, die pip hergibt gefüllt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~] &amp;gt; pipman sysv_ipc
pipman: Preparing virtualenv
pipman: Installing 'sysv_ipc' in virtualenv
Collecting sysv_ipc
  Downloading sysv_ipc-1.0.1.tar.gz (102 kB)
     |████████████████████████████████| 102 kB 1.9 MB/s 
Using legacy 'setup.py install' for sysv-ipc, since package 'wheel' is not installed.
Installing collected packages: sysv-ipc
    Running setup.py install for sysv-ipc ... done
Successfully installed sysv-ipc-1.0.1
pipman: Checking package info
pipman: Generating pkgbuild for sysv_ipc
[sxw@archeus] [~] &amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Und schon wurde ein Verzeichnis &lt;code&gt;python-sysv_ipc&lt;/code&gt; erstellt mit folgender
PKGBUILD:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/python-sysv_ipc] &amp;gt; cat PKGBUILD 
# PKGBUILD generated by pipman
# Python package author: Philip Semanchuk &amp;lt;philip@semanchuk.com&amp;gt;
pkgname=python-sysv_ipc
pkgver=1.0.1
pkgrel=1
pkgdesc="System V IPC primitives (semaphores, shared memory and message queues) for Python"
arch=(any)
url="http://semanchuk.com/philip/sysv_ipc/"
license=(http://creativecommons.org/licenses/BSD/)
makedepends=("python" "python-pip")
build() {
  pip install --no-deps --target="sysv_ipc" sysv_ipc==1.0.1
}
package() {
  sitepackages=$(python -c "import site; print(site.getsitepackages()[0])")
  mkdir -p $pkgdir/"$sitepackages"
  cp -r $srcdir/sysv_ipc/* $pkgdir/"$sitepackages"
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pipman hat soweit möglich alle Felder, die pip bietet übernommen. Jetzt
kann hier wie gewohnt mit &lt;code&gt;makepkg -si&lt;/code&gt; gebaut werden:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/python-sysv_ipc] &amp;gt; makepkg -si
==&amp;gt; Making package: python-sysv_ipc 1.0.1-1 (So 13 Sep 2020 21:58:39 CEST)
==&amp;gt; Checking runtime dependencies...
==&amp;gt; Checking buildtime dependencies...
==&amp;gt; Retrieving sources...
==&amp;gt; Extracting sources...
==&amp;gt; Starting build()...
...
==&amp;gt; Installing package python-sysv_ipc with pacman -U...
loading packages...
resolving dependencies...
looking for conflicting packages...

Package (1)      New Version  Net Change

python-sysv_ipc  1.0.1-1        0,06 MiB

Total Installed Size:  0,06 MiB

:: Proceed with installation? [Y/n] y
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Und fertig:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/python-sysv_ipc] &amp;gt; pacman -Ql python-sysv_ipc
python-sysv_ipc /usr/
python-sysv_ipc /usr/lib/
python-sysv_ipc /usr/lib/python3.8/
python-sysv_ipc /usr/lib/python3.8/site-packages/
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc-1.0.1-py3.8.egg-info/
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc-1.0.1-py3.8.egg-info/PKG-INFO
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc-1.0.1-py3.8.egg-info/SOURCES.txt
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc-1.0.1-py3.8.egg-info/dependency_links.txt
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc-1.0.1-py3.8.egg-info/installed-files.txt
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc-1.0.1-py3.8.egg-info/top_level.txt
python-sysv_ipc /usr/lib/python3.8/site-packages/sysv_ipc.cpython-38-x86_64-linux-gnu.so
&lt;/code&gt;&lt;/pre&gt;
</content></entry><entry><title>Contain</title><link href="http://www.mueslihq.de/techblog/contains/" rel="alternate"/><updated>2020-09-09T00:00:00Z</updated><author><name>Simon Wilper</name></author><id>urn:uuid:0dea4f8f-d671-3d62-829e-c443c0c4b5a2</id><content type="html">&lt;h2&gt;Darum geht es&lt;/h2&gt;
&lt;p&gt;Sie kennen das: Sie setzen auf allen Maschinen eine auf
&lt;a href="https://musl.libc.org/"&gt;musl&lt;/a&gt; basierte Linux-Distribution wie &lt;a href="https://alpinelinux.org/"&gt;Alpine
Linux&lt;/a&gt; ein. Jetzt kommt nun einer ihrer
Kollegen an und möchte unbedingt sein Python-Programm, das
&lt;a href="https://www.tensorflow.org/"&gt;tensorflow&lt;/a&gt;,
&lt;a href="https://keras.io/"&gt;keras&lt;/a&gt; und
&lt;a href="https://opencv.org/"&gt;OpenCV&lt;/a&gt; benötigt.&lt;/p&gt;
&lt;p&gt;Na, Gute Nacht, Marie.&lt;/p&gt;
&lt;p&gt;Falls Sie jetzt auf die Idee kommen sollten alle
Abhängigkeiten für musl zu bauen: Vergessen Sie es. Stattdessen: 
&lt;a href="https://github.com/arachsys/containers"&gt;containers&lt;/a&gt;: &lt;em&gt;Lightweight
containers using Linux user namespaces&lt;/em&gt; -- Für alle, denen
&lt;a href="https://www.docker.com/"&gt;docker&lt;/a&gt; zu 2013 ist und
&lt;a href="https://wiki.archlinux.org/index.php/Systemd-nspawn"&gt;systemd-nspawn&lt;/a&gt; zu viel
systemd. Hier auch mal wieder Dank an Markus, der containers
vorgeschlagen hat. containers macht also nichts anderes als den Inhalt
eines Verzeichnisses als eigenständiges Betriebssystem zu behandeln,
welches auch keinen Zugriff auf die Prozesse des Hostsystems hat.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Unter Archlinux ist
&lt;a href="https://aur.archlinux.org/packages/containers"&gt;containers im AUR&lt;/a&gt; zu
finden, bei
&lt;a href="https://github.com/void-linux/void-packages/tree/master/srcpkgs/containers"&gt;voidlinux&lt;/a&gt;
scheint es eine im offiziellen Repository zu geben. Debian, Ubuntu und
auch Alpine selber gehen leer aus, muss also selber gebaut werden.&lt;/p&gt;
&lt;p&gt;Ist die Installation erfolgt, sollte der Befehl &lt;code&gt;contain&lt;/code&gt; ausgeben:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~] &amp;gt; contain
Usage: contain [OPTIONS] DIR [CMD [ARG]...]
Options:
  -c        disable console emulation in the container
  -g MAP    set the container-to-host GID map
  -i CMD    run a helper child inside the new namespaces
  -n        share the host network unprivileged in the container
  -o CMD    run a helper child outside the new namespaces
  -u MAP    set the container-to-host UID map
GID and UID maps are specified as START:LOWER:COUNT[,START:LOWER:COUNT]...
[sxw@archeus] [~] &amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Usage-Line sagt uns hier ganz klar, dass wir ein Verzeichnis mit dem
System benötigen.&lt;/p&gt;
&lt;h2&gt;Anlegen eines Alpine Rootfs&lt;/h2&gt;
&lt;p&gt;Die Kollegen von Alpinelinux haben das Potential ihrer Distribution als
prädestinierten Kandidaten für Container-System erkannt und bieten uns
ein &lt;a href="https://alpinelinux.org/downloads/"&gt;Mini Root Filesystem&lt;/a&gt; im
Download-Bereich an. Dort laden wir das tar.gz für x86_64 in meinem Fall
herunter und entpacken es.&lt;/p&gt;
&lt;p&gt;Dafür habe ich mir mal ein Verzeichnis erstellt, nach Entpacken sollte
das Ganze dann so aussehen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/my-container] &amp;gt; ls
bin  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[sxw@archeus] [~/my-container] &amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jetzt können wir den container starten indem wir eingeben:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/my-container] &amp;gt; contain -n . /bin/sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wir sehen einen neuen root-Prompt und die Eingabe von &lt;code&gt;ps ax&lt;/code&gt; zeigt
lediglich unsere Prozesse, die nun in einem anderen Namespace laufen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/ # ps ax
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
    2 root      0:00 ps ax
/ #
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der aufmerksame Leser wird die Verwendung von &lt;code&gt;-n&lt;/code&gt; bemerkt haben. Diese
Option aktiviert lediglich die Netzwerkunterstützung und das System im
Container sieht somit die gleichen Network Interfaces wie der Host.&lt;/p&gt;
&lt;h2&gt;Installation von Programmen&lt;/h2&gt;
&lt;p&gt;Damit auf einem Alpine-System glibc-Programm wie tensorflow laufen, muss
zunächst die glibc installiert werden. Außerhalb des containers auf dem
Host-System das apk herunterladen und ins root-Verzeichnis des
containers abspeichern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/my-container/root] &amp;gt; wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-2.32-r0.apk
[sxw@archeus] [~/my-container/root] &amp;gt; wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.32-r0/glibc-bin-2.32-r0.apk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;und die URLs aus dem Repository auskommentieren. Die werden nicht
benötigt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/my-container] &amp;gt; sed -ie 's/^/#/g' etc/apk/repositories
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wieder den Container aktivieren und das APK installieren:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~/my-container] &amp;gt; contain -n . /bin/sh
/ # cd root
~ # apk --allow-untrusted add glibc-2.32-r0.apk
~ # apk --allow-untrusted add glibc-bin-2.32-r0.apk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Und wir sollten sehen, dass der Linker installiert wurde:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ # apk info -L glibc | grep ld
etc/ld.so.cache
lib/ld-linux-x86-64.so.2
lib64/ld-linux-x86-64.so.2
usr/glibc-compat/etc/ld.so.conf
usr/glibc-compat/etc/ld.so.cache
usr/glibc-compat/lib/ld-2.32.so
usr/glibc-compat/lib/ld-linux-x86-64.so.2
usr/glibc-compat/lib64/ld-linux-x86-64.so.2
~ #
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Den Rest erledigen wir über
&lt;a href="https://docs.conda.io/en/latest/miniconda.html"&gt;Miniconda&lt;/a&gt;, einem
Python-Installer, der auch jegliche Binaries, eigene
Python-Installation fuer x86_64 mitbringt und
ziemlich problemlos in meinen Tests funktioniert hat.&lt;/p&gt;
&lt;p&gt;Damit Miniconda auch die Hostnamen auflösen kann sollten wir einen
Nameserver in die &lt;code&gt;/etc/resolv.conf&lt;/code&gt; des Containers eintragen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~ # echo 'nameserver 141.1.1.1' &amp;gt; /etc/resolv.conf
~ # wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
Connecting to repo.anaconda.com (104.16.131.3:443)
saving to 'Miniconda3-latest-Linux-x86_64.sh'
Miniconda3-latest-Li   1% |                                |
...
'Miniconda3-latest-Linux-x86_64.sh' saved
~ # ls
Miniconda3-latest-Linux-x86_64.sh  glibc-2.32-r0.apk
~ # chmod 755 Miniconda3-latest-Linux-x86_64.sh 
~ # ./Miniconda3-latest-Linux-x86_64.sh 

Welcome to Miniconda3 py38_4.8.3

In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
&amp;gt;&amp;gt;&amp;gt;

[... LICENSE ...]

Do you accept the license terms? [yes|no]
[no] &amp;gt;&amp;gt;&amp;gt; yes

Miniconda3 will now be installed into this location:
/miniconda3

  - Press ENTER to confirm the location
  - Press CTRL-C to abort the installation
  - Or specify a different location below

[/miniconda3] &amp;gt;&amp;gt;&amp;gt;

PREFIX=/miniconda3
Unpacking payload ...
...
installation finished.
Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
[no] &amp;gt;&amp;gt;&amp;gt; yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun sollten wir eine komplette Python-Umgebung in &lt;code&gt;/miniconda3&lt;/code&gt; bekommen
haben, dessen Funktionalität wir durch Ausführen von
&lt;code&gt;/miniconda3/bin/python&lt;/code&gt; bestätigen können:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/ # /miniconda3/bin/python
Python 3.8.3 (default, May 19 2020, 18:47:26) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
&amp;gt;&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jetzt nur noch die restlichen Abhängigkeiten installieren:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/ # /miniconda3/bin/conda install pandas
/ # /miniconda3/bin/conda install -c conda-forge opencv
/ # /miniconda3/bin/conda install scikit-image
/ # /miniconda3/bin/conda create -n tf tensorflow
/ # /miniconda3/bin/conda install -c conda-forge keras
/ # /miniconda3/bin/conda install -c conda-forge imutils
/ # /miniconda3/bin/conda install -c anaconda psycopg2
/ # /miniconda3/bin/conda install -c anaconda redis
&lt;/code&gt;&lt;/pre&gt;
</content></entry><entry><title>Qemu als runit Service</title><link href="http://www.mueslihq.de/techblog/qemu_sv/" rel="alternate"/><updated>2020-09-07T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:dd0c51a8-edd6-3637-baea-94f0d04f9512</id><content type="html">&lt;h3&gt;Einleitung&lt;/h3&gt;
&lt;p&gt;Manchmal möchte man zusätzlich zum normalen System noch eine virtuelle Maschine
laufen lassen, was mit qemu ja auch schnell und einfach funktioniert. Soll dies
dauerhaft erfolgen muss qemu als Dienst laufen. Hier könnte man z.B. &lt;code&gt;libvirt&lt;/code&gt;
verwenden oder man erzeugt pro VM einen Dienst was mit
&lt;a href="http://smarden.org/runit/"&gt;runit&lt;/a&gt; auch sehr einfach ist. Allerdings führt ein
SIGTERM, was zum stoppen die Dienstes Verwendung findet, nicht zum
Herunterfahren der Maschine, sondern das Signal schaltet sie aus. Es gibt aber
über die Monitoring-Konsole von qemu die Möglichkeit ein passendes Signal
abzusetzen, so dass die VM normal herunter gefahren wird.&lt;/p&gt;
&lt;h3&gt;Abfangen der Signale&lt;/h3&gt;
&lt;p&gt;Damit das Signal zum Beenden nicht direkt bei qemu landet brauchen wir einen
Wrapper, der angegebene Signale abfängt und die nötigen Aktionen ausführt.
Dafür eignet sich eine Scriptsprache wie etwa Python. Hier ein Codebeispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import time
import signal

class A:
    def __init__(self):
        self.loop = True
        signal.signal(signal.SIGTERM, self.signal_handler)
        while self.loop:
            print("do some thing")
            time.sleep(1)
        print("stop")

    def signal_handler(self, signum, frame):
        if signum == 15:
            print("get SIGTERM")
            self.loop = False
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Child Prozess forken&lt;/h3&gt;
&lt;p&gt;Es gibt verschiedene Möglichkeiten unter python einen neuen Prozess zu erzeugen,
in dem Beispiel hier verwende ich &lt;code&gt;pexpect&lt;/code&gt;. Damit kann man auch mit dem Prozess
sprechen und auf entsprechende Ausgaben reagieren, was wir hier nicht benötigen.&lt;/p&gt;
&lt;p&gt;Um einen neuen Kindprozess zu erstellen reicht dabei ein einfaches &lt;code&gt;child =
pexpect.spawn(cmd)&lt;/code&gt; wobei in &lt;code&gt;cmd&lt;/code&gt; das Programm mit all seinen Parametern
steht. Mit &lt;code&gt;child.isalive()&lt;/code&gt; kann überprüft werden ob der Prozess noch läuft.&lt;/p&gt;
&lt;h3&gt;Kommando an die Monitorkonsole senden&lt;/h3&gt;
&lt;p&gt;Um mit qemu während der Laufzeit sprechen zu können nutzen wir den Parameter
&lt;code&gt;-monitor telnet:127.0.0.1:Port,server,nowait&lt;/code&gt; wobei Port durch einen freien
TPC-Port zu ersetzen ist.&lt;/p&gt;
&lt;p&gt;Über diesen Port können wir nun Kontakt zu der qemu Instanz aufnehmen. Das
geht über &lt;code&gt;telnet&lt;/code&gt;, &lt;code&gt;nc&lt;/code&gt; oder eine Socket-Verbindung. Um nicht weitere
Abhängigkeiten in das Projekt zu ziehen, nutzen wir die Möglichkeiten des
&lt;code&gt;socket&lt;/code&gt; Modules.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import sys
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", port))
s.send(b"system_powerdown\n")

state = 1
for t in range(30):
    if child.isalive()
        time.sleep(1)
    else:
        state = child.exitstatus
        break
sys.exit(state)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Damit senden wir das &lt;code&gt;system_powerdown&lt;/code&gt; Signal an dem Monitor und warten für
eine vorgegebene Zeit auf das Prozessende und geben den Status zurück.&lt;/p&gt;
&lt;h3&gt;Das runit Script&lt;/h3&gt;
&lt;p&gt;Damit der VM-Dienst unter runit laufen kann, erstellen wir die passenden
Verzeichnisse und Dateien, z.B.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mkdir -p /etc/sv/vm1
cd /etc/sv/vm1/
ln -s /run/runit/supervise.vm1 supervise
touch run
chmod -x run
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Der Inhalt von run ist dann z.B.:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/sh
exec chpst -u jack:users /usr/local/bin/qemu_sv.py /home/jack/kvm/vm1.qcow2 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Damit würde die VM mit den Rechten von &lt;code&gt;jack&lt;/code&gt; laufen und das Image im
angegebenen Pfad verwenden.&lt;/p&gt;
&lt;p&gt;Um den Dienst zu aktivieren reicht als root ein &lt;code&gt;ln -s /etc/sv/vm1 /var/service&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Das Script&lt;/h3&gt;
&lt;p&gt;Für alle die nicht selbst Scripten wollen gibt es
&lt;a href="https://www.pf4sh.eu/git/pulux/qemu_sv_helper/src/master/qemu_sv.py"&gt;hier&lt;/a&gt; den
Link dazu.&lt;/p&gt;
&lt;p&gt;Alternativ kann man natürlich auch ein kleines Programm dafür schreiben, z.B.
in &lt;a href="https://nim-lang.org"&gt;nim&lt;/a&gt;, wenn man das dann noch statisch baut (unter
musl libc) mit &lt;code&gt;nim c -d:release --opt:size --passL:-static qemu_sv.nim&lt;/code&gt;, lässt
es sich auch ohne weitere Abhängigkeiten verteilen.
&lt;a href="https://www.pf4sh.eu/git/pulux/qemu_sv_helper/src/master/qemu_sv.nim"&gt;Hier&lt;/a&gt;
gibt es den Quellcode dafür.&lt;/p&gt;
&lt;h3&gt;Bridge Setup&lt;/h3&gt;
&lt;p&gt;Um einen vollständigen Netzzugang der VM zu ermöglichen, bietet es sich an die
Netzwerkkarte im &lt;code&gt;bridged&lt;/code&gt; Modus zu betreiben und die Nutzung qemu über die
Datei &lt;code&gt;/etc/qemu/bridge.conf&lt;/code&gt; zu erlauben.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat /etc/qemu/bridge.conf
allow br0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun kann z.B. über die Datei &lt;code&gt;/etc/rc.local&lt;/code&gt; die Brücke mit&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ip link add name br0 type bridge
ip link set br0 up
ip link set eth0 up
ip link set eth0 master br0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;aufgebaut werden.&lt;/p&gt;
&lt;h3&gt;Verbesserungen&lt;/h3&gt;
&lt;p&gt;Es wäre sicherlich sinnvoll die Parameter für qemu aus einer Datei zu lesen und
diese im run-Script mit anzugeben. Ich freue mich über Rückmeldungen.&lt;/p&gt;
</content></entry><entry><title>Musik-Produktion unter Linux / music as code</title><link href="http://www.mueslihq.de/techblog/musik-produktion/" rel="alternate"/><updated>2020-09-06T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:d0acbd0a-154e-39f8-8233-2db9269afb2f</id><content type="html">&lt;p&gt;Musikproduktion und Linux passt (neuerdings) ebenfalls gut zusammen.
Ich nutze Software unter Linux für das MIDI-Recording, um Noten zu setzen, um Mehrspurmitschnitte von Konzerten zu machen und um Bildaufnahmen und Ton zusammen zu schneiden. Neben analogen Instrumenten, wie Gesang und Gitarre, sind auch MIDI-Daten vom E-Schlagzeug und externen Synthesizern, sowie Soft-Synths aus dem Rechner zu verarbeiten. Hier ein Erfahrungsbericht.&lt;/p&gt;
&lt;p&gt;Folgende Software setze ich ein:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.ardour.org"&gt;ardour&lt;/a&gt; als DAW (Digital Audio Workstation)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.fluidsynth.org"&gt;fluidsynth&lt;/a&gt; + &lt;a href="https://qsynth.sourceforge.io/"&gt;qsynth&lt;/a&gt; als Software Synthesizer&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jackaudio.org"&gt;jackd&lt;/a&gt; + &lt;a href="http://qjackctl.sourceforge.net"&gt;qjackctl&lt;/a&gt; als Audioserver &lt;/li&gt;
&lt;li&gt;&lt;a href="https://kdenlive.org"&gt;Kdenlive&lt;/a&gt; für den Audio/Video Schnitt.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://handbrake.fr"&gt;Handbreak&lt;/a&gt; um Videoformate umzuwandeln&lt;/li&gt;
&lt;li&gt;midisport-firmware Firmware loader für M-Audios MidiSport&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.parabola.me.uk/alsa/pmidi.html"&gt;pmidi&lt;/a&gt; als einfaches MIDI-Werkzeug &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.rosegardenmusic.com"&gt;rosegarden&lt;/a&gt;: als MIDI Sequencer und für den Notendruck&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vmpk.sourceforge.io/"&gt;vmpk&lt;/a&gt;: als Virtual MIDI Piano Keyboard&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.musictribe.com/Categories/Behringer/Mixers/Digital/XR18/p/P0BI8"&gt;X Air Edit&lt;/a&gt; Bedienung des X-Air-18 Digital Mixers (closed source!) &lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.debian.org"&gt;Debian Bullseye&lt;/a&gt; und &lt;a href="http://ubuntustudio.org/"&gt;Ubuntustudio 20.04&lt;/a&gt; als Linux Distributionen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Daneben nutze ich ganz viel &lt;a href="https://git-scm.com"&gt;git&lt;/a&gt;, um der Daten auf den unterschiedlichen Rechnern Herr zu werden (Stichwort: music as code).&lt;/p&gt;
&lt;h2&gt;Anforderungen&lt;/h2&gt;
&lt;p&gt;Ein großes Thema in der Audioproduktion mit dem Computer sind Latenzen. Diese sind bei der Aufnahme möglichst gering zu halten. Beim reinen Abspielen stören sie jedoch nicht.&lt;/p&gt;
&lt;p&gt;Meine Anforderung ist zusätzlich, dass eine Weiterbearbeitung der Daten in unterschiedlichen Umgebungen (Soundkarten, PCs, Laptops) erfolgen muss, denn jeder Rechner hat seine Stärken (Rechenleistung, Portabilität).&lt;/p&gt;
&lt;p&gt;Die Anforderungen sind im Detail:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Live Mitschnitt von 18 Audio-Kanälen. Bedienung eines Mischpultes per Software (man kann große Latenzen in Kauf nehmen).&lt;/li&gt;
&lt;li&gt;Synchronisation zu Videomitschnitten&lt;/li&gt;
&lt;li&gt;Digitale Aufnahme von MIDI und Audio, Benutzung von Soft Synths und echten Sythesizer parallel (kleine Latenzen notwendig)&lt;/li&gt;
&lt;li&gt;Abmischen auf Reisen (große Latenzen akzeptabel, Mischung direkt im Laptop)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tipps zur Konfiguration&lt;/h2&gt;
&lt;p&gt;Anbei ein paar allgemeine Tipps zur streßfreien Verwendung von Linux in (meinem) Audioumfeld.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Verwende stets eine aktuelle Installation mit aktuellem Kernel. Auch im Audio Bereich gibt es große Fortschritte. Beispielsweise ermöglichte es en bloßes Upgrade vom Ubuntustudio 18 auf Ubuntustudio 19.10 die Latenzen  weiter herabzusetzen.&lt;/li&gt;
&lt;li&gt;Verwende eine echte Audio-Soundkarte (z.B: USB oder PCI). On-Board-Karten sind ungeeignet.&lt;/li&gt;
&lt;li&gt;&lt;del&gt;Verwende eine, auf Audio optimierte, Distribution (wie &lt;a href="https://ubuntustudio.org/"&gt;Ubuntustudio&lt;/a&gt;) bzw. optimiere Deine Systeme selbst (wenn Du viel Zeit und Know How hast :-))&lt;/del&gt;. Debian 11 hat sich als gut geeignet herausgestellt.&lt;/li&gt;
&lt;li&gt;Die Verwendung von externen MIDI-Sytnthesizern statt Software Synths führt nach meinen Erfahrungen dazu, dass selbst bei geringen Latenzen keine XRuns mehr auftreten. Heute gibt es für kleines Geld gut klingende Hardware aus den späten 90igern.  &lt;/li&gt;
&lt;li&gt;Der Einsatz von X-Air18 Edit und Latenz kritischen Anwendungen ist nur mit einer eigenen Grafikkarte möglich. Sonst gibt es XRuns. Hat der Rechner keine eigene Grafikkarte so sollte X-Air18 Edit auf einem anderen Rechner laufen als Ardour.&lt;/li&gt;
&lt;li&gt;Das Setzen des &lt;code&gt;scaling_governor&lt;/code&gt;s  in den performance-Mode vermindert die Anzahl der XRuns deutlich. Das kleine Shellskript &lt;a href="set_cpuperformance.sh.txt"&gt;set_cpuperformance.sh&lt;/a&gt; setzt diesen Modus für jeden Prozessorkern.&lt;/li&gt;
&lt;li&gt;Der Audiosrver jack sollte im Realtime-Modus verwendet werden. Ein &lt;code&gt;dpkg-reconfigure -p high jackd2&lt;/code&gt; erlaubt Mitgliedern der Gruppe audio diesen Modus zu verwenden.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pulseaudio führt bei zeitkritischen Anwendungen im Verbund (Rosegarden,Ardour,Fluidsynth,X-Air-Edit und Hardware-Sythesizern ) immer zu XRuns. Daher deaktiviere ich pulseaudio, wie folgt:&lt;/p&gt;
&lt;p&gt;cp /etc/pulse/client.conf $HOME/.config/pulse/client.conf&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In der Datei ist zu setzen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;autospawn = no
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun kann der pulseaudio-Prozess "gekillt" werden, ohne dass sofort eine neuer startet. 
Anmerkung: Beim Schneiden von Videoaufnahmen mit &lt;a href="https://kdenlive.org"&gt;Kdenlive&lt;/a&gt; ist pulseaudio wieder zu aktivieren. Sonst hört man keinen Ton.&lt;/p&gt;
&lt;p&gt;Sind meine Aktionen zeitkritisch, so verwende ich &lt;a href="https://ubuntustudio.org"&gt;Ubuntustdio&lt;/a&gt;. Die Bedienung des X-AIR-18 Inetrfaces ist nicht zeitkritisch. Daher erledige ich diese unter einem Standard &lt;a href="https://debian.org"&gt;Debian&lt;/a&gt;-Stable, oder Raspbian (Behringer bietet die X-AIr18-Software auch für die ARM-Architektur an. Auf einem Raspberry PI ist die Software hinreichend schnell.&lt;/p&gt;
&lt;h3&gt;Installation Raspbian&lt;/h3&gt;
&lt;p&gt;Download der Software unter &lt;a href="https://www.raspberrypi.org/downloads/raspbian/"&gt;https://www.raspberrypi.org/downloads/raspbian/&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;unzip 2018-06-27-raspbian-stretch.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unter /var/log/messages bestimmen welches Devicname der SD-Karte erhält, wenn sie eingesteckt wird. Wird ein externer Kartenleser verwendet, so lautet der Name häufig /dev/sdc oder ähnlich. Bei dem internen Kartenleser meines T420s-Laptops lautet der Name des devices /dev/mmcblk0&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dd bs=4M if=2018-06-27-raspbian-stretch of=/dev/mmcblk0 conv=fsync
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Konfiguration Raspbian&lt;/h4&gt;
&lt;p&gt;Unter &lt;em&gt;Raspberry-Pi-Configuration&lt;/em&gt; kann man den&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hostnamen z.B. auf obelix5 oder hal9003 setzen&lt;/li&gt;
&lt;li&gt;Passwort umsetzen&lt;/li&gt;
&lt;li&gt;Locale: language = de(German), Country=DE (Germany), Charakter Set = UTF-8 setzen.&lt;/li&gt;
&lt;li&gt;SSH-Deamon enablen&lt;/li&gt;
&lt;li&gt;Keyboardlayout umstellen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Eventuell ist ein Proxy zu setzen mittels:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@hal9003:~# cat /etc/apt/apt.conf.d/90custom 
Acquire::http::Proxy "http://foo.bar.de:8080";

aptitude install obconf
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Installation X-Air Software&lt;/h3&gt;
&lt;p&gt;Für die digitale Mischpult-Serie von Behringer gibt es Steuersoftware für Linux. Die Steuersoftware liegt für die Intelarchitektur 32bit und neuerdings auch in 64bit vor.  Auch für den Raspberry-Pi gibt es eine Version.&lt;/p&gt;
&lt;p&gt;Man kann die Software auf der &lt;a href="http://www.musictri.be/Categories/Behringer/Mixers/Digital/XR18/p/P0BI8/downloads"&gt;Behringer Homepage&lt;/a&gt; downloaden.&lt;/p&gt;
&lt;h3&gt;Xruns und Latenzen/Konfiguration jackd&lt;/h3&gt;
&lt;p&gt;Je nach Anforderung, setze ich unterschiedliche Hardware ein.&lt;/p&gt;
&lt;p&gt;holzwurm: Selbstbau PC, Intel(R) Atom(TM) CPU D510, 2GB RAM, 120G SSD, Onboard Grapikkarte - Lüfterfreier PC. Erlaubt Gesangsaufnahmen ohne Nebengeräusche und XRuns. Aufgrund der hohen Latenz sind die Gesangsspuren nach der Aufnahme zu verschieben.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@holzwurm:~$ cat .jackdrc  64ms
/usr/bin/jackd -dalsa -dhw:X18XR18 -r48000 -p1024 -n3 -Xseq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;hackepeter:  Lenovo T420s, Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 8GB RAM, 250G SSD, Onboard Graphikkarte - Laptop zum Abmischen auf Reisen oder Aufnahmen mit ardour bei Auftritten. Wenn Ardour und X-Air-Edit gleichzeitig gestartet sind trotz hoher Latenz keine Aufnahmen ohne XRuns möglich. Daher wird dieser Rechner nur für Aufnahmen verwendet.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@hackepeter:~$ cat .jackdrc # qjackctl Latenz 64ms
/usr/bin/jackd -dalsa -dhw:X18XR18,0 -r48000 -p512 -n6 -Xseq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rapante: Lenovo C20, Intel(R) Xeon(R) CPU X5675  @ 3.07GHz, 24G RAM, 1T Hardisk, NVIDIA Corporation GF106GL - unportable aber eierlegende Wollmilchsau, In diesem Setup kann Ardour, X-Air-Edit Rosegarden und fluidsynth auf einer Hardware mit geringen Latenzen ohne XRuns betrieben werden. Rechner ist jedoch nicht portabel und hat einen (leisen) Lüfter.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@rapante:~$ cat .jackdrc # JAckd Latenz 8,71ms
/usr/bin/jackd -v -dalsa -dhw:X18XR18,0 -r44100 -p128 -n3 -Xseq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;raspbian: Kleiner Raspberry PI 3B+ für X-Air-Edit interface im Kellerstudio. Vorteil: Leise und billig. Nachteil: Zu schwachbrüstig für Ardour und Co.&lt;/p&gt;
&lt;p&gt;piepmatz: Lenovo X220: Intel(R) Core(TM) i5-2540M CPU @ 2.60GHz, 4GB RAM, 300GB Harddisk, Onboard Grapikkarte - 2. PC für X-Air-Edit interface auf Konzerten&lt;/p&gt;
&lt;p&gt;schnippedilrichman: Lenovo T430,  Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz, 4GB RAM, 170G SSD, Onboard Graphikkarte, Gnome Classic, Bildschirmschoner aus, jackdbus deaktiviert  - Laptop als Gitarrenverstärker (&lt;a href="http://guitarix.org/"&gt;guitarix&lt;/a&gt;, Audiointerface Behringer U-Phoria UMC204HD)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@schnippedilrichman:~$ cat .jackdrc # qjackctl Latenz 2.67ms
/usr/bin/jackd -dalsa -dhw:U192k -r48000 -p64 -n2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;mrcrabs: Lenovo ThinkPad Yoga 370, Intel(R) Core(TM) i5-7300U CPU @ 2.60GHz, 8GB RAM, 500G SSD, Onboard Graphikkarte, Cinnamon&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@mrcrabs:~$ cat .jackdrc # gjackctl Latenz 4.35ms
/usr/bin/jackd -dalsa -dhw:X18XR18 -r44100 -p64 -n3 -Xseq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;lithium: Lenovo ThinkStation P340, Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz, 32GM RAM, 500 GB SSD,  Onboard Graphikkarte, Debian 11 GNOME3&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@lithium:~$ cat .jackdrc  #  gjackctl Latenz 1.45ms
/usr/bin/jackd -dalsa -dhw:U192k -r88200 -p64 -n2 -Xseq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;oxygen: Lenovo ThinkPad T480, Intel(R) Core(TM) i5-8350U CPU @ 1.70GHzm 8GB RAM, 256GB SSD, Debian 11, Gnome 3&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@oxygen:~$ cat .jackdrc # 8.71ms
/usr/bin/jackd -dalsa -dhw:U192k -r88200 -p256 -n3 -Xseq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mit diesem kleinen Setup lässt sich nun nach ein paar Jahren Konfigurationsarbeit, im Kellerstudio und auch Live, arbeiten. Es gibt keine Ausreden mehr :-). Jetzt wird also &lt;a href="https://www.boelckeband.de"&gt;Musik gemacht&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Deaktivieren der Onboard-Soundkarte&lt;/h3&gt;
&lt;p&gt;Onboard-Soundkarten besitzen normalerweise einen schlechte Audio-Qualität. Benutzt man nur eine externe Soundkarte, so kann man die interne getrost deaktivieren.&lt;/p&gt;
&lt;p&gt;In der Praxis hat sich auch gezeigt, dass die Verwendung von 2 Soundkarten zur Verwirrung führt. Ardour 6  kann beispielsweise mit 2 Soundkarten umgehen und ich habe noch nicht rausgekriegt, wie ich deren Verwendung im Detail konfugurieren kann.&lt;/p&gt;
&lt;p&gt;Blacklistet man den Treiber der internen Soundkarte, so ist diese nach dem Reboot nicht mehr verfügbar.&lt;/p&gt;
&lt;p&gt;Vor dem Reboot:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    rocholl@schnippedilrichman:~# cat /proc/asound/cards
 0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xd2530000 irq 36
 1 [U192k          ]: USB-Audio - UMC202HD 192k
                      BEHRINGER UMC202HD 192k at usb-0000:00:1d.0-1.5.2, high speed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Deaktivieren der Soundkarte:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root@schnippedilrichman:~# cat /etc/modprobe.d/blacklist.conf 
# disable my PCI intel sound card
blacklist snd_hda_intel
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nach dem Reboot :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rocholl@schnippedilrichman:~$ cat /proc/asound/cards
 1 [U192k          ]: USB-Audio - UMC202HD 192k
                  BEHRINGER UMC202HD 192k at usb-0000:00:1d.0-1.5.2, high speed
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Ardour 6.2&lt;/h3&gt;
&lt;p&gt;Ardour 6.2 hat viele Verbesserungen unter der Haube. Es empfiehlt sich direkt diese Version zu verwenden. Debian unstable hat diese Version bereits paketiert. 
Falls die eigene Distrubution kein Ardour 6.2 dabei hat, kann Ardour als Binary von der &lt;a href="https://ardour.org/"&gt;Homepage&lt;/a&gt; heruntergeladen werden.&lt;/p&gt;
&lt;p&gt;Es ist jedoch auch einfach möglich sich Ardour einfach selbst zu kompilieren.&lt;/p&gt;
&lt;p&gt;Unter Ubuntustudio sind einige Pakete nachzuinstallieren.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt install libboost-dev libasound2-dev libpulse-dev libglibmm-2.4-dev libsndfile1-dev libcurl4-gnutls-dev libarchive-dev liblo-dev \ 
libtag1-dev librubberband-dev libfftw3-dev libaubio-dev libxml2-dev liblrdf0-dev libsamplerate0-dev lv2-dev libserd-dev libsord-dev \
libsratom-dev liblilv-dev libgtkmm-2.4-dev libsuil-dev libjack-jackd2-dev libudev-dev libwebsockets-dev libcppunit-dev \
libreadline-dev libusb-dev vamp-plugin-sd chrpath libclang-dev libsoundtouch-dev libdbus1.0-cil-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dann braucht man nur noch der &lt;a href="https://ardour.org/building_linux.html"&gt;Installationsanleitung unter https://ardour.org/building_linux.html&lt;/a&gt; zu folgen.&lt;/p&gt;
&lt;h3&gt;Links&lt;/h3&gt;
&lt;p&gt;Anbei ein paar Links, die mir bei der Konfiguration geholfen haben:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boelckeband.de"&gt;boelckeband.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/FluidSynth/fluidsynth/issues/225"&gt;Bug fluidsynth?: multi channel output not working&lt;/a&gt; - habe ich noch nicht hingekrieg &lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.linuxaudio.org/wiki/system_configuration"&gt;Check der Konfiguration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://collaps.de"&gt;collaps.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxnix.com/find-sound-card-details-in-linuxunix/"&gt;Find Sound card details in Linux/Unix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linuxconfig.org/how-to-upgrade-to-ubuntu-18-04-lts-bionic-beaver"&gt;How To Upgrade Ubuntu To 18.04 LTS Bionic Beaver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.ubuntuusers.de/topic/kein-sound-bei-midi-jack-rosegarden-nted-qsynt/"&gt;Kein Sound bei MIDI. JACK, Rosegarden, NtEd, qsynth, TiMidity, FluidSynth&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.delamar.de/musikproduktion/die-latenz-in-der-musikproduktion-2838/"&gt;Latenzen in der Musikproduktion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/lilypond/comments/8ivxge/lilypond_in_debian_stretch/"&gt;Lillipond und Debian Stretch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.vintagesynth.com/articles/5-free-software-synths-linux"&gt;Linux Softsynths&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raspberrypi.stackexchange.com/questions/66466/how-to-set-the-number-of-virtual-desktops-in-pixel-create-new-vdesktops"&gt;Mehrere Desktops im Raspberry-PI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sites.google.com/site/xairutilities/"&gt;Open Source Utilities für das X-Ait 18 Mischpult&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://lists.ardour.org/pipermail/ardour-users-ardour.org/2016-August/028052.html"&gt;Shortcut = in Ardour&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://lists.linuxaudio.org/archives/linux-audio-user/2018-May/109984.html"&gt;System Example for Running Configuration mit Latenz: 1.33ms&lt;/a&gt; - Das ist das Ziel :-)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazona.de/test-behringer-xr18-digitalmixer-teil-1/6/"&gt;Test Behringer X-Air 18, Latenz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://linuxsynths.com/"&gt;Überblick über Linux Software Synthesizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxbabe.com/ubuntu/upgrade-ubuntu-18-04-18-10-to-ubuntu-19-04"&gt;Upgrade Ubuntu Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://behringerwiki.music-group.com/index.php?title=1._Introduction"&gt;Wiki zum X-AIR-18 Mischpult&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sourceforge.net/projects/xairlivetoolbox/"&gt;X-Air Live Toolbox/Open Source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.musictri.be/showthread.php?20950-X-Air-Python-Open-Source-X-Air-Controller"&gt;X-Air-Python Open Source X-Air Controller&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://digital-audio-systems.com/technischer-hintergrund/"&gt;https://digital-audio-systems.com/technischer-hintergrund/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linuxconfig.org/how-to-upgrade-ubuntu-to-20-04-lts-focal-fossa"&gt;Upgrade Ubuntustudio 19.10 nach 20&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x42-plugins.com/x42/x42-avldrums"&gt;AVL Drumkits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://drumgizmo.org"&gt;Drum Gizmo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ctrlr.org/jv-xp-editor-for-roland-jv1080-jv2080-xp30-xp50-and-xp80-series-synthesizers"&gt;ctrlr.org: MIDI editor for all your hardware&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=IHurl-2Sjy0"&gt;Linux midi routing mit QMidiRoute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://audiogeek11.com/jam-music-online-with-jamulus/"&gt;Jam music online with jamulus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/questions/110835/how-to-disable-the-internal-sound-card"&gt;https://askubuntu.com/questions/110835/how-to-disable-the-internal-sound-card&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forums.linuxmint.com/viewtopic.php?t=82230"&gt;https://forums.linuxmint.com/viewtopic.php?t=82230&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.techtimejourney.net/how-to-blacklist-a-sound-card-in-linux/"&gt;https://www.techtimejourney.net/how-to-blacklist-a-sound-card-in-linux/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.thomann.de/de/onlineexpert_topic_home_recording.html"&gt;Home Recording Ratgeber von Thomann&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazona.de/community/wenn-der-linuxer-mehr-audio-ausgaenge-braucht/"&gt;https://www.amazona.de/community/wenn-der-linuxer-mehr-audio-ausgaenge-braucht/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazona.de/community/linux-guitarix-dickes-daw-projekt-und-die-loesung-des-latenzproblems/"&gt;https://www.amazona.de/community/linux-guitarix-dickes-daw-projekt-und-die-loesung-des-latenzproblems/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pTT-L1oEbcw"&gt;Guitarx Demo on Youtube - Part1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=t91xJUos10A"&gt;Guitarx Demo on Youtube - Part2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linuxmusicians.com/viewtopic.php?t=17176"&gt;Difference between jackd and jackdbus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.linuxaudio.org/wiki/list_of_jack_frame_period_settings_ideal_for_usb_interface"&gt;List of JACK Frame [or Buffer] &amp;amp; Period settings ideal for USB interface, Berechnung der Latenz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amp.reddit.com/r/linuxaudio/comments/emj53r/looking_of_a_low_latency_usb_audio_interface/"&gt;Thread zu Low-Latency USB-Interface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.ubuntuusers.de/Prozessortaktung/"&gt;Pozessortakung&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bfTAKv4htDE"&gt;Ardour 6 Quickstart (recording, editing, mixing and exporting)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alsa.opensrc.org/MultipleUSBAudioDevices"&gt;MultipleUSBAudioDevices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kosua20/MIDIVisualizer.git"&gt;MIDIVisualizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://debianforum.de/forum/viewtopic.php?t=182590"&gt;RT Kernel installieren für Jack?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>Goofys</title><link href="http://www.mueslihq.de/techblog/goofys/" rel="alternate"/><updated>2020-09-06T00:00:00Z</updated><author><name>Simon Wilper</name></author><id>urn:uuid:1773fa03-a866-3b0f-b784-db0f93033922</id><content type="html">&lt;h2&gt;Darum geht es&lt;/h2&gt;
&lt;p&gt;Sie kennen das: Jemand hat jeglich Webdienste und Dienste zum
Vorverarbeiten von Daten in die &lt;a href="https://de.wikipedia.org/wiki/Microsoft_Azure"&gt;Microsoft Azure
Cloud&lt;/a&gt; in Form von
virtuellen Maschinen und sogenannten &lt;em&gt;Azure Functions&lt;/em&gt; verlegt. Dazu
gibt es dann noch den Azure
&lt;a href="https://de.wikipedia.org/wiki/Data-Lake"&gt;Datalake&lt;/a&gt;, einem
Storage-Dienst um Rohdaten abzuspeichern.&lt;/p&gt;
&lt;p&gt;Das Problem hierbei ist, dass man für den Zugriff auf diesen Datalake
ein Tool von Microsoft brauch, das deren Datalake-Web-API bedient,
obwohl es am Ende nichts anderes als eine Festplatte ist.&lt;/p&gt;
&lt;p&gt;Somit wäre es doch ein opportune Angelegenheit, wenn es ein
&lt;a href="https://de.wikipedia.org/wiki/Filesystem_in_Userspace"&gt;FUSE&lt;/a&gt;-basiertes
Tool gäbe, das den Datalake als normales mount-bares Dateisystem
behandelt.&lt;/p&gt;
&lt;h2&gt;Die Lösung&lt;/h2&gt;
&lt;p&gt;Vor Kurzem hat mir mein Kollege (Danke, Markus) das Programm
&lt;a href="https://github.com/kahing/goofys"&gt;Goofys&lt;/a&gt; vorgeschlagen, um den Zugriff
auf unseren Datalake zu vereinfachen. Das hat hervorragend funktioniert.
Wir haben ein komplettes Backup unserer fast 1TB Daten durchgeführt und
es gab keine Verbindungsabbrüche.&lt;/p&gt;
&lt;p&gt;Wir haben uns erhofft, damit natürlich dann auf die Azure-Client-Tools
verzichten zu können, was uns aber leider verwehrt blieb, da es für die
Datalakes keine Verbindungszeichenfolge (wie etwa für Blob-Storages) existieren.
Man muss sich erst über das Azure-Command-Tool "az" anmelden.&lt;/p&gt;
&lt;p&gt;Naja, man kann nicht alles haben.&lt;/p&gt;
&lt;h2&gt;Voraussetzungen&lt;/h2&gt;
&lt;p&gt;Wir brauchen zwei Pakete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;azure-cli: Das Azure Commandline Interface&lt;/li&gt;
&lt;li&gt;goofys&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je nach Distribution kann die Installation unterschiedlich ausfallen.
Bei Archlinux z.B. gibt es beide Pakete nicht in den offiziellen
Repositories und müssen über das AUR installiert werden.&lt;/p&gt;
&lt;p&gt;Bei Ubuntu gibt es azure-cli immerhin im &lt;a href="https://packages.ubuntu.com/focal/azure-cli"&gt;offiziellen
Repo&lt;/a&gt;, goofys am besten
einfach als x86-binary direkt herunterladen.&lt;/p&gt;
&lt;p&gt;Bei voidlinux... oh boy... hat sich noch niemand dazu berufen gefühlt
Pakete zu bauen. ;) Naja, das kann sich ja noch ändern.&lt;/p&gt;
&lt;p&gt;Auf jeden Fall sollte man bei Eingabe von &lt;code&gt;az --version&lt;/code&gt; ungefähr
folgende Ausgabe bekommen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;azure-cli                         2.11.1

core                              2.11.1
telemetry                          1.0.6

Python location '/opt/azure-cli/bin/python'
Extensions directory '/home/sxw/.azure/cliextensions'

Python (Linux) 3.8.5 (default, Jul 27 2020, 08:42:51) 
[GCC 10.1.0]

Legal docs and information: aka.ms/AzureCliLegal


Your CLI is up-to-date.

Please let us know how we are doing: https://aka.ms/azureclihats
and let us know if you're interested in trying out our newest features: https://aka.ms/CLIUXstudy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;und bei &lt;code&gt;goofys --version&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;goofys version 0.24.0-45b8d78375af1b24604439d2e60c567654bcdf88
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;So funktioniert es&lt;/h2&gt;
&lt;p&gt;Wie bereits erwähnt müssen wir uns bei Microsoft Azure erstmal anmelden:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~] &amp;gt; az login
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn die Shell in einer grafischen Umgebung läuft (also, in so etwas wie
in einer XTerm) wird sofort ein Webbrowser geöffnet, der die Login-Seite
aufruft. Ruft man den Befehl hingegen in einer SSH-Shell auf, wird eine
URL ausgegeben, die man manuell aufrufen und den angegebenen Code
eingeben muss.&lt;/p&gt;
&lt;p&gt;Nach erfolgreichem Login wird eine JSON-Liste mit allen verfügbaren
Subscriptions ausgegeben, die etwa folgendermaßen aussieht:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "f88555d1-8ccb-48ea-af9c-c6b2b24e4fe7",
    "id": "f372136a-12de-67a7-60c8-d23483247320",
    "isDefault": true,
    "managedByTenants": [
      {
        "tenantId": "2f232332-22b7-422e-b220-c33343234353"
      }
    ],
    "name": "SKYNET.Node.0000.0001",
    "state": "Enabled",
    "tenantId": "f88555d1-8ccb-48ea-af9c-c6b2b24e4fe7",
    "user": {
      "name": "marcus.wright@skynet.com",
      "type": "user"
    }
  }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun, da wir eingeloggt sind, können wir uns die Datalakes, auf die wir
Zugriff haben auflisten lassen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~] &amp;gt; az dls account list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das könnte uns allerdings die Konsole mit JSON vollmüllen, je nachdem,
wie viele Lakes dort herumlungern. Da wir nur am
Namen interessiert sind, kann man die Ausgabe von JSON nach "tab
separated values" umschalten und durch awk pipen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~] &amp;gt; az dls account list --output tsv | awk '{print $3}'
skynetcentral01.azuredatalakestore.net
t800production01.azuredatalakestore.net
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jetzt müssen wir nur noch wissen, ob es sich bei unserem Lake, auf den
wir zugreifen wollen um einen Gen1 oder Gen2 Lake handelt. Dazu kurz die
Azure Portal Webseite und dann die Datalake-Übersichtsseite geöffnet:&lt;/p&gt;
&lt;p&gt;&lt;img src="goofys_azure.png" class="img-fluid"
     alt="Datalake Generation Screenshot"&gt;&lt;/img&gt;&lt;/p&gt;
&lt;p&gt;Alles klar, für einen Gen1-Datalake können wir diesen jetzt mit goofys mounten.
Dazu nehmen wir einfach die URL mit dem Datalake-Namen, und setzen ein
&lt;code&gt;adl://&lt;/code&gt; davor:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[sxw@archeus] [~] &amp;gt; goofys adl://dlindigolaiarchivedev01.azuredatalakestore.net mnt
[sxw@archeus] [~] &amp;gt; ls mnt
total 32K
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 Nodes
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 T-800
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 T-1000
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 Production-Data
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 Manuals
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 Turbo-Encabulator-4.0
drwxr-xr-x 2 sxw mco 4,0K  6. Sep 21:12 temp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Und schon können wir den Datalake als klassisches Filesystem benutzen.&lt;/p&gt;
</content></entry><entry><title>IRC part II</title><link href="http://www.mueslihq.de/techblog/irc_part2/" rel="alternate"/><updated>2020-03-26T00:00:00Z</updated><author><name>Robin Schubert</name></author><id>urn:uuid:fdcf1e62-20a0-38cc-8984-7b07ad49a109</id><content type="html">&lt;h3&gt;tl;dr&lt;/h3&gt;
&lt;p&gt;Wer einfach schnell loslegen moechte, ohne viel Einrichtung, ohne eigenem Hosting aber &lt;strong&gt;mit dauerhafter Verbindung zum IRC&lt;/strong&gt;, der moege zum Punkt &lt;a href="#matrix"&gt;Matrix und element&lt;/a&gt; springen.&lt;/p&gt;
&lt;h3&gt;Vorneweg zum Problem&lt;/h3&gt;
&lt;p&gt;Vor einiger Zeit hatte ich eine &lt;a href="../irc/"&gt;Einfuehrung in IRC&lt;/a&gt; in diesem Blog geschrieben. Im Moment wird die Zeit von Covid-19 beherrscht und digitale Kommunikationskanaele sind auf ein mal wieder etwas mehr gefragt.
IRC ist nach wie vor eine solide Alternative zu vielen heute populaeren Kommunikationsdiensten. Fuer viele Einsteiger ist das Konzept ungewohnt, dass Nachrichten nicht gelesen werden koennen wenn man nicht eingeloggt bzw. in dem entsprechenden Chatraum anwesend war. Dieses Konzept hat seine Vorteile - man jeder Zeit den Raum verlassen oder betreten, je nachdem ob man an Diskussionen teilnehmen moechte oder nicht. Aber was wenn man alles mitlesen moechte ohne den PC/Laptop ununterbrochen verbunden zu haben?&lt;/p&gt;
&lt;p&gt;Dazu gibt es einige Loesungen, ein paar davon moechte ich hier vorstellen.&lt;/p&gt;
&lt;p&gt;Vorweg zu nennen waere ein naheliegender Ansatz, dass z.B. ein Bot die Konversation aufzeichnet und irgendwo oeffentlich zur Verfuegung stellt. Das ist in Sachen Privatsphaere allerdings [problematisch][link:freenode_logs].&lt;/p&gt;
&lt;h3&gt;Schnell und schlank selbst gehostet&lt;/h3&gt;
&lt;p&gt;Das set-up das ich selbst nutze und bisher uneingeschraenkt weiterempfehlen kann. Ich betreibe meinen eigenen Heim-Server den ich ueber SSH von aussen auch gut erreichen kann. Auf dem Server laeuft &lt;a href="https://weechat.org/"&gt;weechat&lt;/a&gt; in einer &lt;a href="https://github.com/tmux/tmux/wiki"&gt;tmux&lt;/a&gt; session. Andere Kombinationen von IRC Terminal Client und Terminal Multiplexer sind moeglich, statt weechat und tmux koennte man eben so gut &lt;a href="https://irssi.org/"&gt;irssi&lt;/a&gt; und &lt;a href="https://www.gnu.org/software/screen/"&gt;GNU screen&lt;/a&gt; benutzen.&lt;/p&gt;
&lt;p&gt;Auf dem Server mit eingerichtetem weechat wird weechat in der tmux Session gestartet&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-{bash}"&gt;tmux new-session -s weechat
weechat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Auf meinen Clients die sich mit SSH verbinden koennen habe ich einen alias eingerichtet, der direkt ueber SSH mit der tmux session verbindet:&lt;/p&gt;
&lt;pre&gt;&lt;code class="lang-{bash}"&gt;alias weechat=&amp;quot;ssh &amp;lt;user@host&amp;gt; -t tmux attach -t weechat&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Das funktioniert auch ganz hervorragend auf Android Geraeten mit &lt;a href="https://termux.com/"&gt;Termux&lt;/a&gt;, einem Terminal Emulator und Linux Umgebung fuer Android. Dazu bietet sich an, unter weechat den Maus support zu aktivieren, dann klappt auch das Channel wechseln und scrollen bequem per Tappen und Swipen. Anstatt den Client zu beenden, wird dann je nach Terminal Multiplexer die Session getrennt / detacht. Bei tmux also mit &lt;code&gt;ctrl+b, d&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Speziell fuer die "Weechat + Android" Kombination gibt es auch eine &lt;a href="https://github.com/ubergeek42/weechat-android"&gt;Weechat-Relay App&lt;/a&gt; im Google oder F-Droid Repository.&lt;/p&gt;
&lt;h3&gt;Die Quassel Komplettloesung&lt;/h3&gt;
&lt;p&gt;Quassel ist einer der beliebtesten IRC Clients. Das Besondere an Quassel ist allerdings, das er nicht nur als Client sondern auch als Komplettloesung mit Bouncer-Server / Client zur Verfuegung steht. Quassel-Core wird auf dem Server ausgefuehrt und Quassel-Clients koennen sich verbinden. Das Paket bietet eine komfortable Loesung die in den meisten Faellen direkt aus dem Paketmanager heraus installiert werden kann. Eine Ausfuehrlichere Anleitung zur Konfiguration findet ihr zum Beispiel in der &lt;a href="https://wiki.ubuntuusers.de/Quassel/"&gt;Ubuntuusers Wiki&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;IRC Bouncer&lt;/h3&gt;
&lt;p&gt;Eine weitere Methode im IRC dauerhaft verbunden zu bleiben ist die "bounced network connection" (BNC). Der User verbindet seinen Client mit einem &lt;a href="https://en.wikipedia.org/wiki/BNC_(software)#IRC"&gt;Bouncer&lt;/a&gt;, der wiederum dauerhaft mit dem IRC Netzwerk verbunden bleibt. Ein Bouncer der sich mit relativ wenig Aufwand selbst hosten laesst ist &lt;a href="https://github.com/znc/znc"&gt;ZNC&lt;/a&gt;. Neben einer Web-Oberflaeche mit Einstellungen zu IRC Servern und Channeln sowie einigen Plugins bietet diese Methode ausserdem die Moeglichkeit, verschiedene Personen den Service nutzen zu lassen und ihre Servereinstellungen individuell einzurichten.&lt;/p&gt;
&lt;h3&gt;Glowing Bear&lt;/h3&gt;
&lt;p&gt;Wem ein reines Terminal Interface doch noch zu gruselig ist, fuer den lohnt sich vielleicht ein Blick auf den &lt;a href="https://github.com/glowing-bear/glowing-bear"&gt;Glowing Bear&lt;/a&gt;, um den eigenen weechat Server ueber ein schickes Web-Interface anzusteuern.&lt;/p&gt;
&lt;h3&gt;Matrix und Element &lt;a name="matrix"&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://matrix.org/"&gt;Matrix&lt;/a&gt; ist ein freies Software Projekt, dass sichere und dezentrale Kommunikation fuer alle bieten moechte. Ein Matrix Server kann selbst gehostet werden, aber auch die Registrirung am matrix.org Server ist kostenlos und schnell moeglich.&lt;/p&gt;
&lt;p&gt;Das Matrix Netzwerk bietet Bruecken zu den meisten anderen Kommunikationsdiensten, natuerlich auch zu IRC. Der offizielle Client um sich mit dem Matrix Netzwerk zu verbinden ist &lt;a href="https://matrix.org/docs/projects/client/element"&gt;Element&lt;/a&gt; (ehemals Riot.im), der wiederum fuer die meisten Betriebssysteme als native oder Web-App zur Verfuegung steht. Es existieren allerdings noch eine Vielzahl von &lt;a href="https://matrix.org/clients/"&gt;weiteren Clients&lt;/a&gt; fuer Matrix, falls Element euch nicht zusagen sollte.&lt;/p&gt;
&lt;p&gt;In eurem Matrix Client koennt ihr z.B. unserem #muesli Channel im libera.chat Netzwerk beitreten mit dem Befehl&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/join #muesli:libera.chat&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;wie man &lt;a href="https://opensource.com/article/17/5/introducing-riot-IRC"&gt;hier&lt;/a&gt; nachlesen kann.&lt;/p&gt;
&lt;p&gt;Matrix/Element ist eine exzellente Alternative nicht nur zum selber hosten des IRC Servers, sondern auch zu anderen Instant Messenger Opionen.&lt;/p&gt;
&lt;h3&gt;3rd party BNC&lt;/h3&gt;
&lt;p&gt;Wer aus irgendeinem Grund Element nicht moegen sollte, fuer den gibt es immernoch die Moeglichkeit einen der kostenlosen BNC Services zu nutzen, eine Suche mit der Search Engine eurer Wahl sollte euch hier weiterhelfen.&lt;/p&gt;
&lt;h3&gt;Update 2021-05-26&lt;/h3&gt;
&lt;p&gt;Ich habe einige Passagen in diesem Artikel minimal angepasse, auf Grund der Situation die ich schon im Update &lt;a href="../irc/"&gt;hier&lt;/a&gt; beschrieben hatte.&lt;/p&gt;
&lt;h3&gt;Update 2022-06-25&lt;/h3&gt;
&lt;p&gt;Der Client Riot.im wurde in Element umbenannt.&lt;/p&gt;
</content></entry><entry><title>Praxis: Konfiguration von IEEE-802.1q-VLANs mit einem EdgeRouter X</title><link href="http://www.mueslihq.de/techblog/vlans/" rel="alternate"/><updated>2019-04-14T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:13222d95-8d80-3ed7-81ea-cb508f19f67b</id><content type="html">&lt;p&gt;Netzwerksegmentierung ist auch im Heimnetzwerk ein großes Thema. Gerade in Zeiten der zunehmenden Vernetzung von Geräten, die bekannterweise Sicherheitsprobleme haben (wie z.B. IP-Kameras). Diese Geräte möchte man von der wichtigen Infrastruktur abschotten.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://de.wikipedia.org/wiki/Virtual_Local_Area_Network"&gt;VLANs&lt;/a&gt; sind hier eine wichtige Komponente.&lt;/p&gt;
&lt;p&gt;In unserer &lt;a href="../../mueslihq.de/mailinglist/"&gt;Mailingliste&lt;/a&gt; habe ich einige Fragen zum Setup vom IEEE 802.1q-VLANs und zu Erfahrungen mit einem speziellen, sehr günstigen Router von Ubiquiti gestellt.&lt;/p&gt;
&lt;p&gt;Die Konfiguration ist mir im stillen Kämmerlein nicht auf Anhieb geglückt.&lt;/p&gt;
&lt;p&gt;Die offenen Fragen konnte ich jedoch direkt auf dem &lt;a href="../../stammtisch/"&gt;Aprilstammtisch&lt;/a&gt; klären.
Ich habe einfach die Hardware mit in die Kneipe genommen und wir haben diese gemeinsam erfolgreich konfiguriert. Super.&lt;/p&gt;
&lt;p&gt;Hier ein Techblog zu den Details der Konfiguration und ein paar weiteren Ergebnisse.&lt;/p&gt;
&lt;h2&gt;Anforderungen&lt;/h2&gt;
&lt;p&gt;Ziel war die Erstellung einer lauffähigen IEEE 802.1q-VLAN-Konfiguration mit einem Zyxel GS1200-8 managed Switch und einem Ubiquity Edge-Router X. Im VLAN20 sollten die weniger vertrauenswürdigen  Geräte, wie IP-Kameras, stehen. Im VLAN10 stehen eher vertrauenswürdige Geräte.
Die VLANs sollen über Firewall Regeln miteinander sprechen können. Das VLAN20 sollte keinen direkten Zugriff ins Internet haben.&lt;/p&gt;
&lt;p&gt;Hier das Komponentendiagramm (&lt;a href="ubiquiti-2-vlans.uml"&gt;plantuml-Quellcode&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src="ubiquiti-2-vlans.png" class="img-fluid" alt="VLAN-Komponentendiagramm"&gt;&lt;/img&gt;&lt;/p&gt;
&lt;h2&gt;Konfiguration des Switches&lt;/h2&gt;
&lt;p&gt;Der Zyxel GS1200-8 Switch kann per Webinterface konfiguriert werden. Im Auslieferungszustand besitzt er die IP Adresse 192.168.1.3.
Im Switch sind die VLANs wie folgt einzustellen.&lt;/p&gt;
&lt;p&gt;&lt;img src="gs1200-vlan-setup.png" class="img-fluid" alt="GS1200-VLAN-Setup"&gt;&lt;/img&gt;&lt;/p&gt;
&lt;p&gt;Leider kann man die Konfiguration bei diesem Switch nur als Binary abspeichern. Auch müssen dieselben VLAN-IDs an mehreren Stellen eingegeben werden, was für den Anfänger etwas verwirrend ist. Ist er aber einmal konfiguriert, tut er was er soll.&lt;/p&gt;
&lt;h2&gt;Konfiguration Ubiquity EdgeRouter X&lt;/h2&gt;
&lt;p&gt;Der EdgeRouter X ist für wenig  Geld zu haben und liefert eine klicky-bunty Web-Schnittstelle. Er kann jedoch auch über die Kommandozeile, in einer eigenen Sprache, konfiguriert werden. Unter der Haube steckt ein Linux.&lt;/p&gt;
&lt;p&gt;Es können Netze, DHCP-Server, Firewalls etc. konfiguriert werden. Trotz der Weboberfläche kann die Konfiguration schnell knifflig werden. Das liegt jedoch am Thema bzw. an der Vorbildung :-).&lt;/p&gt;
&lt;p&gt;Sehr schön ist, dass man die Konfiguration als Tarball exportieren kann. Packt man diese aus, so erhält man sehr, sehr wenige ASCII-Dateien, die man schön versionieren kann. Nur so konnte ich beispielsweise erkennen, welche Änderungen ein Konfigurationswizard im Detail gemacht hat.&lt;/p&gt;
&lt;p&gt;Anbei die Konfiguration des oben beschriebenen Anwendungsfalls.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;firewall {
    all-ping enable
    broadcast-ping disable
    ipv6-receive-redirects disable
    ipv6-src-route disable
    ip-src-route disable
    log-martians enable
    name VLAN20_IN {
        default-action drop
        description "Filter VLAN20"
        rule 1 {
            action accept
            description ALLOW_ICMP
            log disable
            protocol icmp
        }
        rule 2 {
            action accept
            description ALLOW_SSH_TO_VLAN10
            destination {
                address 192.168.10.0/24
                port 22
            }
            log disable
            protocol tcp
            source {
                address 192.168.20.0/24
            }
        }
    }
    name VLAN20_LOCAL {
        default-action drop
        description ""
        rule 1 {
            action accept
            description ALLOW_ICMP
            log disable
            protocol icmp
        }
        rule 2 {
            action accept
            description ALLOW_DNS
            destination {
                port 53
            }
            log disable
            protocol tcp_udp
        }
    }
    name WAN_IN {
        default-action drop
        description "WAN to internal"
        rule 10 {
            action accept
            description "Allow established/related"
            state {
                established enable
                related enable
            }
        }
        rule 20 {
            action drop
            description "Drop invalid state"
            state {
                invalid enable
            }
        }
    }
    name WAN_LOCAL {
        default-action drop
        description "WAN to router"
        rule 10 {
            action accept
            description "Allow established/related"
            state {
                established enable
                related enable
            }
        }
        rule 20 {
            action drop
            description "Drop invalid state"
            state {
                invalid enable
            }
        }
    }
    receive-redirects disable
    send-redirects enable
    source-validation disable
    syn-cookies enable
}
interfaces {
    ethernet eth0 {
        address 192.168.11.1/24
        description "Local 2"
        duplex auto
        speed auto
    }
    ethernet eth1 {
        address dhcp
        description Internet
        duplex auto
        firewall {
            in {
                name WAN_IN
            }
            local {
                name WAN_LOCAL
            }
        }
        speed auto
    }
    ethernet eth2 {
        description Local
        duplex auto
        speed auto
        vif 10 {
            address 192.168.10.1/24
            description VLAN10
            mtu 1500
        }
        vif 20 {
            address 192.168.20.1/24
            description VLAN20
            firewall {
                in {
                    name VLAN20_IN
                }
                local {
                    name VLAN20_LOCAL
                }
            }
            mtu 1500
        }
    }
    ethernet eth3 {
        description Local
        duplex auto
        speed auto
    }
    ethernet eth4 {
        description Local
        duplex auto
        poe {
            output off
        }
        speed auto
    }
    loopback lo {
    }
    switch switch0 {
        address 192.168.2.1/24
        description Local
        mtu 1500
        switch-port {
            interface eth3 {
            }
            interface eth4 {
            }
            vlan-aware disable
        }
    }
}
service {
    dhcp-server {
        disabled false
        hostfile-update disable
        shared-network-name LAN2 {
            authoritative disable
            subnet 192.168.2.0/24 {
                default-router 192.168.2.1
                dns-server 192.168.2.1
                lease 86400
                start 192.168.2.21 {
                    stop 192.168.2.240
                }
            }
        }
        shared-network-name VLAN10 {
            authoritative disable
            subnet 192.168.10.0/24 {
                default-router 192.168.10.1
                dns-server 192.168.10.1
                lease 86400
                start 192.168.10.20 {
                    stop 192.168.10.50
                }
            }
        }
        shared-network-name VLAN20 {
            authoritative disable
            subnet 192.168.20.0/24 {
                default-router 192.168.20.1
                dns-server 192.168.20.1
                lease 86400
                start 192.168.20.20 {
                    stop 192.168.20.140
                }
            }
        }
        static-arp disable
        use-dnsmasq disable
    }
    dns {
        forwarding {
            cache-size 150
            listen-on eth0
            listen-on switch0
            listen-on eth2.10
            listen-on eth2.20
        }
    }
    gui {
        http-port 80
        https-port 443
        older-ciphers enable
    }
    nat {
        rule 5010 {
            outbound-interface eth1
            type masquerade
        }
    }
    ssh {
        port 22
        protocol-version v2
    }
}
system {
    host-name ubnt
    login {
        user ubnt {
            authentication {
                encrypted-password $1$geheim$geheim.
            }
            level admin
        }
    }
    ntp {
        server 1.ubnt.pool.ntp.org {
        }
        server 2.ubnt.pool.ntp.org {
        }
    }
    syslog {
        global {
            facility all {
                level notice
            }
            facility protocols {
                level debug
            }
        }
    }
    time-zone UTC
}


/* Warning: Do not remove the following line. */
/* === vyatta-config-version: "config-management@1:conntrack@1:cron@1:dhcp-relay@1:dhcp-server@4:
firewall@5:ipsec@5:nat@3:qos@1:quagga@2:suspend@1:system@4:ubnt-pptp@1:ubnt-udapi-server@1:
ubnt-unms@1:ubnt-util@1:vrrp@1:webgui@1:webproxy@1:zone-policy@1" === */
/* Release version: v1.10.9.5166958.190213.1952 */
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Benchmark&lt;/h2&gt;
&lt;p&gt;Ich habe Benchmarktests des Setups mit dem Programm iperf3 durchgeführt. 
Rechner im selben VLAN am Zyxel Switch lieferten erwartungsgemäß eine Bandbreite vom 940 Mbits/sec. Befinden sich zwei Rechner im selben LAN (switch0, eth3 und eth4) direkt am EdgeRouter X, so erhält man ebenfalls eine Bandbreite von 941 Mbits/sec.&lt;/p&gt;
&lt;p&gt;Muss der EdgerRoute-X zwischen IEEE 802.1q VLANs routen (hier VLAN10 und VLAN20), so bricht die Übertragungsgeschwindigkeit auf 168 Mbits/sec ein.&lt;/p&gt;
&lt;h2&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Mit beiden Geräten (EdgeRouter X und GS-1200-8) kann man für wenig Geld VLANs und mehr aufsetzen. Natürlich ist die Bandbreite im EdgeRouter X beschränkt. Es handelt sich ja um ein Einsteigermodell. Man muss für sich selbst entscheiden, ob diese Bandbreite für den Anwendungsfall hinreichend ist. Man hat jedenfalls relativ schnell eine Konfiguration stehen.&lt;/p&gt;
&lt;p&gt;Eine echte Alternative wäre es aber auch mit diesen Erkenntnissen ein Standard Linux oder OpenBSD aufzusetzen. Hier hätte man noch mehr Freiheitsgrade und befände sich in heimischen Gefilden.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.ubnt.com/t5/EdgeRouter/ssh-authorized-keys/td-p/458361"&gt;https://community.ubnt.com/t5/EdgeRouter/ssh-authorized-keys/td-p/458361&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stevejenkins.com/blog/2015/10/install-an-ssl-certificate-on-a-ubiquiti-edgemax-edgerouter/"&gt;https://www.stevejenkins.com/blog/2015/10/install-an-ssl-certificate-on-a-ubiquiti-edgemax-edgerouter/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.magenbrot.net/netzwerk/router_hardware/edgemax/dualstack_ipv6_mit_1_1_auf_dem_edgerouter_poe_5-port"&gt;https://wiki.magenbrot.net/netzwerk/router_hardware/edgemax/dualstack_ipv6_mit_1_1_auf_dem_edgerouter_poe_5-port&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.freifunk-dresden.de/index.php/Ubnt_EdgeRouter-X"&gt;https://wiki.freifunk-dresden.de/index.php/Ubnt_EdgeRouter-X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=D-Cw5VHAL8M"&gt;Ubiquiti Routing and Switching Basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content></entry><entry><title>Internet Relay Chat (IRC)</title><link href="http://www.mueslihq.de/techblog/irc/" rel="alternate"/><updated>2018-08-08T00:00:00Z</updated><author><name>Robin Schubert</name></author><id>urn:uuid:ec155fd7-fb2f-3604-a76f-3419f2723c49</id><content type="html">&lt;p&gt;&lt;a href="https://de.wikipedia.org/wiki/Internet_Relay_Chat"&gt;IRC&lt;/a&gt; ist ein &lt;del&gt;altes&lt;/del&gt; schlankes, praktisches und lang etabliertes Chat System, dass seit 30 Jahren Menschen in aller Welt verbindet die sich ueber alle Arten von Problemen austauschen und gegenseitig helfen (oder einfach chatten). Es ist schnell und unkompliziert, benoetigt kaum Bandbreite und durch den offenen Webstandard gibt es fuer alle denkbaren Betriebssysteme eine Fuelle an Clients zur Auswahl.&lt;/p&gt;
&lt;h2&gt;Schneller Start - Beitreten in den #muesli channel&lt;/h2&gt;
&lt;p&gt;Um schnell loslegen zu koennen muessen drei Schritte durchgefuehrt werden (die in der Regel nach Konfiguration des Clients automatisch geschehen):&lt;/p&gt;
&lt;h3&gt;1. Auswaehlen eines Nicknames&lt;/h3&gt;
&lt;p&gt;Jeder Nutzer braucht einen Nick. Dieser muss nicht zwanglaeufig irgendwo registriert werden; fuer einen schnellen Start kann ein beliebiger Name gewaehlt werden, vorrausgesetzt zum Zeitpunkt der Anmeldung am Server existiert kein zweiter gleichnamiger Nick auf diesem Server.
Trotzdem ist eine Registrierung moeglich um den eigenen Nick zu sichern. Mehr dazu weiter unten.&lt;/p&gt;
&lt;h3&gt;2. Verbinden mit dem Server&lt;/h3&gt;
&lt;p&gt;Es existieren unzaehlige Netzwerke und Server, und auch das Aufsetzen eines eigenen IRC Servers ist schnell gemacht. Ein populaerer Server auf dem man insbesondere mit GNU/Linux Fragen oft fuendig wird war lange Zeit freenode.net, heute abgeloest durch libera.chat, ein Server der sich FOSS Support auf die Fahne geschrieben hat. Hier findet man auch unseren #muesli Channel.&lt;/p&gt;
&lt;h3&gt;3. Beitreten in einen oder mehrere Channel(s)&lt;/h3&gt;
&lt;p&gt;Channels oder Chat Raeume starten mit einer oder mehreren Rauten &lt;code&gt;#&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In UI Clients wird in der Regel beim Start eine Liste von verfuegbaren Servern angezeigt von denen sich der Nutzer einen auswaehlt. IRC laesst sich aber auch prima ueber text Kommandos steuern. Ist man mit einem Server verbunden kann man mit einem einfachen &lt;code&gt;/join #muesli&lt;/code&gt; unserem Channel beitreten.&lt;/p&gt;
&lt;h2&gt;Clients&lt;/h2&gt;
&lt;p&gt;Da das Protokoll ein freier Standard ist, gibt es eine ganze Reihe von Clients die sich hauptsaechlich im look-and-feel voneinander unterscheiden. Zu den beliebtesten gehoeren:&lt;/p&gt;
&lt;h3&gt;Graphische Oberflaeche&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hexchat&lt;/li&gt;
&lt;li&gt;XChat&lt;/li&gt;
&lt;li&gt;Quassel (KDE)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Text Basiert&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;weechat (editor's choice)&lt;/li&gt;
&lt;li&gt;irssi&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Warum schreibt mir nie einer zurueck?&lt;/h2&gt;
&lt;p&gt;Um moeglichen Frust im Keim zu ersticken, hier ein paar Tips:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Stay online: Wenn du schon mal verzweifelt genut warst um in einem IRC Channel eine Frage zu stellen kennst du vielleicht das Phaenomen; der Channel ist voller Nutzer und keiner schreibt zurueck. Tatsaechlich haengen die wenigsten 24/7 vor dem Bildschirm und warten darauf das jemand in den Channel schreibt. Oft ist Geduld gefragt, teilweise soll es Menschen auf der Welt geben die sogar schlafen waehrend wir hier Arbeiten. Bleib online und verbunden wenn es geht, und warte auf Antwort.&lt;/li&gt;
&lt;li&gt;Manche Leute fuehlen sich etwas auf den Schlips getreten wenn man in den Channel kommt, seine Frage hinklatscht und direkt wieder verschwindet. Es schadet nicht kurz &lt;em&gt;hallo&lt;/em&gt; zu sagen, immerhin betritt man einen Raum.&lt;/li&gt;
&lt;li&gt;Frage nicht ob du eine Frage stellen darfst. Frage einfach.&lt;/li&gt;
&lt;li&gt;Gib Hintergrundinformationen um deine Frage verstaendlich zu machen. Die Wahrscheinlichkeiten eine gute Antwort zu bekommen steigen rasant mit der Qualitaet der Frage.&lt;/li&gt;
&lt;li&gt;Spamme nicht den Channel mit seitenweise Fehlermeldungen und Programmcode etc. Wenn du laengeren Text hast den du teilen moechtest, benutze einen Pastebin Service wie &lt;a href="https://pastebin.com/"&gt;pastebin.com&lt;/a&gt; und poste den entsprechenden Link dazu in den Channel.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Sicherheit und Nicknames&lt;/h2&gt;
&lt;p&gt;Um einen Nickname auf libera.chat zu registrieren wendet man sich an einen speziellen Bot der &lt;code&gt;NickServ&lt;/code&gt; heist. &lt;code&gt;NickServ&lt;/code&gt; kann im Zweifelsfall sagen ob ein Nick schon in Benutzung ist, falls nicht kann man ihn sich Passwort-geschuetzt registrieren. Auch mehrere Nicks unter einem Account sind moeglich.&lt;/p&gt;
&lt;p&gt;Sollte der eigene Nick bei Verbinden doch in Benutzung sein (sei es durch einen anderen Nutzer oder durch eine andere eigene Verbindung) kann man ihn sich ueber &lt;code&gt;NickServ&lt;/code&gt; zurueckfordern. Bei seinem Client hinterlegt man trotzdem in der Regel 2 - 3 Backup Nicknames falls der primaere schon vergeben ist. Die volle Prozedur der Nick-Registrierung kann man &lt;a href="https://libera.chat/guides/registration"&gt;hier&lt;/a&gt; lesen.&lt;/p&gt;
&lt;p&gt;Per default ist die Uebertragung in IRC ungesichert und plain text. Im Client kann man aber auf SSL/TLS Verschluesselung umstellen oder bei Bedarf auch Tor als Proxy einstellen. Auch die &lt;em&gt;Anmeldung&lt;/em&gt; bei &lt;code&gt;NickServ&lt;/code&gt; kann via SASL verschluesselt werden.&lt;/p&gt;
&lt;h2&gt;Update 2021-05-26&lt;/h2&gt;
&lt;p&gt;Leider gibt es auch im IRC immer mal wieder Kaempfe um Macht und Einfluss; eine grosse Community von Entwicklern und Software Interessierten zu beherbergen ist dabei sicherlich etwas worum es sich zu kaempfen lohnt. Im Fall des Freenode Netzwerkes hat es gerade einen Machtwechsel gegeben, der potentiell die Freiheiten und Privatsphaeren der Nutzer einschraenkt oder angreift. Die meisten der langjaehrigen Voluntaere des Netzwerkes, sowie auch die Communities haben sich daher von Freenode verabschieded und sind zu dem neu gegruendeten libera.chat Netzwerk gewechselt.&lt;/p&gt;
&lt;p&gt;Ich habe die Links und Text-Passagen in diesem Artikel entsprechend angepasst, moeglichst ohne die originalen Referenzen auf Freenode ganz zu entfernen.&lt;/p&gt;
</content></entry><entry><title>Bau der MueSLi-Homepage mit Git/Gitolite/lektor und ein paar Skripten</title><link href="http://www.mueslihq.de/techblog/muesli-deployment/" rel="alternate"/><updated>2018-05-04T00:00:00Z</updated><author><name>Frank Rocholl</name></author><id>urn:uuid:a3f54376-7ed3-3e7a-85ca-69c951a6abad</id><content type="html">&lt;p&gt;Nachdem die MueSLi-Homepage schon etwas in die Jahre gekommen ist, haben wir auf unseren Stammtisch den Entschluß gefasst, eine neues Webteam zu bilden und die Homepage mit einfachen Mitteln in das neue Jahrtausend zu führen.&lt;/p&gt;
&lt;h2&gt;Anforderungen&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Editieren soll auch Offline möglich sein&lt;/li&gt;
&lt;li&gt;Jeder aus dem Webteam soll eigenständig live stellen können&lt;/li&gt;
&lt;li&gt;KISS-Prinzip: Einfach aber genial&lt;/li&gt;
&lt;li&gt;Lizenzrechtlich einwandfrei und (allmost) Stallmann kompatibel&lt;/li&gt;
&lt;li&gt;Mehrstufiges Deployment-Modell&lt;/li&gt;
&lt;li&gt;Multiuserfähig: Mehrere Autoren können editieren&lt;/li&gt;
&lt;li&gt;Mobilefähig und Lynxkonform&lt;/li&gt;
&lt;li&gt;Offene Standards&lt;/li&gt;
&lt;li&gt;Optional muss es möglich sein, ein einfaches Rollenkonzept und einen Freigabemnechanismus zu implementieren&lt;/li&gt;
&lt;li&gt;Revisionssicher: Man kann alte Versionen nicht mehr löschen&lt;/li&gt;
&lt;li&gt;Sicher auf dem Server (keine kruden Frameworks oder andere Sicherheitsprobleme)&lt;/li&gt;
&lt;li&gt;Trennung von Content (gern Markdown a.Ä.) und Layout&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Implementierung&lt;/h2&gt;
&lt;p&gt;Die Verwaltung der Homepage erfolgt gleichberechtig von allen Mitgliedern des &lt;a href="mailto:muesli-webteam138@mueslihq.de"&gt;Webteams&lt;/a&gt;. Jeder pflegt Webseiten auf seinem lokalen PC und checkt diese dann in ein zentrales Git-Repository ein.&lt;/p&gt;
&lt;h3&gt;MuesLi-Branching-Modell&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;master-Branch:&lt;/strong&gt; In diesem sollten alle Daten gemerged werden, die Bestand haben sollen. Man kann keine Versionen aus diesem Branch löschen sondern nur Neue erzeugen. Ein Rebase ist nicht erlaubt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;dev-Branch:&lt;/strong&gt; (wird ausgecheckt unter dev.mueslihq.de):  Dieser Branch steht für die (Web)-Entwickler zur Verfügung. Will man als (Web)-Entwickler mit den Anderen Dinge diskutieren kann man sagen: "Schau Dir mal die DEV" an. Per Definition kann der Branch auch mal kaputt sein.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;qual-Branch:&lt;/strong&gt; (wird ausgecheckt unter qual.mueslihq.de): Hier kann man anderen  (Nicht Entwicklern) sagen: "Schau Dir mal die Inhalte an. Ist das OK so?"&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;prod-Branch:&lt;/strong&gt; (wird ausgecheckt unter &lt;a href="https://mueslihq.de"&gt;https://mueslihq.de&lt;/a&gt;). Das ist unsere Live Homepage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;archive-Branch:&lt;/strong&gt; Die Branch beinhaltet nicht mehr gültige, oder noch nicht noch nicht veröffentlichungswürdige Dokumente. Dieser Branch kann nicht zurückgespult werden und dient als Archiv.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Daneben kann es Interims-Branches geben (wie z.B. lektor_vorschlag). Die kann man später wieder löschen.&lt;/p&gt;
&lt;h3&gt;Rechteverwaltung mit Gitolite&lt;/h3&gt;
&lt;p&gt;Im Gitolite kann man mit wenigen Zeilen das Rechtekonzept umsetzen. Hier Auszüge aus der &lt;code&gt;gitolite.conf&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;repo www.mueslihq.de
    RW+        = webteam-member1@mueslihq.de webteam-member2@mueslihq.de webteam-member3@mueslihq.de
    RW master  = webteam-member1@mueslihq.de webteam-member2@mueslihq.de webteam-member3@mueslihq.de
    RW archive = webteam-member1@mueslihq.de webteam-member2@mueslihq.de webteam-member3@mueslihq.de
    R          = auschecker@mueslihq.de
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Praxisbeispiel: Erstellung einer neuen Webseite&lt;/h3&gt;
&lt;p&gt;Will man die MueSLi-Webseite editieren, so ist diese zuerst aus der Versionsverwaltung auszuchecken:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git clone git@git.hottemax.org:www.mueslihq.de
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will man eine tolle Änderung, so erstellt man sich zuerst einen eigenen Branch auf Basis des master-Branches:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git checkout -b tolle-aenderung 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hier kann man nach Belieben editieren. Änderungen sind mit &lt;code&gt;git commit -a&lt;/code&gt; zu committen.&lt;/p&gt;
&lt;p&gt;Ist die Modifikation abgeschlossen, so ist der neuen Zweig in den master-Branch zu mergen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git checkout master
git merge tolle-aenderung
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will man die Änderungen auf dem Entwicklungsserver dev.mueslihq.de checken, so ist der Branch in den dev-Branch zu überführen und auf den Server zu pushen.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git checkout dev
git merge master
git push origin dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Analog ist mit dem qual-Branch zu verfahren. Das Ergebnis kann man sich anschauen unter qual.mueslihq.de.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git checkout qual
git merge master
git push origin qual
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wenn dann alles OK ist, kann man die MuesLi-Homepage &lt;a href="https://mueslihq.de"&gt;https://mueslihq.de&lt;/a&gt; erzeugen mittels:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git checkout prod
git merge master
git push origin prod
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Es ist nicht notwendig den gesamten Lebenszyklus eines Dokumentes zu durchschreiten. Man kann natürlich direkt den master-Branch mit dem prod-Branch mergen, wenn keine weitere Person sich die Änderungen angucken muß.&lt;/p&gt;
&lt;p&gt;Im master-Branch sind ja alle Änderungen festgeschrieben und man kann immer wieder zurück, wenn es den andern Mitgliedern des MueSLi-Webteams nicht gefällt.&lt;/p&gt;
&lt;h3&gt;Anpassungen für Lektor im Betriebssystem&lt;/h3&gt;
&lt;p&gt;Betreibt man Lektor auf seiner Workstation im server-Modus (&lt;code&gt;lektor server&lt;/code&gt;),
so kann es in seltenen Fällen Probleme mit der Höhe des "inotify watch limit"s geben.  Der Standardwert von 8192 ist manchmal zu klein (&lt;code&gt;cat /proc/sys/fs/inotify/max_user_watches&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Man kann diesen Wert jedoch einfach erhöhen:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sysctl fs.inotify.max_user_watches=524288
sysctl -p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Weitere Details dazu gibt es &lt;a href="https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers"&gt;hier&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Skripte auf dem Server&lt;/h3&gt;
&lt;p&gt;In das Deployment sind 2 Server involviert:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ehli6 trägt das git repository und baut mit Lektor die Seiten&lt;/li&gt;
&lt;li&gt;ehli9 serviert die Webseiten und hosted die &lt;a href="../../mailinglist/"&gt;Mailingliste&lt;/a&gt;. Die Webseiten sind rein statisch. Der Webserver spricht kein PHP (&lt;code&gt;php_value engine off&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nach  der Generierung der statischen Seiten werden noch dynamische Inhalte, wie Anzahl der MueSLis-Mitglieder, hinzu gerendert. Der funktionale User &lt;em&gt;muesli-macher&lt;/em&gt; lässt um 00:01h das Skript &lt;code&gt;muesli-daily.sh&lt;/code&gt; laufen. Dieses&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generiert den &lt;a href="../../mailinglist/statistik/"&gt;MueSLi-Members-Plot&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;generiert ggf. das &lt;a href="../../stammtisch/"&gt;Stammtisch Datum&lt;/a&gt; neu.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alle Änderungen werden automatisiert in den Lektor Dateien gemacht und dann ins &lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; in den master und prod branch eingecheckt. Der Automat rendert daraus wieder statische HTML-Dateien.
So stellt man sicher, dass jede Änderung revisionssicher ist.&lt;/p&gt;
&lt;p&gt;Auf dem Git-Server läuft ein Hook, der bei einem push mittels  &lt;code&gt;lektor build $DOCUMENT_ROOT&lt;/code&gt; die Webseiten rendert und diese dann auf den eigentlichen Web-Server synchronisiert.&lt;/p&gt;
</content></entry><entry><title>Linux Distribution</title><link href="http://www.mueslihq.de/techblog/distribution/" rel="alternate"/><updated>2018-04-23T00:00:00Z</updated><author><name>Markus Berger</name></author><id>urn:uuid:7067577b-e656-3cb1-a908-f22e991d6cc6</id><content type="html">&lt;h3&gt;Einleitung&lt;/h3&gt;
&lt;p&gt;Eine Frage, die sich jeder Linuxbenutzer, stellt, ist, welche
Linux-Distribution die richtige ist? Obwohl die Frage lauten sollte, welche
Distribution für meine Anwendung(en) und/oder meinen Einsatz die richtige ist?
Und weshalb gibt es überhaupt soviele Distributionen?&lt;/p&gt;
&lt;p&gt;Diese Fragen kann man sich mit der Entstehungsgeschichte von Linux, dem
Betriebssystem-Kern gut erklären, denn dieser ist freie Software und somit
offen für alle, die daran mitarbeiten möchten, stellt jedoch nur die
Schnittstellen für POSIX-kompatible Programme über Systemaufrufe zur
Verfügung, nicht aber die Programme selbst. Um ein benutzbares System zu
erhalten, benötigt man aber eben diese Programme. Linus hat sich hier
traditionell bei GNU bedient, welches genau diese Programme ebenfalls als freie Software
bereitstellt.&lt;/p&gt;
&lt;p&gt;Da nun die Programme (Userland) und Linux (Kernel) von
unterschiedlichen Personen entwickelt und gepflegt werden, sind auch die
Prioritäten und Entwicklungsgeschwindigkeiten unterschiedlich. Dies stellt die
Anwender vor die Herausforderung, die passenden Teile sinnvoll und richtig zu
kombinieren, um ein für den Einsatzzweck lauffähiges System zu erhalten. Dies
wurde schon sehr zeitig erkannt und so bildeten sich die ersten Distributoren,
welche genau diese konsistente Zusammenstellung leisteten. Sie stellten also
eine für die angegebene Plattform aus freien Quellen zusammengebaute Programme
und den Kern in Binärformat bereit, und verkauften die Datenträger.&lt;/p&gt;
&lt;h3&gt;Paketmanager&lt;/h3&gt;
&lt;p&gt;Da die Wartung eines Systems, das Software aus vielen verschiedenen Quellen verwendet, die wiederum über komplexe Abhängigkeiten miteinander verbunden sind, eine Herausforderung ist, entstanden die Paketmanager. Diese Software
kümmert sich darum, alle zu einem Programm gehörenden Dateien in einem Paket zusammenzufassen, mit keinen anderen Dateien eines anderen Paketes zu kollidieren
und idealerweise auch, dass alle erforderliche Software (Bibliotheken) zur Verfügung steht, um selbst lauffähig zu
sein (Abhängigkeiten).&lt;/p&gt;
&lt;p&gt;Mit Hilfe eines Paketmanagers ist es nun viel leichter, eine Zusammenstellung
von konsistenter Software zu gewährleisten und damit eine Distribution zu
erstellen.&lt;/p&gt;
&lt;p&gt;Da die Anforderungen, die jede Aufgabe und/oder jeder an ein System hat, völlig
unterschiedlich und vielfältig sind, wie wir alle, entstanden also quasi
zwangsläufig neue Distributionen, die eben diese Anforderungen besser erfüllen
als die bestehenden.&lt;/p&gt;
&lt;h3&gt;GNU/Linux als Arbeitsplatz&lt;/h3&gt;
&lt;p&gt;Um hier nicht allzuweit in die Breite abzuschleifen, wird im weiteren nur
auf die Nutzung von GNU/Linux an einem klassischen Arbeitsplatz (PC/Laptop)
eingegangen.&lt;/p&gt;
&lt;p&gt;Hier sind zur Zeit zwei Modelle weitverbreitet, das Release-Model und das
Rolling-Modell.&lt;/p&gt;
&lt;h4&gt;Release-Modell&lt;/h4&gt;
&lt;p&gt;Hier erzeugten die Maintainer einer Distribution zu bestimmten Zeiten eine
Zusammenstellung der Software und ihrer Abhängigkeiten. Im Laufe der Zeit
werden z.B. in einzelnen Teilen Fehler gefunden und behoben, dabei wird aber
die Version der betroffenen Software (ihre Programmierschnittstelle, ABI z.B.
der c-Bibliothek) nicht angepasst. Der eigentliche Entwickler der Software
(upstream) macht aber das gleiche und erzeugt zusätzlich weitere Versionen, die
sich mit der Zeit deutlich unterscheiden.&lt;/p&gt;
&lt;p&gt;Von dieser Weiterentwicklung ist man dann als Nutzer der
Release-Linux-Distribution bis zum nächten Release abgeschnitten.&lt;/p&gt;
&lt;p&gt;Typische Vertreter diese Modells sind RedHat, Debian und davon abgeleitete
Distributionen.&lt;/p&gt;
&lt;p&gt;Trotz des Nachteils, mit alter Software zu arbeiten, gibt es Einsatzfälle wo
dies von Vorteil ist. Denn immer dann, wenn nicht freie Software eingesetzt werden muss, liegt diese meist nur im Binär-Format vor, wurde also mit
bestimmten Versionen anderer Software erzeugt und hängt auch oft davon ab.
Neuere Versionen der abhängigen Software führen in einem solchen Fall meist
dazu, dass speziell diese Software nicht mehr lauffähig ist. Deshalb
unterstützt z.B. RedHat eine Version über 10 Jahre.&lt;/p&gt;
&lt;p&gt;Als Privatanwender ist man davon im Allgemeinen nicht betroffen, doch sollte
man wenn möglich auf proprietäre Software verzichten.&lt;/p&gt;
&lt;h4&gt;Rolling-Modell&lt;/h4&gt;
&lt;p&gt;Bei diesem Modell wird die aktuelle Version der einzelnen Software
verwendet, die der Hersteller (upstream) veröffentlicht. Hier
gibt es natürlich je nach Distribution unterschiedliche Auffassungen, was eine
Version ist und welche genau verwendet wird.&lt;/p&gt;
&lt;p&gt;Da von dieser Software andere Software abhängig sein kann, müssen also nach der
Aktualisierung eines Teils, evtl. weitere Software (weitere Pakete) neu
übersetzt werden. Hier kommt der Paketmanager noch stärker zum Tragen, denn
über ihn müssen sich diese Pakete auch finden und bauen lassen.&lt;/p&gt;
&lt;p&gt;Der enorme Vorteil ist hier, dass man immer mit aktueller Software arbeiten
kann und der Entwicklung ohne Probleme folgt und eine aufwändige
Rückportierung über Patches nicht nötig ist. Die neuen Funktionen stehen
nach einem Neustart der Anwendung direkt zur Verfügung.&lt;/p&gt;
&lt;p&gt;Nachteilig ist, dass es quasi ständig neue Versionen gibt, das bedeutet ein höheres
Download-Volumen bei häufiger Aktualisierung.&lt;/p&gt;
&lt;p&gt;Typische Vertreter diese Modells sind ArchLinux und VoidLinux.&lt;/p&gt;
&lt;h3&gt;Welche Distribution?&lt;/h3&gt;
&lt;p&gt;Nun zurück zur ursprünglichen Frage, welche Distribution soll ich nehmen?
Darauf kann ich auch keine Antwort geben. Hier ist es sicherlich viel wichtiger,
in welchen Umfeld ich mich bewege. Es spricht auch nichts dagegen, verschiedene Distributionen/Versionen einfach auszuprobieren, denn wenn man seine Daten (/home) z.B. auf einer separaten Partition
oder auf einer eigenen Platte hält, kann man ohne weiteres die verschiedenen
Varianten testen und trotzdem seine Daten behalten.&lt;/p&gt;
&lt;p&gt;Also dann viel Spaß beim Ausprobieren und Stöbern, um dann zu einer eigenen
Entscheidung zu kommen.&lt;/p&gt;
</content></entry><entry><title>Statische Websites mit Lektor</title><link href="http://www.mueslihq.de/techblog/lektor/" rel="alternate"/><updated>2018-04-09T00:00:00Z</updated><author><name>Robin Schubert</name></author><id>urn:uuid:84148045-654f-39b6-ba56-43ffc6cc66cf</id><content type="html">&lt;p&gt;&lt;a href="https://www.getlektor.com/"&gt;Lektor&lt;/a&gt; ist ein Content Management System (CMS) das schnell einsetzbar ist, und erlaubt in einem praktischen File system einfach statische Webseiten zu bauen. Das CMS macht das Pflegen und Hinzufuegen von Inhalten auch ohne Programmierkenntnisse leicht.&lt;/p&gt;
&lt;p&gt;Die hervorragende &lt;a href="https://www.getlektor.com/docs/"&gt;Dokumentation&lt;/a&gt; beinhaltet unter anderem Anleitungen fuer verschiedene Design-Beispiele die extrem hilfreich sind und auf die auch dieser Blog aufgebaut wurde.&lt;/p&gt;
&lt;p&gt;Diese gesamte Seite wird mit Lektor betrieben und gepflegt, und wer gerne ein deutsches Tutorial haette wird in diesem Post vielleicht fuendig.&lt;/p&gt;
&lt;h2&gt;Die Funktionsweise&lt;/h2&gt;
&lt;p&gt;Damit Lektor eine Webseite rendern kann benoetigt es mindestens ein Model, ein Template und ein Lektor-File (.lr) mit den entsprechenden Inhalten.&lt;/p&gt;
&lt;h3&gt;Models&lt;/h3&gt;
&lt;p&gt;Models sind in Lektor &lt;code&gt;.ini&lt;/code&gt; Dateien, in denen Felder und Eigenschaften deklariert werden welche die zukuenftige Seite haben soll. Das koennen bestimmte Variablen sein wie z.B.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Titel&lt;/li&gt;
&lt;li&gt;Inhalt&lt;/li&gt;
&lt;li&gt;Datum&lt;/li&gt;
&lt;li&gt;Author&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Die Felder werden jeweils mit dem entsprechenden Datentypen deklariert, wie &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;integer&lt;/code&gt;, &lt;code&gt;date&lt;/code&gt;, &lt;code&gt;markdown&lt;/code&gt; etc. Im Admin Bereich von Lektor koennen dann Instanzen des Models erstellt und mit Inhalt gefuellt werden. Natuerlich kann man auch ganz auf den Admin Bereich verzichten und direkt in plain text schreiben.&lt;/p&gt;
&lt;p&gt;Das Model das fuer diese Seite genutzt wird sieht in etwa so aus:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[model]
name = Blog Post
label = {{ this.title }}

[fields.title]
label = Title
type = string

[fields.pub_date]
label = Publication date
type = date

[fields.author]
label = Author
type = string

[fields.body]
label = Body
type = markdown
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fuer jedes Feld muss es mindestens die Attribute &lt;code&gt;label&lt;/code&gt; und &lt;code&gt;type&lt;/code&gt; geben, damit im Lektor Admin Bereich eine entsprechende Instanz erstellt werden kann.&lt;/p&gt;
&lt;h3&gt;Templates&lt;/h3&gt;
&lt;p&gt;Als Template Engine verwendet Lektor &lt;a href="http://jinja.pocoo.org/"&gt;Jinja2&lt;/a&gt;, eine sehr flexible und effektive Mischung aus HTML und Python. Jinja2 erlaubt das einbinden von einfacheren Schleifen oder &lt;code&gt;If-Else&lt;/code&gt; Bedingungen und auch Zugriff auf die im Model deklarierten Variablen und Eigenschaften, direkt zwischen dem HTML code.&lt;/p&gt;
&lt;p&gt;Per Konvention soll jedes Template denselben Namen haben wie das dazugehoerige Model. Lektor erlaubt allerdings auch das manuelle Festlegen von unterschiedlichen Templates und Models, was allerdings nur begrenzt sinnvoll ist.&lt;/p&gt;
&lt;p&gt;Dieses uebersichtliche Template wird aktuell fuer diese Seite genutzt:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{% extends "layout.html" %}
{% block title %}{{ this.title }} | News {% endblock %}
{% block body %}
&amp;lt;h1&amp;gt;{{ this.title }}&amp;lt;/h1&amp;gt;
&amp;lt;p class="meta" &amp;gt;
    von {{ this.author }}
    am {{ this.pub_date|dateformat('full') }}
    &amp;lt;div class="body"&amp;gt;
        {{ this.body }}
    &amp;lt;/div&amp;gt;
&amp;lt;/p&amp;gt;
{% endblock %}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jinja2 ermoeglicht Vererbung; in der ersten Zeile wird zunaechst auf das zu erweiternde Master Template referenziert. Das Master Template definiert einige &lt;code&gt;Blocks&lt;/code&gt; deren Inhalte hier festgelegt werden. Das erspart unnoetige Wiederholung von Code. Das Master Template beinhaltet ausserdem noch weiteren HTML code wie z.B. den gesamten Header mit allen CSS Referenzen und Meta-Informationen und das rohe Skelett.&lt;/p&gt;
&lt;p&gt;Auf Variablen und Felder kann zwischen zwei geschweiften Klammern &lt;code&gt;{{ ... }}&lt;/code&gt; zugreifen, Schleifen und weitere Jinja2 Kommandos landen zwischen geschweiften Klammern und Prozent Zeichen &lt;code&gt;{% if condition %} ... {% endif %}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Haeufig genutzte Jinja2-Snippets lassen sich auch als Makros auslagern und in verschiedene Templates importieren.&lt;/p&gt;
&lt;h3&gt;Contents.lr&lt;/h3&gt;
&lt;p&gt;Wie der Name erahnen laesst befinden sich die eigentlchen Inhalte der Webpages in den Dateien mit dem Namen &lt;code&gt;Contents.lr&lt;/code&gt;. Die einzelnen Webseiten werden in je einem Ordner pro Seite verwaltet, jeder Ordner enthaelt dabei eine &lt;code&gt;Contents.lr&lt;/code&gt; Datei und wahlweise verschiedene Anhaenge und Bilder die in der entsprechenden Seite gezeigt bzw. verfuegbar gemacht werden sollen.&lt;/p&gt;
&lt;p&gt;Diese Dateiverwaltung kann man leicht haendisch uebernehmen, wird aber fuer weniger versierte Nutzer auch von dem dem Lektor Admin uebernommen.&lt;/p&gt;
&lt;p&gt;Die Felder des zu Grunde liegenden Models werden dabei ueber &lt;code&gt;key: value&lt;/code&gt; Paare zugewiesen wie in diesem Beispiel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;_model: blog-post
---
title: Lektor
---
author: Robin Schubert
---
pub_date: 2018-04-09
---
body:

Hier steht der Inhalt als Markdown vormatiert, wie im Model-Type angegeben.
---
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Dateistruktur&lt;/h3&gt;
&lt;p&gt;Um ein neues Projekt zu initialisieren, erstellt Lektor die benoetigte auf Wunsch voll automatisch ueber die Kommandozeile: &lt;code&gt;lektor quickstart&lt;/code&gt; fragt einige Parameter wie z.B. den Namen und Pfad des Projektes ab und erstellt folgende Dateien:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;├── assets
│   └── static
│       └── style.css
├── content
│   ├── about
│   │   └── contents.lr
│   ├── contents.lr
│   └── projects
│       └── contents.lr
├── models
│   └── page.ini
├── templates
│   ├── layout.html
│   ├── macros
│   │   └── pagination.html
│   └── page.html
└── MyProject.lektorproject
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Ansehen, Bauen und Verwalten der Seiten&lt;/h2&gt;
&lt;p&gt;Ueber den Befehl &lt;code&gt;lektor server&lt;/code&gt; laesst sich das Projekt leicht unter &lt;code&gt;localhost:5000&lt;/code&gt; ansehen. Lektor baut die Seite &lt;em&gt;on the fly&lt;/em&gt; in einem temporaeren Verzeichnis und aktualisiert solange der Server laeuft auch nach jeder Aenderung automatisch.&lt;/p&gt;
&lt;p&gt;In diesem Modus laesst sich nun auch der Admin Bereich aktivieren um ueber das Web Interface neue Seiten, Blog Posts etc. zu erstellen, und wahlweise die Aenderungen auch gleich auf den Deploy Server zu pushen.&lt;/p&gt;
&lt;p&gt;Sollen einfach nur statische HTML Seiten erstellt werden, reicht ein einfaches &lt;code&gt;lektor build&lt;/code&gt;, wahlweise mit option &lt;code&gt;--output-path&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Bis hierher&lt;/h2&gt;
&lt;p&gt;Die Moeglichkeiten sind selbstverstaendlich weitaus vielfaeltiger, und dieser Artikel kratzt gerade eben an der Oberflaeche. Dieser Post zielt allerdings nicht darauf ab, die bereits vorhandene &lt;a href="https://www.getlektor.com/docs/"&gt;Doku&lt;/a&gt; voll ins Deutsche zu uebersetzen, sondern soll vielleicht ein bisschen neugierig machen. Lektor bietet als CMS mehr Komfort als es vielleicht ein Flask Projekt geben koennte, kommt aber gleichzeitig mit deutlich weniger Overhead daher als ein Framework wie Django, und duerfte fuer viele eine attraktive Alternative sein, sowohl fuer kleinere Anwendungen wie den eigenen Blog als auch fuer grosse und professionelle Projekte.&lt;/p&gt;
</content></entry></feed>