As I was intending to create a nice multi-client configuration for Restic’s REST-server, I found that Debian comes with all I needed.
Note that this is a configuration that prioritizes automation and availability and at no point relies on interactive entering of passwords or passphrases or an ssh-/putty agent.
You MUST however keep note of a) how to access your backup medium and b) the restic repository passphrase.
REST-Server (on Linux)
For the BACKUP_DIR configuration in /etc/default/restic-rest-server, I’ll go with /var/lib/restic-rest-server:
# lvcreate, mkfs, fstab, mount etc...
chown restic-rest-server /var/lib/restic-rest-server
For good measure, I also add the –private-repos option in /etc/default/restic-rest-server, so every user will only be able to access repositories in the directory hierarchy matching their user name:
# TCP or UNIX listen address.
#LISTEN = unix:/run/restic-rest-server
LISTEN = :8000
# Directory to store backups.
# Note: the server will not start unless this variable is defined.
#BACKUP_DIR = /srv/backups/
BACKUP_DIR = /var/lib/restic-rest-server
# Extra arguments to pass to the server. Run `restic-rest-server --help` to see
# available options. By default, basic authentication is enabled.
ARGS = "\
--htpasswd-file /etc/restic-rest-server/users.htpasswd \
--private-repos \
"
An HTTP password for my user mas needs to be set and my user’s backup location created:
htpasswd -B /etc/restic-rest-server/users.htpasswd mas
install -o restic-rest-server -d /var/lib/restic-rest-server/mas
restic-rest-server.service can be started now.
I’m lazy, so I didn’t configure TLS but configured a reverse proxy into a TLS web server that was already running:
I have added the directory containing the restic.exe binary to the Windows PATH environment, and also maintain restic configuration as environment variables:
The repository passphrase is in restic-pw.txt,
the URL for the repository in restic-url.txt, and
the list of files to back up in restic-include.txt (no environment for this one).
Note that while Windows has awful file system issues with files locked while open for reading, restic has the ability to create and work on a volume shadow copy on the fly, provided it runs with elevated privileges:
For running restic on a schedule, I use the operating system’s built-in Task Scheduler.
Restic on Windows does NOT allow mounting the backups the ways it does on Linux. For browsing the backups on Windows, I therefore use Restic Browser which just springs to life without any configuration, provided the environment variables are in place.
Soviel wusste ich schonmal: Das Trinkwasser wird aktiv in die bekannten Hochbehälter gepumpt, und spätestens sobald die leer sind, fällt es aus. Vermutlich ist das auch gut so, denn die Kläranlage funktioniert bei Stromausfall schließlich ebenfalls nicht.
Ich habe das Thema zunächst vergessen und als ich dann mal wieder am Hochbehälter spazierenging, war die Frage erneut da: Wo kommt eigentlich das Wasser her?
Die wenigen Fakten
An den aktiven und historischen Hochbehältern hier in Pohlheim stehen Schautafeln, die aber in erster Linie die (gar nicht mal uninteressante) Historie beleuchten und nicht so wirklich auf die aktuellen Gegebenheiten eingehen. Ein paar Eckpunkte lassen sich hier aber ablesen:
Das Wasser kommt seit den 1960er Jahren nicht mehr aus Quellen vor Ort, sondern aus dem 50 km entfernten Wasserwerk Stadtallendorf.
Die Leitung in meine Stadt zweigt an einem bekannten Industriebetrieb mitten im Wald von der Fernleitung ab.
Das sind erste Kristallisationspunkte, an denen man andocken kann.
Umfangreiches Klicken brachte einen Netzplan des Zweckverbands Mittelhessischer Wasserwerke zutage, von dem ich lernte, dass Wasserleitungen Nummern zur Identifikation haben, und dass es Wasserleitungen gibt, die vom Zweckverband betrieben werden und welche, die von der Stadt betrieben werden. Mich interessierten vor allem die vom Zweckverband betriebenen Fernleitungen, die jeweils an der Stadgrenze enden, ab wo es mit Hausanschlüssen und Hydranten weitergeht.
Auf dem Netzplan tauchten auch zum ersten mal die von mir in ihrer Existenz lediglich vermuteten Pumpwerke, im Fachjargon Druckerhöhungsanlagen, auf. Eine kleine, klar zum älteren aber noch aktiven Hochbehälter gehörende, die das Wasser in den höher gelegenen neuen Hochbehälter pumpt, und eine größere irgendwo im Süden von Gießen.
Zeichen lesen
Weiß man erst einmal, dass die Leitungen Nummern haben, erkennt man auf den kleinen blauen Wasserschildern, mit denen alle Armaturen oberirdisch beschriftet sind, leicht eine organisatorische Nummer, die immer die Nummer der jeweiligen Leitung beinhaltet. Mit dem eher abstrakten Netzplan bewaffnet, konnte ich dann relativ gut ausschließen, was links und was rechts der Leitung liegt, Annahmen über den weiteren Verlauf der Leitung treffen und immer mehr unterirdische Standorte identifizieren, die Rückschluss auf den Leitungsverlauf erlauben. Mit etwas numerologischem Gefühl kann man anhand zweier Nummern auch bewerten, ob man dazwischen noch einen Standort übersehen hat.
Die Kürzel der Wasserschilder hinsichtlich des Typs der jeweiligen Armatur sind mir leider bis zuletzt ein Rätsel geblieben, denn es existiert hier vor Ort *keine* Schnittmenge (also wirklich Null) mit dem, was jemand auf Wikipedia dazu aufgeschrieben hat.
Nachdem die Umgebung des Hochbehälters zu Fuß erkundet war, gab es keine Ausreden mehr, und es musste mit dem Fahrrad querfeldein gehen.
Bei dieser Spurensuche hat sich eine ganz wichtige Grundregel entwickelt: Die Leute vom Wasserwerk wollen und müssen mit ihrem blauen Werkstattwagen überall direkt ran. Jeder einzelne Standort, den ich identifiziert habe, ist (wenn auch nicht öffentlich) mit einem nicht geländegängigen Auto anfahrbar. Auf einem kaum passierbaren Trail mitten in der Wildnis wird man niemals Wasserarmaturen finden.
Ich habe also angefangen, mir ein paar der dünn gesäten Beispiele zu suchen, das ganze mit dem OSM-Wiki abgeglichen und angefangen, wie folgt zu taggen:
Armaturen
diameter=x
operator=ZMW
pipeline=valve
ref=x.y
substance=water
note=x (Kürzel und Durchmesserangabe des Schilds)
Ganz fehlende Hydranten auf Hauptleitungen aufgenommen
Gegebenenfalls note=Blauer Rand für Hydranten, die nicht ohne weiteres von der Feuerwehr zur Wasserentnahme benutzt werden dürfen.
Falschzuordnung Unter-/Überflurhydrant berichtigt
Wenn ergänzt wurde, dann auch Durchmesser und Referenznummer dazu.
Hier die von mir kartierten Relationen:
ZMW 1.1, die aus Richtung Wetzlar kommende und östlich von Gießen verlaufende Fernleitung nach Stadtallendorf
ZMW 2.7, die von ZMW 1.1 abzweigende westlich von Gießen verlaufende Fernleitung nach Stadtallendorf
ZMW 5.9, die von ZMW 1.1 abzweigende Hauptleitung zu meinem Wohnort
ZMW 3.14, eine zu einer südlich gelegenen Kommune weiterführende Leitung, die auch die beiden Hochbehälter verbindet
ZMW 3.15, eine redundante Leitung zwischen den Hochbehältern
ZMW 4.15, eine zu den östlichen Stadtteilen führende Leitung
ZMW 4.16, eine zu den südlichen Stadtteilen führende Leitung
ZMW 4.18, eine zu den nördlichen Stadtteilen führende Leitung, von der ich vermute, dass sie auch die Anbindung der sogenannten “Hochdruckzone” der Stadt ist.
ZMW 1.5 in Richtung Lich hat mich nur interessiert, weil ihre Druckerhöhungsanlage so prominent im Wald zu sehen ist
Leitungsverläufe wurden grundsätzlich nur als direkte Verbindungen zwischen überirdisch gefundenen Armaturen kartiert, außer es war eine zweifelsfreie Aussage über den Verlauf möglich, wie etwa bei ZMW 1.5 auf der auffälligen Schneise im Stadtwald, sowie der SWG-Querverbindung entlang der Bahngleise und entlang des Aulweg, an dessen Kreuzung mit dem Wartweg zum Zeitpunkt meiner Erkundungen genau diese 600er Leitung der Querverbindung gebrochen war.
Druckerhöhungsanlagen
Die Schnittstelle zwischen ZMW 1.1, ihrer Querverbindung, und ZMW 2.7 hat mir ein paar Tage lang ziemliche Rätsel aufgegeben, weil sie sich an einem komplett unübersichtlichen gordischen Knoten zwischen Bahnlinien und mehreren autobahnänlichen Bundesstraßen befinden musste. Ich konnte das sehr unauffällige Gebäude schließlich zweifelsfrei identifizieren, habe es aber in der Karte nicht getaggt.
Ein spannender Einblick in Infrastruktur, von der man kaum etwas weiß und sieht, geht zu Ende. Unauffälligen Grüngürteln in Neubaugebieten und vegetationsfreien Schneisen im Wald messe ich plötzlich Bedeutung als potenziellem und vermutlichem Trassenverlauf zu.
Falls mich jemand auf Insiderbasis in die Geheimnisse der Schilderkürzel einweihen und zu einer Besichtigungstour in Wasserwerk und Hochbehälter einladen möchte: Kontaktmöglichkeiten finden sich im Impressum. 🙂
We have a commercial piece of software here that can cause an irrecoverable kernel panic when starting, by loading a proprietary kernel module. Detect whether the system was previously shut down cleanly and fail the service, if not:
# /etc/systemd/system/fouled-up.service.d/prevent.conf
[Service]
ExecStartPre=echo 'Analyzing journal for clean shutdown on previous boot.'
ExecStartPre=journalctl -b -1 -g 'Shutting down.' _COMM=systemd
ExecStartPre – Fail the unit if this command fails.
journalctl -b -1 – Look at entries from previous boot.
-g 'Shutting down.' – Grep for entries containing this string. Returns non-zero if not found.
_COMM=systemd – Match entries from this command only.
Gnome session keyring / Seahorse CLI interaction
Nobody seems to really know how this works. I do however have an application password that I want to keep in the Gnome session keyring.
The documentation for secret-tool references attributes/keys and values, but there seem to be no predefined names or convention for this.
How to save and retrieve a password in the Gnome session keyring:
Ratarmount is an excellent tool for mounting archives as filesystems, and I use it a lot. Mostly for union-mounting tar.xz telemetry bundles created by sos report. The ratarmount README suggests to prefer indexed tar.xz archives created using pixz for performance, so let’s see what’s the best compression to use.
TL;DRs
On huge archives, tar.gz is always fast and fastest, no optimization required.
Best to recompress tar.xz to tar.gz for best performance. Recompressing with pixz yields an improvement, but not as much as gzip.
On tiny archives close to the host’s RAM size, performance is hard to predict and may put gzip behind.
The “Backup” use-case
For my test to have a bit of a sizable workload, I pick a reasonably-sized tar.gz, a remnant historical backup of a long-gone server:
-rw-r----- 1 root root 1.7G Aug 6 10:16 example.tar.gz
This is stored on a RAID-1 of 7200 rpm hard drives, which should amplify all seek performance issues. 8 GB RAM, 6 physical CPU cores, 12 threads.
I prepare a list of 1000 random files from the archive that I’ll be reading from the mounted archive.
tar ztf example.tar.gz | egrep -v '(/$|(sys|proc|dev|run))' | shuf | head -1000 > example.list
Now, I mount the tar.gz for my baseline measurement.
umount ./mnt; ratarmount example.tar.gz ./mnt
time xargs -I{} md5sum ./mnt/{} < example.list
...
real 0m13.974s
user 0m1.178s
sys 0m0.984s
I recompress the tar from gzip to pixz and measure again:
gzip -dc example.tar.gz | pixz > example.tar.pxz
umount ./mnt; ratarmount example.tar.pxz ./mnt
time xargs -I{} md5sum ./mnt/{} < example.list
...
real 0m57.408s
user 0m1.216s
sys 0m0.904s
Multiple times slower! Back to ratarmount‘s README: “In contrast to bzip2 and gzip compressed files, true seeking on XZ and ZStandard files is only possible at block or frame boundaries.” – Are you telling me gzip is not the issue and only naively compressed xz is? A quick recompress using vanilla xz and a comparison of that to the pixz compressed archive:
gzip -dc example.tar.gz | xz --threads=$(nproc) > example.tar.xz
umount ./mnt; ratarmount example.tar.xz ./mnt
time xargs -I{} md5sum ./mnt/{} < example.list
...
real 1m33.549s
user 0m1.109s
sys 0m0.838s
Indeed a noticable, although not huge, penalty compared to pixz. Now that I’m here and wasted this much time, a final measurement using bzip2:
gzip -dc example.tar.gz | bzip2 > example.tar.bz2
umount ./mnt; ratarmount example.tar.bz2 ./mnt
time xargs -I{} md5sum ./mnt/{} < example.list
...
real 0m44.410s
user 0m1.301s
sys 0m1.164s
So ratarmount handles bzip2 around the same speed as xz created by pixz.
Gzip is always fastest, even without any special treatment, and I assume this is because multi-threaded rapidgzip literally is ratarmount’s sister project.
The “Telemetry” use-case
Back to my tiny sosreport files in tar.xz format, still on the 7200-rpm HDD system. For consistency, I’ll use the same md5sum benchmark on 1000 archive members as above.
ls -lh sosreport.tar.xz
-rw------- 1 root root 9.3M Aug 14 16:07 sosreport.tar.xz
tar Jtf sosreport.tar.xz | egrep -v '(/$|(sys|proc|dev|run))' | shuf | head -1000 > sosreport.list
umount ./mnt; ratarmount sosreport.tar.xz ./mnt
time xargs -I{} md5sum ./mnt/{} < sosreport.list
...
real 0m4.979s
user 0m0.940s
sys 0m0.625s
A conversion to pixz:
xz -dc sosreport.tar.xz | pixz > sosreport.tar.pxz
umount ./mnt; ratarmount sosreport.tar.pxz ./mnt
time xargs -I{} md5sum ./mnt/{} < sosreport.list
...
real 0m6.847s
user 0m0.829s
sys 0m0.553s
And a conversion to tar.gz:
xz -dc sosreport.tar.xz | gzip > sosreport.tar.gz
umount ./mnt; ratarmount sosreport.tar.gz ./mnt
time xargs -I{} md5sum ./mnt/{} < sosreport.list
...
real 0m13.202s
user 0m0.918s
sys 0m0.598s
gzip is suddenly slower here, and I believe it’s because the file turned out more than 50% larger than the xz versions, both of which are close to the hosts’s RAM size of 8 GB:
-rw-r--r-- 1 root root 14M Aug 14 16:17 sosreport.tar.gz
-rw-r--r-- 1 root root 7.8M Aug 14 16:16 sosreport.tar.pxz
-rw------- 1 root root 9.3M Aug 14 16:07 sosreport.tar.xz
My initial notes on how to install ratarmount in a python virtualenv are documented in Too good to #0013.
Cobbled this up for putting a 1993 vintage RS/6000 into perspective. Counts how many rand() / (rand() + 1) divisions the system will do in 10 second intervals.
Die Morning Midas war ein Frachtschiff beladen mit Autos, das ab dem 26. Mai 2025 auf dem Weg von China nach Mexiko war. Am 3. Juni 2025 geriet es im Nordpazifik in Brand und die Crew konnte nach erfolglosen Löschversuchen von einem vorbeikommenden Frachtschiff aufgenommen werden. Es gab keine Toten oder Verletzten.
Am 16. Juni meldete die US Coast Guard, das Feuer auf dem führerlosen Schiff sei erloschen.
Am 24. Juni wurde dann schließlich der Untergang der Morning Midas am Tag zuvor gemeldet.
Autos an Bord
Die Ladung der Morning Midas setzte sich nach Meldungen der US Coast Guard wie folgt zusammen:
3048 Fahrzeuge insgesamt
70 batterieelektrische Fahrzeuge
681 Fahrzeuge mit Hybridantrieb
Daraus abgeleitet also: 2297 reine Verbrennerfahrzeuge und 2978 Fahrzeuge mit Verbrennungsmotor.
Zum Tankinhalt der 2978 Fahrzeuge mit Verbrennungsmotor kamen 1880 Tonnen(!) fossiler Betriebsmittel für das Schiff selbst, die beim Untergang – noch – nicht in die Umwelt ausgetreten waren.
Brandwahrscheinlichkeit pro Antriebskonzept
Die Hybriden sollen für eine ganz einfach gehaltene Betrachtung doppelt, sowohl als Verbrenner als auch als Elektroauto gezählt werden:
2978 konventionelle Antriebe mit Verbrennungsmotor
Es liegen keine öffentlich verfügbaren Informationen der Reederei vor; offenbar wurde ausschließlich direkt mit Presse und Coast Guard kommuniziert.
Das einzige, was die These mit dem Elektroauto-Deck stützen könnte, wäre, dass das Schiff gezielt auf Lücke beladen worden sein könnte, um die Elektroautos zu isolieren. Ich würde tatsächlich erwarten, dass von unten nach oben beladen wird, die schweren Elektroautos zuunterst, und dann auch keine Lücken gelassen werden, um den Schwerpunkt niedrig zu halten.
Will man der neuen Entwicklung folgen, dass Hybride als Elektroautos zählen, waren auf den entsprechenden Decks (nicht nur auf einem) hunderte Hybride mit Verbrennungsmotoren verladen und die These vom Elektroauto-Deck ist in sich nicht schlüssig.
Ein Defekt am Schiff, oder Fahrlässigkeit, sind genauso denkbar wie ein Defekt an einem der Autos.
Anders als im Fall der Fremantle Highway, wo die am Brand schuldigen Elektroautos alle unbeschädigt von Bord gekommen sind, liegen alle Beweisstücke diesmal in kaum erreichbaren 5000 Metern Tiefe am Grund des Pazifik.
Martin Schmitt ist in den 1990er Jahren nach Ausbildung und Berufstätigkeit als gelernter Speditionskaufmann in die IT gewechselt, hält sich also selbstbewusst für einen Experten in Logistikfragen.
Dieses Posting wurde – wie alle anderen auf diesem Blog – ohne die Unterstützung eines großen Sprachmodells (im Volksmund “künstliche Intelligenz”) verfasst.
--argfile behaves differently depending on the number of JSON objects in the file. If it the file contains 1 JSON object, it is returned as a JSON object. If I create a JSON file that contains 2 JSON objects, they are converted to a list of objects:
--slurpfile treats all JSON objects the same and if the file contains a single JSON object, returns a list of JSON objects containing a single entry. Hence the added [0] from the TL;DR section.
One might argue that the removal of --argfile could have come following a clear deprecation notice instead of semi-permanently (first appearance in Debian 9/Stretch) advising against its use and then removing it all of a sudden. However, as far as I am concerned, the issue was detected in earliest Debian 13 compatibility testing within days after the freeze, I immediately knew what was cooking, the migration to --slurpfile was trivial, and it can also be deployed retroactively on all older systems.
Not the first appearance of systemd-run in this category, and probably not the last. Here’s how to hand a task to systemd-run in order to be retried a number of times.
My bro math for interval calculation goes like this:
RestartSec = Time to wait between end of a failed attempt and start of the next attempt
RuntimeMaxSec = Allowed time for each attempt
StartLimitBurst = Number of attempts to make
StartLimitIntervalSec = (RestartSec + RuntimeMaxSec) x StartLimitBurst x 10
So for a service that shall retry every 5 minutes (RestartSec), 12 times (StartLimitBurst), and shall be timed out after 30 seconds (RuntimeMaxSec):
sudo install -m 0755 /dev/stdin /etc/NetworkManager/dispatcher.d/vpn-up << "Here"
#!/bin/sh
if [ "$2" = "vpn-up" ]; then
ip link set dev "$1" mtu 1392
fi
Here
Caveat: The preview pane inside OBS requires 24 bit color depth.
The ~/.xinitrc sets a language environment, which I use for influencing the date format inside the OBS browser source. The OBS invocation also starts the stream automatically, and ignores uncontrolled shutdowns of OBS, so the stream will autostart after a reboot.
The VNC service will be bound to localhost only, but adding a password won’t hurt and will hardly be noticeable once it’s setup and saved in the VNC client.
x11vnc -storepasswd
Another systemd user-unit takes care of starting x11vnc:
Pipewire Easyeffects with RNNoise on Debian 12 / Bookworm
Gnome Night Light from Sunrise to Sunset, without Location Services
Revisiting ratarmount
Pipewire Easyeffects with RNNoise on Debian 12 / Bookworm
RNNoise for removing background sound on your microphone is not included in Debian 12, due to licensing issues around its training data. The least painful way to work around this is to install the Easyeffects Flatpak instead of the packaged easyeffects: