Techstack n – 1 is dead!

TL;DR TechStack n-1 is dead. It ended with the rise of the clouds and software release cycles going down to weeks due to containerized CIs.

Beeing OpenSource-based, Ubuntu already had the concept of point releases every 6 months when the Docker and K8s hit the world and gave automated CIs a big boost in making system containers. Some years after Docker itself switched to a 3-month release cycle. So did the Linux Kernel with 2-3 months. Firefox 4-weeks.

And Microsoft? Windows 10 became a platform. Service Releases for the end customers every 6 months. Insider Program became a built-in feature of Windows 10. Now you can call that a rolling release!

Given that and comparing that to the old paradigm of “we don’t run edgy software” it may take 8 weeks or 6 months until we have already reached TechStack n – 2.

Now compare that with the speed of your management decision processes!

Sure, not every feature is important but some of them are business critical just like WSL2. Or sometimes you get a security requirement like please change the base image of the systems. Sometimes you save time and money if you just deploy applications as services by helm chart instead of fixing a custom setup for weeks. Sometimes it’s easier to just rollback a deployment on kubernetes than replaying a build process in hope to rebuild a lost artifact (build once, deploy many).

And then you have security: there infrastructure is also changing. Snapshot technolgies are on the rise (hypervisors/ostree/next gen fielsystems like ZFS and BTRFS).

Back to WSL2. Why? Dev/Production parity. And maintaining one toolchain based on an image. Still you could use VMs and some indeed still do you Vagrant with all it’s problems Both Apple and Microsoft strife for best developer experience on their systems, simple because OpenSource and Linux has triumphed and it is run on the future market which is cloud native.

That is why every big company is behind the (corporate) Linux Foundation and CNCF (Cloud Native Computing Foundation). That is probably why Linux Foundations gets are so cheap – because we need skilled developers that know their platform.

So, how do we keep up? Clouds are evolving fast and are ephermal. So we need to become that too.

Not everyone is living at the edge and that’s also a requirement for a healthy system.

We need early adopters that can surf on the static noise generated by cloud native experiments, that can see where the ocean is moving. These are the OpenSource contributers and the ones birding GitHub repos on their laptops.

We need those who can build stable container ships that sail the ocean. Those who know what’s happing on the technology radar.

We need sceptical ones that can see beyond fancy applications and hero myths to the bottom of underlying bare metal infrastructure.

We need people with long time experience knowing old and forgotten tricks.

Running that old techstack n-1 paradigma in modern environments has become dangerous and negligent.

PS.: Sure, for datacenters keep running your RHEL or CentOS with support until 2026!

Download an LFS backed file from without `git` and `git-lfs` installed

Well, the API is there and you can do it already!

Just dig into the what git is doing by a test-clone with any LFS repo:

export GIT_CURL_VERBOSE=1                                                                               
export GIT_TRACE_CURL=1                                 
git clone <my-repo> 2>&1 | tee git-clone.log                                                

From there you are able to figure what is happing on SSH:

Now: download an LFS backed file from without git and git-lfs installed!

#!/usr/bin/env bash

PROJECT="${1}" # your-company/or-repo/whatever
FILEPATH="${2}" # foo/bar.tar.gz
REF="${3:-master}" # branch
SSHID="${4:-$HOME/.ssh/ecdsa_id}" # like $HOME/.ssh/mycompany

OID="$(set -o pipefail; curl -fSL -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${PROJECT//\//%2F}/repository/files/${FILEPATH//\//%2F}/raw?ref=${REF}" -o - | grep '^oid' | cut -d: -f2)"
AUTH="$(set -o pipefail; ssh -o IdentitiesOnly=yes -o IdentityFile="${SSHID}" git-lfs-authenticate "${PROJECT}.git" download | jq -er '.header.Authorization')"
mkdir -p "${FILEPATH%%/*}"
curl -H "Authorization: $AUTH" "${PROJECT}.git/gitlab-lfs/objects/${OID}" -o "${FILEPATH}"
file "${FILEPATH}"

And you can even do it without using SSH!

#!/usr/bin/env bash

PROJECT="${1}" # your-company/or-repo/whatever
FILEPATH="${2}" # foo/bar.tar.gz
BRANCH="${3:-master}" # branch

