Dateien, Ordner, Schmerzen

Nach über Tausend1 Jahren “Computer” ist es noch immer ein ungelöstes Problem:

Zwei Computer stehen einen halben Meter nebeneinander. Wie tauscht man jetzt Dateien aus?!?

Ja, dafür gibt es doch Nullmodem-Kabel, Infrarot-Schnittstellen, oder dieses moderne “Ethernet”.. Schon gehört? Setz doch “einfach” einen Samba Server auf, oder schick dir doch selbst eine Mail mit Anhang.

Ich kotz im dicken Strahl.

Wie? Du willst an beiden Computern die selben Dateien bearbeiten, und es soll immer aktuell bleiben, ohne die immer manuell rüber zu schieben?

Ach ja? Die Computer sind nicht im selben Netzwerk, und dank IPv4 NAT-Hölle können die sich nicht sehen?

Stellt sich raus, damals™ hat Dropbox das Problem gelöst.. Aber hey, es kann doch wohl nicht wahr sein, dass “der einfachste Weg” Dateien von Süderbrarup nach Flensburg zu synchronisieren einmal über den Atlantik und wieder zurück geht. Wie, was? Datenschutz?!? Nie gehört - Vielleicht doch lieber Google Drive oder OneDrive?

Strahl wird noch dicker!

Wir wären ja nicht im Self-Host Abenteuer, gäbe es nicht doch was brauchbares.

Es heißt Syncthing und es ist sehr gut!

Was mir sehr viel Freude bereitet - es läuft alles lokal, nur auf Maschinen die man selbst kontrolliert (und nicht über fremde Server in anderen Ländern, auf die irgendwelche Leute im Zweifel zugreifen ohne dass man es weiß). Noch ein bisschen Kryptographie drüber gestreut, Schlüssel-Austausch wird mittels QR-Codes vereinfacht. Dazu ein offenes Protokoll, mit UPnP zum entkommen aus der IPv4 NAT-Hölle..


Einfaches Setup: Zwei Computer, sonst nix.

Meine Mutti (die Beste!) hat ein MacBook und eine Wintendo-Maschine am Start. Und möchte den “Dokumente” Ordner immer gleich haben.

Also hab ich ihr Syncthing untergejubelt. Am Mac gibt es ein Homebrew Cask das alles mitbringt, für die Büchse muss man bisschen improvisieren: mit SyncTrayzor (oder davor QSyncthingTray - Hilfe, diese Namen.. grusel). Funktioniert alles wunderbar. Das größte Problem: man muss ab und an mal sicher stellen, dass beide Computer gleichzeitig laufen. Aber wenn man mal zu Hause ist, und Updates installiert und Probleme repariert lässt man beide parallel laufen, dann hat sich das.

Positiver Nebeneffekt: Die wichtigsten Sachen sind mehrfach gespeichert. Ist nicht direkt ein Backup, das ist klar, aber doch besser als gar nichts.


Fortgeschritten: Mein Setup (FreeBSD, MacBooks, Linux & iPhone)

Hab einen FreeBSD Server beim Hoster der immer läuft, also soll dieser doch “einmal alles” (mit Soße & Scharf) vorhalten, und die anderen Maschinen untereinander koordinieren.

Also eine neue Jail angelegt, den net/syncthing Port (mit pkg) installiert. Dann die passenden Löcher in die Firewall gebohrt, und den Reverse-Proxy mit LetsEncrypt-Zertifikat in die Jail zeigen lassen (Wiki-Seite). Fertig ist der Karton.

Auf meinem NAS zu Hause (natürlich auch FreeBSD weil ZFS!) genauso wie oben, bloß ohne Reverse-Proxy; Für die MacBooks gibt es Homebrew (noch weiter oben), für Linux ist was in den jeweiligen Repositories. Alles schick!

Am iPhone jedoch war es lange Zeit leider echt übel, da gab es nichts, und/oder nichts brauchbares. Irgendwann tauchte aber Möbius Sync auf (der Name, das Icon.. grusel). Es ist zwar “nur” die Web-Oberfläche von SyncThing in einem Safari-Frame, jedoch an den entsprechenden Stellen so modifiziert, damit dann alles funktioniert. Letztendlich landen die Dateien im App-Bundle der Files.app und sind dadurch von überall erreichbar. Wunderbar! Es lohnt sich da auch Geld einzuwerfen - die App wird aktiv entwickelt und funktioniert bei mir schon seit Jahren ohne Probleme. Das einzig nervige ist - ab und an muss man die App manuell starten: iOS Akku sparen und Hintergrund-Prozesse kommen nicht so gut miteinander klar. Aber gut, so ist es halt.


