First step to NixOS

Given my OS history (Windows -> macOS -> Fedora -> Arch Linux) these were the options I was interested in as a next one:

  • Gentoo (but I have no interests in compiling everything myself)
  • GNU Hurd (but I don’t think it is ready yet)
  • Arch Linux (There was nothing bad about it except the installation process)
  • Manjaro (because it is Arch with an installer)
  • NixOS (because I like writing configurations)

I decided on NixOS because I could see me using it for the next years (other then Gentoo and GNU Hurd) and it would give me the opportunity to learn something completely new (other then Arch and Manjaro that I used for a few years now).

Since my old laptop T440S was gone and beyond repair I got my hands on an old T430S (which makes it amazingly easy to swap parts) and created a bootable USB Stick. And then …

some wonderful things happened in my private live and I had no time to go further.

It has been a few months, but I finally could pick up my experiment with NixOS. Booting from the stick was easy and before you know it you get a Desktop Environment. There are some multiple tools to help you get the disk in the shape you want before the real installation begins.

While I know how my way around the commandline the same can not be said about partitioning, formating and file systems. It seems like there are multiple definitions of “device” for different programms and I wouldn’t even know how a good setup would look like. I clearly lack knowledge in this area.

The NixOS manual uses a lot of commands that sounded obscure to me (parted, mkfs and mkswap) so I choose to follow a guide from alexherbo2 that seemed more detailed and recommended “GParted for discoverability”. Unfortunatelly I got stuck when creating new partitions. I couldn’t assign any other filesystems then ‘linux-swap and ‘minix’.