# get LFS file info
IFS=$'\n' LFS_OBJECT_INFO=($(curl -fsSL -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${PROJECT//\//%2F}/repository/files/${FILEPATH//\//%2F}/raw?ref=${BRANCH}" -o -))
OID="$(echo "${LFS_OBJECT_INFO[@]}" | grep -oP "oid sha256:\K[^\s]+")"
SIZE="$(echo "${LFS_OBJECT_INFO[@]}" | grep -oP "size \K[^\s]+")"
# request actions for given lfs objects
LFS_OBJECT_REQUEST_JSON="$(jq -rnc --arg oid $OID --arg size $SIZE --arg ref "refs/heads/$BRANCH" '{"operation":"download","objects":[{"oid":$oid,"size":$size}],"transfers":["lfs-standalone-file","basic"],"ref":{"name": $ref }}')"
LFS_OBJECT_ACTION_DOWNLOAD="$(set -o pipefail; curl -sSlf -H "Content-Type: application/json" -X POST -d "$JSON" "https://oauth2:${GITLAB_TOKEN}${PROJECT}.git/info/lfs/objects/batch" | jq -er '.objects[0]')"
AUTH="$(echo "$LFS_OBJECT_ACTION_DOWNLOAD" | jq -er '.header.Authorization')"
DOWNLOAD_URL="$(echo "$LFS_OBJECT_ACTION_DOWNLOAD" | jq -er '.href')"
mkdir -p "${FILEPATH%%/*}"
curl -H "Authorization: ${AUTH}" "${DOWNLOAD_URL}" -o "${FILEPATH}"

AWS CLI V2 is general available since Februray 2020. BUT 鈥

It is distributed as binary package (built on python and with pyinstaller that has bundled native libs) BUT鈥

  • Problem #1 this requires a decent GLIBC and probably won’t run on older redhat distributions
  • Problem #2 as it turns out many people use the official docker images to build their images and push to AWS ECR. and since these images are based on alpine and therefore use MUSL and NOT GLIBC it simply won’t run (but well people have seen now alpine pipelines in AWS builds although they do NOT support any other linux than their own; probably THEY HAVE TO)
  • Problem #3 you now have to download the application to update it (hey, the way to install software on windows or mac? but hey an own updater with aws/install –update)
  • Problem #4 forget installing and updating from pip for now; well you can directly pip from repo BUT it’s tricky. although the version says 2.0.38 (no beta or alpha!) it still requires a botocore==2.0.0dev42. i guess they should suffix a “ga” for “General Availability”.
  • Problem #5 If you belong to the majority (or the people with broken python installations) please refrain from saying “I have no problems! It’s better now!”

Anyway, they have some nyce features now and it seems they packed aws-shell right into to CLI:

#blacklivesmatter in Software Industry und So…

Ich sehe das so: Systemischer Rassismus* f眉hrte dazu dass eine heterogene aber ethnische Gruppe von Menschen bez眉glich ihrer Hautfarbe benachteiligt wurden. Mittlerweile wog die Ungleichgewicht durch die ganzen kleinen Benachteiligungen so stark, dass informell und formell jetzt eine Ausbalancierung stattfindet; “The White Man’s Legacy” sozusagen鈥

Leider wird dabei wieder gegen falsche Ziele oder 眉ber das Ziel hinaus gescho脽en. Es ist aber vor allem in unserer Zeit der Selbstradikalisierung besonders einfach, sich mit dem “correct a wrong” zu profilieren. Es z盲hlt wie in der Politik ohnehin oft nur noch das “moralisch korrekte”, da sich damit am einfachsten ill-informed Follower rekrutieren lassen. Ethisch gerechte sowie rationale Entscheidungen treten in den Hintergrund.

Getreu “yesterday’s heroes, tomorrow’s fool” d眉rfen wir wohl damit leben, dass Leits盲tze wie “Wenn nur einer im Team sich damit mehr inkludiert f眉hlt, dann machen wir das” unseren Hedonismus befl眉geln und dadurch auch ein Pressure auf Need-to-Change entsteht. Auch wenn dadurch mal was einfach total deppert benamst wird.

Ich denke das gute Kommunikation bei denen, die sich diskriminiert f眉hlen, dazu f眉hren kann, auch mal den Blickwinkel zu justieren. Nur weil in einem Chat jemand mal das falsche Wort getroffen hat, hei脽t dass nicht, dass es ein b枚se Person ist.

“Big solutions for Small problems”.

Davon abzulassen einen “Code of Conduct” zum Selbstzweck zu weaponizen – oder das mal zu erkennen. Steht man nicht for Logik und Verstand ein kann das bei vielen Justice Warriorn schnell zu einer toxischen Kommunikationskultur f眉hren (you know “logic is a patriarchal thing”). Trotzem, das Selbstwertgef眉hl dieser Personen sollte man nicht verletzen! Entweder arrangiert man sich, wenn nicht passt man vielleicht doch nicht zu der Gruppe.

Ich bin aber auch ein Vertreter davon, dass Sprache Realit盲t schafft. Aber es bringt nix Denkm盲ler sinnlos zu zerst枚ren, weil damit viele auch Sinnbilder einer Kultur verbinden. Es muss Verst盲ndniss geschaffen werden, welche negativen Bilder besser Narrative andere damit verbinden. Wenn zu kritisch, dann vielleicht ab damit ins Museum? Oder: “yeah, it’s time to lower the rebel flag!

Vielleicht m眉ssen wir ein St眉ck weit mit dem “Unsinn” mitschwimmen, und es vielleicht auch mal als Anregung sehen unsere eigenen Sichtweisen in Frage zu stellen.

Ist es nicht 盲hnlich wie beim Feminismus? eine Frauenquote betrachte ich strukturell als ungerecht, aber wir wissen mittlerweile auch, dass Frauen sich sehr positiv auf den Climatus auswirken, eben Diversit盲t. Das Problem ist eher der Maskulinismus, das Patriarchat, das nur als Anti-These zum Feminismus steht und es nicht geschafft hat, sich zu emanzipieren. So, ist jetzt besser zu sagen: ich schwimme als Whity mit allem mit, oder bin ich eher ein Mensch mit Intelligenz, Verantwortungsbewu脽tsein der sich erlaubt zu sagen: “Ich verstehe deine Punkte, aber Master kommt aus dem lateinischen ”

Und apropos Patriarchat: es ist tot, das Problem ist wir leben noch in den Resten von Rom.

Vielleicht sollte man sich auch mal 眉berlegen welche Pers枚nlichsdefizite oder -defekte man selbst hat und warum man sich so getriggert f眉hlt. Und das f盲ngt bei dem Qu盲lgeist der heutigen Zeit, Narzismus an, der ja bekannterweise durch Sozialisisation entstehen kann. Aber es geht ja weiter鈥 Depression, Borderline, bipolar…

Naja, mehr Gedanken zu dem Thema von Bryan Lunduke: Linux Kernel blacklists “blacklist”

5垄 on YAML in the DevOps world

Envsubst as a GitHub Action, Serverless Frameworks that just look like a YAML wrapper around an API, YAML based TaskRunners that somewhat reensemble the requirements of a CI . Not sure if everyoke understood the convention over configuration thing and why would do descriptive instead of imperative (CloudFormation anyone?). It reminds me more of people now pushing thin layered YAML wrappers since the micro NPM projects now look a bit old-school on the curriculum vitae 馃檮 Well, obviously it’s about getting things to be easier to grasp. But then again sometimes find odd solutions when you hit the limits. The question is rather: who does find the most usable one? Interesting read:

CSV tools

Some CSV utils which may come handy since most teams are dealing with that kind of formats 馃槈
  • – part of my default toolset 馃槈
  • – part of my default toolset 馃槈
  • – interesting read
  • – yeah, the ripgrep guy
  • – now part of my default toolset (yeah, json but faster than jq with “flatten” filter; line grep is powerful)
  • – patch/diff for CSV and spreadsheet data
  • – in trial

Pure BASH interactive CLI/TUI menu (single-/muliti-select/checkboxes)

First version. To be refactord.


Inspired by


  • This is a hacky first implementation for my shell tools/dotfiles (ZSH)
  • Intention is to use it for CLI wizards (my aim is NOT a full blown curses TUI window interface)
  • I converted TPUT to ANSII-sequences to spare command executions (e.g. tput ed | xxd --plain)

Permission to copy and modify is granted under the Creative Commons Attribution 4.0 license

Gedankenspiel: Automatisierung bei Big Corporate

Zielsetzung: Wir m枚chten von eigenes Autos auf Taxi als Dienstleister wechseln.

Wir kennen allerdings das Taxi-Business zu wenig, f眉hlen uns unsicher und bestellen daher erstmal Fahrer, die in unseren eigenen Autos Taxi fahren sollen. Die Fahrer sind aber keine ausgebildeten Taxi-Fahrer, kennen die Strassen nicht, und das Navi ist leider ein proprit盲res Produkt mit veralteter Karte. Allerdings von namhaften Hersteller, was nicht wirklich was bringt. Ebenso bieten wir auch unseren Fahrern Kaffee von Starbucks, damit sie nicht einschlafen und die Stra脽en lernen k枚nnen.

Ziemlicher K盲se, oder?

Kubernetes w盲re in dem Fall das Car-Sharing. oder Uber die Amazon-Services. Und weil Amazon es eh besser kann, denken wir, wir k枚nnten unseren “Taxi-Fahrern ohne Plan” ja von 脺ber gemietete Autos hinstellen, in der Hoffnung, das sie die Stra脽en dann effizienter abfahren.

Oder auf deutsch: warum Migration in Baby-Steps manchmal Unsinn ist. Automatisiert was geht, und nehmt bitte Abstand von halbgahren L枚sungen, weil Kontrollfreaks nunnal FUD und Babysteps propagieren. Die Zeit, die f眉r #reinventingthewheel oder das “wir wollen es erstmal verstehen oder sehen dass es funktioniert” drauf geht, kann man getrost auch ins Development stecken. Infrastructure first. Nehmt euch DevOps die euch ne Infrastruktur und ne CI hinstellen und l盲sst sie machen. Umso schneller steigt ihr in eure eigenes Taxis ein und m眉sst euch um den Weg zum Ziel keine Gedanken mehr machen. Je besserer die Automatisierung l盲uft, desto weniger Fehler gibt es. Eine Liste mit zig Punkten, die trotzdem manuell abgearbeitet werden muss, bleibt nunmal fehlertr盲chtig und es geht nur menschliche Zeit und Nerven darauf. Und Devs lernen auch nichts, au脽er menschliche Fehler zu wiederholen. Also, noch mehr Frust satt an einer CI zu arbeiten, die Dinge wirklich einfacher machen w眉rde. Time to Rollback. Time to go live. Instant response. Zeit f眉r Tests und Qualit盲t statt immer der gleiche Bullshit.

Auch ja, und dann gab es noch diese fetten Limosinen aka. vertikale Bare Metal Skalierung. Hat sich leider im Berufsverkehr als unpraktikabel erwiesen. Aber h眉bsch sehen sie ja aus. Wer’s braucht…

PHP: just in case posix_isatty() is missing

From StackOverflow

Short function

function is_a_tty() 
    static $result;
    if (is_null(result)) {
        $fp = fopen('php://stdin', 'r');
        $stat = fstat($fp);
        $mode = $stat['mode'] & 0170000; // S_IFMT
        $result = $mode == 0020000; // S_IFCHR
    return $result;

Info Class from StackOverflow by leigh


class IOMode
    public $stdin;
    public $stdout;
    public $stderr;

    private function getMode(&$dev, $fp)
        $stat = fstat($fp);
        $mode = $stat['mode'] & 0170000; // S_IFMT

        $dev = new StdClass;

        $dev->isFifo = $mode == 0010000; // S_IFIFO
        $dev->isChr  = $mode == 0020000; // S_IFCHR
        $dev->isDir  = $mode == 0040000; // S_IFDIR
        $dev->isBlk  = $mode == 0060000; // S_IFBLK
        $dev->isReg  = $mode == 0100000; // S_IFREG
        $dev->isLnk  = $mode == 0120000; // S_IFLNK
        $dev->isSock = $mode == 0140000; // S_IFSOCK

    public function __construct()
        $this->getMode($this->stdin, fopen('php://stdin', 'r'));
        $this->getMode($this->stdout, fopen('php://stdout', 'w'));
        $this->getMode($this->stderr, fopen('php://stderr', 'w'));

$io = new IOMode;


$ php io.php
// Character device as input
// $io->stdin->isChr  == true

$ echo | php io.php
// Input piped from another command
// $io->stdin->isFifo == true

$ php io.php < infile
// Input from a regular file (name taken verbatim from C headers)
// $io->stdin->isReg  == true

$ mkdir test
$ php io.php < test
// Directory used as input
// $io->stdin->isDir  == true

$ php io.php
// $io->stdout->isChr  == true

$ php io.php | cat
// $io->stdout->isFifo == true

$ php io.php > outfile
// $io->stdout->isReg  == true

$ php io.php
// $io->stderr->isChr  == true

$ php io.php 2>&1 | cat
// stderr redirected to stdout AND piped to another command
// $io->stderr->isFifo == true

$ php io.php 2>error
// $io->stderr->isReg  == true

I hope those PHP stuff finally dies 馃檨

Infojunk November 2018

Hacking / MITM-API-Testing





  • KataCode Playground with fully funcional real browser shells for learning without barriers (using Containers?)
  • GoTTY
    How about gotty -w docker run -it --rm anapsix/nyancat:alpine?