Sonst so

Das Leben macht man sich einfacher, wenn man den Server als “Introducer” an den anderen Computern einträgt, und ggf. das “Auto Accept” Setting anschaltet. Somit werden neue geteilte Ordner automatisch bei den anderen Computern zum Austausch angeboten und man spart sich den Weg über die QR-Codes. Auch hab ich meist “Staggered File Versioning” aktiviert, gebraucht hab ich das noch nie wirklich (puh, Glück).

Es ist in Go geschrieben. Persönlich hat die Sprache bei mir nicht verfangen, aber aus Anwender-Sicht wird alles richtig gemacht. Das Executable irgendwie herbekommen, starten, und dank statischem linken funktioniert das einfach so - und das auf Dauer.. Wunderbar.

Auf bald!


  1. Internet-Jahre ↩︎

$> sl dc gti!!1!

So, I spend 98% of my life in the command line. It’s super effective and a lot of fun. But typos happen… A lot.

I am well aware of external commands that annoy you when you type the wrong command:

Having a steam locomotive or some gti car running through the terminal is fun!

But there is the dc command - known as desk calculator. Preinstalled on most systems. This is unfortunate as it drops you into some prompt, interrupting what you intended to do in the first place.

So I have solved this problem little bit differently: I’ve decided to count how often I type something wrong.

Inside my shell rc I’ve put some functions similar to this:

_missed() {
    track="$HOME/.missed_$1"
    count=$(cat "$track" 2> /dev/null)
    printf "'%s' missed %d times!!1!\n" "$2" "$((count = count + 1))"
    printf "%d" "$count" > "$track"
}
dc() { _missed "dc" "cd"; cd "$@" || return; }
sl() { _missed "sl" "ls"; ls "$@"; }
gti() { _missed "gti" "git"; git "$@"; }

They should work on most shells, might need some adaptions for different implementations.

I should synchronize the ~/.missed_* files across all my machines to have the total failure rate available 😅

So long!

Docker Purge

My relation with docker is … well mixed.

Constantly I am oscillating between “I love docker” and “I hate docker”. This happens in a matter of seconds, many times per day.

The containers I run are mostly locally, I do not use it on the server.

My primary use case is during development of software: It’s nice to run your Unit-Tests against the real deal instead of mocking everything away. That would be for example some MySQL database in Testcontainers instead of using some In-Memory database or something. They behave little bit different than the real deal, drawing in subtle bugs that only occur later in production. Horrible.

Doing cross compiling of software is my other use case: Starting from a clean system, drawing in only required dependencies and then running the build during container creation. This keeps your normal system clean, and comes with the benefit that every build step is automatically documented: every step is part of the Dockerfile. When it finally works you have already written down every detail how to setup the environment and every step how to build it. Nice!

So enough of the introduction - why I am writing this post?

It turns out that sometimes you leave some broken state behind. Old containers are still running, eating up resources of your machine, unused volumes still lurk around, the network setup is all messed up…

Sad.

But there is a solution. I use these helper snippets in my shell rc to address the cleanup parts.

This one is obvious - If I want to try something out, not messing up the shell history this comes in handy:

alias focker="docker"

To actually remove all running containers, images, volumes and whatnot there are these functions:

function dockerpurge-containers() {
  echo ":: docker containers"
  docker container ls --all --quiet | xargs docker container rm --force
}
function dockerpurge-images() {
  echo ":: docker images"
  docker image ls --all --quiet | xargs docker image rm --force
}
function dockerpurge-volumes() {
  echo ":: docker volumes"
  docker volume prune --all --force
}
function dockerpurge-network() {
  echo ":: docker network"
  docker network prune --force
}
function dockerpurge-cache() {
  echo ":: docker builder"
  docker builder prune --all --force
}
function dockerpurge-system() {
  echo ":: docker system"
  docker system prune --all --force --volumes
}
function dockerpurge() {
  echo ":: :: :: ::"
  dockerpurge-containers
  dockerpurge-images
  dockerpurge-volumes
  dockerpurge-network
  dockerpurge-cache
  dockerpurge-system
}

So to remove all running containers I run dockerpurge-containers, to actually reset everything dockerpurge does it’s job. Then I can start over from a clean state.

This is nice, and helps me to say “I hate docker” less often…

So long!

Notizen, digital

Ach ja, Notizen in digitaler Form.. Ein Thema voller Missverständnisse.

Es könnte ja so einfach sein - Macht man einfach ein C:\notizen.txt, schreibt alles rein, fertig ist der Karton.