Asking for help in the IRC (#nixos) got me some advice (from colemickens, thanks a lot) - he encouraged me to give the commands from the manual a try (because I didn’t have much to loose on that machine). It turned out that they did work as advertised. When I typed them in by hand I got a better understanding of what they did than from just reading/copying/pasting them.

The rest of the installation process went as expected. I had a little trouble because I hadn’t installed the network-manager before rebooting (so I couldn’t install it later because I had no network-manager to get the wifi going) but fortunately the Ethernet worked out of the box.

So now I have a working NixOS on my Thinkpad. Having managed the installation so far makes me a bit proud and I am looking forward to learn the nix way. I really like it so far, but didn’t have much time to play with it. Currently I only have emacs, network-manager, sway and firefox installed, qutebrowser will follow. That should be enough to get along for a while, the next step is to migrate my old data.

Using Newsblur's API

Everybody should have a feedreader for RSS feeds. Lately I decided to subscribe to some feeds of local organisations (like the zoo, some local fablabs or the nearest police station). Things that take place nearby are more interesting after all.

So yesterday I found that our city administration provides some RSS-feeds - many actually. They are all listed on this website. So I want to subscribe to all of them. I didn’t find an easy way to subscribe to many feeds at once through the Newsblur web interface, so I decided it was a good day to test out the Newsblur api. (While the API is well documented, I found that I missed having some examples to play around with. So here is my example.)

For authentication I got my session coockie like this:

curl -X POST \
    --cookie-jar session.newsblur \
    --data "username=$MY_USERNAME" \
    --data "password=$MY_PASSWORD" \

After that, the file session.newsblur contains something that looks like a sessionid: TRUE / FALSE 1601234874 newsblur_sessionid xa3w22sometokenspecifictome6duds

As a test I tried reading a list of all my feeds (the json_pp is just for formating):

curl -X GET \
    --cookie session.newsblur \
    "" \
    | json_pp

This works just fine and contains information about my personal feeds, so we know I did the authentication right.

Next I want to subscribe to a single the feed (, taken from the site mentioned above) and add it in the folder regional. The documentation for this command tells us we will need to add the two arguments as url parameters. Since the url contains suspicious caracters like :, ., / and \ (that are likely to break things) I will use the curl flag --data-urlencode:

curl -X POST \
    --cookie session.newsblur \
    --data-urlencode "url=" \
    --data-urlencode "folder=regional" \

The output again is some json, telling my information about the newly subscribed feed:

      "subs" : 1,
      "feed_link" : " - Ausstellungen",
      "id" : 7686975,
      "min_to_decay" : 240,
      "updated_seconds_ago" : 15878,
      "stories_last_month" : 6,
      "favicon_text_color" : "white",
      "fetched_once" : true,
      "search_indexed" : true,
      "last_story_seconds_ago" : 541185,

A look at the Newsblur’s website tells us that we really did subscribe to the feed and it was placed in the correct folder. So we are nearly there! Let’s get a list of all the feeds that are linked in the site of the city administration:

lynx -dump -listonly "" \
    | grep xml | awk '{print $2}' > feeds_to_subscribe_to.txt

We get a file with one feed address per line (36 in sum). Now all that is left is to loop over them and subscribe to them one by one.

cat feeds_to_subscribe_to.txt | while read feed
        curl -X POST \
            --cookie session.newsblur \
            --data-urlencode "url=$feed" \
            --data-urlencode "folder=regional" \
        sleep 1 # don't spam the api

And there we go: We subscribed to each of the feeds listed on the website.

I didn’t have much opportunity to work with APIs, yet. But it was fun to play around with this one, there is nothing to be afraid of.

My wifes macbook didn't start anymore, it tried but went into the same error again and again. This is how I got the data from the old hard drive.

  1. Get yourself a drive to rescue the files to (we will call it LIFEBOAT). Connect it to the mac.

  2. Enter Recovery mode by pressing CMD and R at startup.

  3. Get yourself a terminal (in the upper menu under "Utilities").

  4. Make sure LIFEBOAT can be found under /Volumes/LIFEBOAT.

  5. Make sure your userdata is in /Volumes/Macintosh HD/Users/YOURUSERNAME.

  6. Copy the files you need to the LIFEBOAT with a simple cp -r command.

  7. Close the Terminal (CMD-Q) and shut down the Mac.

The critical step is clearly step 5. If the data is not there, I have no idea what to do.

The mac I used was running an old version of OSX (Mavericks) and I think in the newer ones the files might be encrypted.

I did have two backup plans:

  • Try to find whatever is left from the files with TestDisk, perhaps after copying the drive to make sure I don't destroy anything by excident. This was a recommendation of Pascal and David.

  • Pay someone to rescue as much data as possible. There are companies for this.

In the end I was very glad to get everything back.

Most of us know awk as the program that you use when you want only that one column of your output. Just pipe it through awk '{print $3}' and the third column you get.

Fewer people know that awk is a programming language. It is specialized for processing structured input like tables.

As an example we will analyze this table of events at of the first Quidditch match of the first Harry Potter book, Griffindor vs Slytherin.

player team points
Johnson Griffindor 10
Spinnet Griffindor 10
Flint Slytherin 10
Flint Slytherin 10
Flint Slytherin 10
Flint Slytherin 10
Flint Slytherin 10
Flint Slytherin 10
Potter Griffindor 150

You can run all the awk programs in this blogpost with awk -F, 'PROGRAMM' quidditch.csv or by saving the awk-program into a file and running awk -F, -f 'PROGRAMMFILE' quidditch.csv. The file can be found here, it is the table from above with columns separated by ,.`

Get values from column 3

In awk we think of the input as a sequence of records (lines normally) that consists of sequence of fields (words). These fields can be adressed by $1, $2 etc (and $0 is the whole record).

Lets extract the column "points": The third field of each record.

{print $3}

Of course the header is not interesting here and we should remove it.

Remove the header

The syntax of awk is a bit different from the programming languages you might know. In man awk we read:

An awk program is a sequence of patterns and corresponding actions. When input is read that matches a pattern, the action associated with that pattern is carried out.

So a program is a series of statements like this:

<script type="text/javascript" src=""> </script>

$$\stackrel{\text{If the input matches this pattern ....}}{\overbrace{\text{pattern}}}\underset{\text{... then run this action on it}}{\underbrace{\left\{ \text{action}\right\} }}$$

In the case of our program above a special case zoccurs: If there is no pattern given every record matches.

To remove the header of the results we can simply add a condition to the program: Don't act on the first line (the record where the record number NR is 1).

NR!=1 {print $3}

Sum of a column …

Now lets get the sum of all the points scored by the players. Our first thought here is to pipe the result into the program sum. But interestingly enough there is no such program in the world of commandlines as far as I know. It seems like our ancestors with their great beards were fine with writing their own version when they saw need to. And when they did they probably used awk.

NR!=1 {points+=$3}
END{print points}

Two things should be noted here:

  • the line marked with END is only triggered after all the input has been processed. There is a similar keyword (BEGIN) which allows code to be executed before the rest of the code. (Dough!~)

  • the variable points did not have to be initialized. awk is full of sensible defaults and one of them is that a numerical variable with no value is assumed to have the value 0 if not stated otherwise.

… grouped by another column

To get the result of the Quidditch match we need to sum the points for every team separately. We can use arrays (which would be called dict in other languages) for that.

NR!=1 {points[$2]+=$3}
END {for (key in points) { print key " " points[key]}}
Griffindor 170
Slytherin 60

And here we have our final score of the game.

I really know only one other language which can do this sort of processing with so little code: SQL. But SQL only works for databases so it needs a big setup to be useful. So when I find myself with a bunch of text files in a unixoid environment, then awk is the way to go.

Oh, and if you think Griffindor totally dominated this match, here is how the score would have looked like if Harry hadn't caught the snitch (which happened more or less by luck).

NR!=1 && $1 !~ "Potter" {points[$2]+=$3}
END {for (key in points) { print key " " points[key]}}
Griffindor 20
Slytherin 60

Die letzten Tage habe ich auf der PyconGermany in Karlsruhe verbracht. Die dominanten Themen waren Machine learning, Docker und vielleicht noch ein bisschen BigData. Über Python2 redet eigentlich keiner mehr, das ist schön.

Ich habe viel gelernt und einige spannende Leute getroffen (schöne Grüße an Corrie). Irgendwie schafft es die Pythoncommunity, ein breiteres Feld als die üblichen Nerds anzusprechen (zu denen ich mich selbst dazu zählen würde). Insbesondere das Verhaeltnis Maenner:Frauen war erfreulich ausgeglichen, wenn auch noch nicht 1:1.

Dort habe ich meinen ersten Lightningtalk gehalten. Ich war sehr aufgeregt, zumal der Vortrag auf Englisch sein sollte. Aber es lief sehr gut, ich habe das Zeitlimit eingehalten und die Aha-Momente sind übergesprungen. Ich bin sehr zufrieden.

Für die Slides habe ich Remark.js verwendet: Man hat eine html-Datei, den eigentlichen Inhalt schreibt man im Markdownformat. Das wird dann vom Javascript in Folien umgewandelt, wenn man die Datei im Browser öffnet. Das ist ein cleveres Format, weil es mehrere Vorteile vereint:

  • Schreiben in Markdown
  • Styling mit der Macht von HTML und CSS
  • Code Highlighting mit highlight.js
  • Nur ein einzelnes, schlankes Dokument (zumindest solange man keine Bilder einbettet)
  • Läuft auf jedem OS, das einen Browser hat.
  • Es gibt ein minimales Interface für den Praesentierenden, in dem Notitzen, ein Timer und die nächste Folie angezeigt wird. Hilfe gibt es mit h oder ?.

Interface fuer den Praesentierenden.

Ein paar Schwierigkeiten habe ich aber noch:

Es ist knifflig, offline zu präsentieren, weil Remark.js aus dem Netz nachgeladen wird. Gerade auf Konferenzen ist stabiles Netz ja keine Selbstverständlichkeit. Man kann das natürlich lösen, indem man das Repo klont und die lokale Version lädt, aber dann ist es halt nicht mehr so portabel.

Außerdem habe ich ein bisschen die Allmacht von Orgmode vermisst, Code einzubinden und den Output direkt generieren zu lassen. Aber das ist ein Luxusproblem, wer Orgmode will muss eben Orgmode benutzen.

Insgesamt war ich mit Remark.js sehr zufrieden und würde es für Praesentationen wieder verwenden. Andererseits kenne ich mich gut genug um zu wissen, dass ich selten zweimal das gleiche Setup für meine Grafiken und Folien verwende. Es gibt einfach zu viele spannende Tools.

Start videos from the commandline

tldr: Just use mpv VIDEOURL to start watching.

Lets say you want to watch a video, how would you do it from the commandline?

local video file

If the file you want to see is already on your computer, then this can’t be too hard. Just go with your favorite video player (vlc in this example):

vlc ~/Videos/Nyan_Cat.mkv

videos from the internet

So what if the video isn’t already downloaded? Lets say we want to look at this YouTube Video: Nyan Cat.

No problem, we can download it right away with youtube-dl.

youtube-dl -o "~/Videos/Nyan_Cat.mkv" "" && vlc ~/Videos/Nyan_Cat.mkv

The reason why we don’t use curl/wget here is that we don’t have the url of the video file itself (and if we did, we could just continue to feed it into vlc directly). The video is embedded into a website and there is no trivial way to get its url. If we ask youtube-dl nicely (with --get-url) he will tell us, but at this point we have used youtube-dl anyway, so what’s the point?

The video that google uses has a really long url. Something tells me that is isn’t meant for direct use.

Youtube-dl is quite amazing. It supports a great number of video sites and file formats. It also supports playlists, logins for private videos and downloading the audio only. Being controlled from the commandline makes it scriptable, but the best thing about it is that it has been under continuous development for many years now, catching up with all the api-changes from all the supported websites.

streaming, not downloading

Downloading works, but what if we want to start to watch straight away, waiting for the download to finish is unnecessary (especially if the video is a big one, like the 10 hour version of the video above).

Youtube-dl can write the file to stdout (--output -) and tell the video-player to play from stdin (vlc - in this case).

youtube-dl --output - '' | vlc -

Unfortunatelly there is no easy way to jump positions in the videos itself.

mpv to the rescue

vlc has a big fanbase, but for quite some time I preferred to use mplayer, because it has the most minimal gui imaginable (a window whith the video in it, nothing more) and is easier to use from the keyboard. Then I found mpv, a pimped version of mplayer - and everything is perfect. Much like feh for images, it does all I want and goes out of the way otherwise. I just love it.

Mpv makes all the problems from above trivial.

mpv ''

It uses youtube-dl, can show subtitles in different languages, jumps between positions and has an easy syntax. It is free software (like all the other programs I talked about in this post) and its development continues steadily.

Why not use a browser, like a normal person?

Using a native video-player comes with some cool bonuses. You can configure and finetune it, use media-keys on your keyboard, it plays nicely with the rest of your setup and your window-manager etc.

The only downside I see is that the resolution is not adjusted on the fly if the connection is not good enough to stream in full resolution. That’s why I still use a browser for twitch-streams.

Wieder da

Ich bin wieder da. Der Blog hat lange geruht und jetzt habe ich Lust, wieder zu schreiben.

Der Blog war auch und vor allem deshalb fort, weil wir unseren geliebten Server Gipfelsturm verloren haben. Da sind auch Sandras und mein Ghostblog drauf gewesen und ich wollte erst wieder schreiben, wenn ich beide Blogs wieder so weit habe, dass sie benutzt werden können (Es wäre unfair gewesen, selbst weiter zu bloggen bevor ihr Blog wieder läuft).

Dazu musste ich aber aus schlechten Backups die meisten Artikel wieder herzaubern (viel habe ich von und dem google-cache gezogen, Viele Bilder hatten wir noch undeinige konnten wir wieder zuordnen) und eine ganz neue Bloginfrastrucktur aufbauen. Das war eine lange Reise, aber jetzt bin ich ganz zufrieden. Vielleicht schreibe ich später mehr zu den Details. Die Hauptsache ist, dass ich jetzt große Kontrolle über den Blog habe (wenn was nicht geht kann ichs wahrscheinlich reparieren) und es trotzdem einfach ist, zu bloggen.

Es läuft wieder was in der Schauderbasis.

PS: Der RSS-Feed funktioniert auch:

Bilder aussortieren

Es gab eine Feier, jemand hat Fotos gemacht und rumgeschickt. Oder vielleicht habe ich selbst hundert mal den selbe Essen fotografiert. Jedenfalls sind da ein Haufen Bilder und ich will nur die guten behalten.

Dieses Aussortieren macht wenig Spaß und soll deshalb schnell gehen. Wenn man es gut macht hat man danach nur noch 5-10% der Bilder. Der Lohn: Man kann den wenigen guten Bildern viel mehr Beachtung schenken.

Erstaunlicherweise bietet der einfachste (und schnellste) mir bekannte Imageviewer dafür das beste Interface bereit: feh


Wir bilden den Sortierprozess auf das Filesystem ab. Wärend dem sortieren haben wir 3 Haufen von Fotos:

  • die noch unsortierten Fotos (~/Pictures/feier)
  • die guten Fotos (~/Pictures/feier/good)
  • die schlechten Fotos (~/Pictures/feier/bad)
mkdir ~/Pictures/feier
cd ~/Pictures/feier
mv ~/Downloads/ .
mkdir good bad

Wir werden die schlechten Bilder erst wegwerfen wenn wir mit dem sortieren ganz fertig sind (so vermeiden wir unglückliche Versehen).


Hier steckt die ganze Magie drin:

feh --auto-zoom --scale-down --action1 "mv %f good/" --action2 "mv %f bad/" .

Übersetzt bedeutet das: “Zeige alle Bilder im aktuellen Verzeichnis (.) nacheinander (als Slideshow) an, so gezoomt das man immer das ganze Foto sehen kann. Wenn ich die Taste 1 drücke, verschiebe das aktuelle Bild ins Verzeichnis good, wenn ich 2 rücke verschiebe es nach bad.”

Nette Annehmlichkeiten sind dabei:

  • Wenn man gerade nicht sicher ist, kann man mit den Pfeiltasten einfach zum nächsten Bild springen und die Entscheidung verschieben.
  • Ein Bild, bei dem man eine Wahl getroffen hat wird nicht mehr angezeigt. Sind keine Bilder mehr übrig, wird das Programm beendet
  • Will man unterbrechen, hilft die Taste q, was man bisher sortiert hat bleibt auch sortiert.
  • feh ist zwar schlank und klein, aber zum zoomen und Bilder richtig herum drehen reicht es noch.
  • Wie die meisten Unix-workflows ist auch dieser sehr flexibel. Ideen, die man damit schnell verwirklichen könnte:
    • einen dritten Ordner (bin_nicht_sicher)
    • mehrere Sortierdurchläufe.
    • Photos taggen
  • Das Interface ist so einfach wie nur irgend möglich: Man sieht nur das Bild und hat genau 2 Tasten für 2 Möglichkeiten.
  • Es geht schnell. Wenn man mal ein bisschen drin ist hat man schnell einige Hundert Bilder sortiert.


Zum Schluss (und wenn man sich sicher ist) wirft man die schlechten Fotos weg und behält die guten:

rm bad/* -f
mv good/* .
rmdir good bad

Bilder von hier und hier.

Hörbücher auf SailfishOS

Unterwegs höre ich sehr gerne Hörbücher - besonders in vollen öffentlichen Verkehrsmitteln, wo man ohnehin nicht viel anderes machen kann als Musik/Podcasts/Hörbüchern zu lauschen oder seinen Feedreeder durchzuarbeiten. Auf SailfishOS gibt es keinen nativen Client, aber die Standardapp “Medien” funktioniert wunderbar. Wie ist also der Workflow?

Umweg über den Rechner

Bestimmt geht das auch direkt auf dem Telefon, aber ehrlich gesagt habe ichs noch nicht ausprobiert. Außerdem geht es dank ssh/scp sehr flott auch von der Kommandozeile.

Hörbuch finden

Ich könnte es gar nicht besser zusammenschreiben als es im Wiki Audiobooks Subreddit steht.

Für diesen Blogpost wählen wir The Wrong Box auf Librivox.

Hörbuch herunterladen

Hörbücher sind meistens mehrere Audiodateien, zum Beispiel eine für jedes Kapitel. Meistens bekommt man diese schön kompakt in einer zip-Datei, die lädt man herunter und entpackt sie. Manchmal sieht man aber auch nur eine Website voll mit Links zu dein einzelenen Dateien (wsl für Leute, die alles direkt im Browser konsumieren wollen). In diesem Fall hilft dieser Befehl.

lynx -dump | grep 64kb.mp3$ | awk '{print $2}' | xargs -n1 wget

In Worten: Schau dir alle Links der genannten Webseite an, nimm die die auf “64kb.mp3” enden und lade sie einzeln herunter. (Es könnte also schlau sein, das in einem leeren Ordner auszuführen.)

Bei librivox ist das aber eigentlich nicht nötig, man kann alles direkt herunterladen (sogar per Torrent, wohooo!).

Es macht übrigends alles (erheblich) einfacher, wenn die Dateien so benannt sind, dass die alphabetische und die logische Ordnung übereinstimmen.

ssh aufs Telefon

Testweise kann man sich schonmal aufs Telefon verbinden und den Ordner anlegen, wo die Dateien später liegen sollen. Ssh muss in den Einstellungen des Telefons unter “Entwicklermodus” aktiviert werden, dort findet man auch Passwort und IP-Adresse.

ssh nemo@
mkdir Music/wrong_box

Hörbuch aufs Telefon

Da wir ja jetzt schon alles vorbereitet haben, reicht ein kurzes Befehl:

scp *.mp3 nemo@

Das wars schon.


Wir können alles in der Medien-App anhören. Nach dem aktuellen Kapitel wird automatisch zum nächsten gesprungen.