Stellt sich raus, Menschen haben mehr als ein Gerät am Start (vor allem kein Wintendo®), und den selben Inhalt darüber verteilen ist schon ein nettes Feature.

Wenn es um die Sammlung von Schmierzettel geht, für kleine Schnipsel ohne groß Features gibt es etwas sehr einfaches:

Das Zauberwort heißt IMAP. Fast alle Plattformen unterstützen dies auf irgend eine Art und Weise. Hat man irgendwo ein Mail-Postfach dann ist man schon fast fertig!

Am Mac kann man die Notes.app darauf ansetzen, genauso auch am iPhone (Einfach in den Settings anschalten - wenn man sein Postfach einrichtet). Unter KDE läuft das fluffig auch in der Kontact Anwendung; auf Arbeit geht das sogar in Outlook (grusel) - zumindest auf dem Mac.

Und zack fertig, sind die Schmierzettel überall immer aktuell. Unter der Haube funktioniert das wie ein extra Postfach, in dem einzelne Mails drinnen liegen. Kann also durchaus sein dass man das am Mail-Client extra ausblenden muss, ist aber ein lösbares Problem™. Einmal eingerichtet, funktioniert das sehr gut, der sync ist dank IMAP atomar und stressfrei. Ist gekauft!

Was bisschen Schade ist - Die Qualität der Implementierungen variiert immer ein bisschen, also ist es gut möglich dass die Formatierung mal flöten geht, oder irgendwie kaputt ist. Dennoch - wir reden hier über die Sammlung der Schmierzettel, da sollte man sich nicht zu arg austoben. Für was anspruchsvolleres (z.B. Entwürfe für Blog-Artikel wie diesen hier) gibt es andere Tools, aber das wär dann das Thema von einem anderen Beitrag.. Spoiler-Alert!

Auf bald!

Heiter bis wolkig

Habe das im Blog immer mal angestreift, nie direkt drüber geschrieben:

Der Grund warum diese Seite hier existiert, ist die Domain toor.su. Dort antwortet mein eigener Server aus den Untiefen des Internets (Kiste, aus Blech, 2x Festplatte, Netzwerk, Speicher, Strom, usw. beim Hoster des geringsten Misstrauens).

Keine Antwort auf HTTP oder nur statisch die Standard Seite von nginx ausliefern ist doof. Also neues Projekt gestartet: Blog schreiben. Dieses hier!

Parallel dazu: Genau die Dienste betreiben die ich für ein modernes Leben ohne Cloud benötige (Schön war auch die Episode: eine .su Domain zu registrieren. Irgendwann ist alles nur noch auf russisch in den Mails ..hmm, not sure if scam, or legit invoice..).

Warum mir das so wichtig ist, kann ich schwer beschreiben, finde allerdings dass alle Daten die man so hat & produziert nur auf eigenen Geräten oder zumindest Geräten unter eigener Kontrolle halten sollte. Natürlich gibt es Abstufungen je nach Kontext, dennoch - je vertraulicher umso mehr sollte man drauf achten, dass z.B. die Passwörter nicht in der iCloud Keychain, oder die Sachen von der Bank in der Dropbox landen…

Ist definitiv das Nischenthema deluxe - perfekt geeignet auf Parties, es interessiert exakt niemanden!!1! Dennoch: No kink shaming! kthnxbye:wq!

Die Lösung liegt auf der Hand, alles immer selbst hosten!!!1! Der Weg dahin ist … schwierig. Mache das schon länger, hab vieles ausprobiert, wieder verworfen, manches funktioniert. Neben dem Technischen gibt es viele Erfahrungen die man sonst so macht.

Lass doch mal die Serien Funktion in diesem Blog nutzen: Self Host - Live-Berichte aus den Irrungen und Wirrungen des Maschinenraums des Wahnsinns. Oder so..

Auf bald!

The struggle is real

Oh yeah, there is this box somewhere in the internet.. Minding it’s business and running a lot of services..

But the “blog” service hasn’t been updated for a while. Content wise. Nothing much, but something to have some regular activity (more then every x months/years)…

Well, …


So. Jetzt mal ernsthaft: Stimmt, hier auf dem Blog ist gar nichts los!

Schade - grob hatte ich das Ziel, im allgemeinen über Technik schreiben, und das auf Englisch.

But as it turns out - Die Sprache an sich ist kein Problem für mich, aber gut lesbare Texte in Englisch zu schreiben dauert bei mir ewig und ist sehr arbeitsintensiv. Kann sein dass sich das durch Übung verbessert - aber das Experiment die letzten Jahre zeigt: Bin ja gar nicht am üben, weil sich hier ja nichts tut. Deadlock.

Also: Planänderung, die erste Regel wird beibehalten, die zweite gelockert. Ab sofort werden die Einträge hier wahlweise auf Englisch oder Kartoffel erscheinen, je nach Lust und Laune.

Völlig unklar ob mein schönes, von Hand gedängeltes, Hugo-Theme das irgendwie unterstützt, zur Not hab ich schon wieder eine Dauerbaustelle aufgemacht. 😅 Das Ergebnis wird man ja dann hier sehen: 👈 👇 👆 👉 🤞 🫵

Ansonsten. Baustellen. Davon reiße ich grad eine Menge auf, und habe eine Menge Spaß dabei.. Muss bisschen aufpassen dass es nicht zu viel wird, aber da fällt eine Menge auch für den Blog bei ab, so hoffe ich. 😀

Auf bald!

Location aware config in git

Something you should know about, because it is really useful:

It is possible to change the (global) git configuration depending on the folder you are in.

For example - when mixing work-related and private projects on the same machine:

~/.gitconfig:

1
2
3
4
5
6
[user]
    name = Some Name
    email = my.personal.address@example.org

[includeIf "gitdir:~/code/work/"]
    path = ~/code/work/.gitconfig

And then inside ~/code/work/.gitconfig:

1
2
[user]
    email = my.work.address@example.com

I rely on this daily - It is very useful!

So long!

Pylint magic

I am using pylint on most of my code to make sure nothing bad or too complicated sneaks in. So far it has helped me a lot in discovering stuff I would not notice, and if you are not using #pylint: disable=... too often it forces you to write better code.

I just stumbled across this:

I want to find the first element in a list of elements that is bigger than the specified one. For simplicity I am just using numbers here…

./some.py:

def function(current, *selection):
    for number in [num for num in sorted(selection) if num > current]:
        return number

But my tests show me that something bad is happening…

./test_some.py:

from some import function

NUMBERS = [5, 4, 3, 2, 1]


def test_function():
    assert function(3, *NUMBERS) == 4
    assert function(3) is None

Running the tests shows that the last assert statement goes over the for loop end exits the function, returning None.

$ pytest -vv  test_some.py
================= test session starts =================
collected 1 item

test_some.py::test_function PASSED              [100%]

================== 1 passed in 0.02s ==================

But running the tests yields no errors:

$ pylint --disable "C0114" --disable "C0116" some.py test_some.py

------------------------------------
Your code has been rated at 10.00/10

I would have expected this typical message:

Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements)

Weird.


So, digging a little further, that example can be trimmed down to this:

def fun():
    for _ in []:
        return True

It seems, that the check for inconsistent-return-statements gets confused by the return inside the for loop. It does (or cannot?) not check if the input of the for loop is empty or not.

So, now I am aware of this. Anyway, I only discovered this while doing test driven development. For a moment I was confused why some assert bailed out with some None value for some edge-case that was not implemented yet..

So long!

Fixed!

Again, there has been a long time since the last post.

Somehow I lost motivation, because syntax highlighting did not really work. Black text on a very dark background is not much fun to read.

In the previous post I thought this needs to be fixed inside Firefox. But no, it seems to be intended behaviour, because at some point Chrome also stopped working. And with that, all the Electron apps suffered from the same issue.

Things went quickly then, as the bug trackers filled up with random Electron app users complaining.

So the colored SVG glyphs of the font were dropped and a new release was published. Great. Who would have thought that Electron is good for anything after all? 🤭

But the node package was not updated.

Sad, so my blog theme still was broken. But tonight it struck me: “Hey, isn’t it possible to install node packages directly from the git repos?!”

Yes it is. I tried that, and guess what:

1
2
3
4
from sys import stdout

stdout.write('It works!!1!\n')
stdout.flush()

This is great. Let’s see, if I can find more time to write about random stuff in the future…

So long!

Can't fix

So after many many debugging sessions I finally found the real culprit for this issue here.. It has nothing to do with CSS, but with SVG. Who would have guessed?!

I figured — it has something to do with the web-font, so there is this issue and also that issue. But in reality it is some regression in Firefox.

Oh no. I have spent so many hours trying to figure out what’s going on. And now I am very sad to not really be able to fix this. My knowledge of SVG font rendering inside Firefox is very very limited, so I don’t feel like solving this issue anytime soon. Sorry about that.

Reading through the original ticket some high profile sites are also affected.. Hopefully this speeds up things..

Otherwise - this is something very frustrating - not be able to fix some bug. Let’s see what the future will bring..

So long!