musicmatzes blog

Some of you might know that I am using KDE Plasma for some time now and that I am really in love with it. Lately, I've been even more in love with it.

Here's why.

A new device

As I recently switched my job, I had the opportunity to get my hands on a new device (thank you, employer)! I opted for a Tuxedo Pulse 15 Gen 1 which is a wonderful device. I might be writing about that in another article.

Naturally, I installed my favourite linux distribution on it (which is NixOS) and KDE Plasma. After updating the device and all my other installations to the latest release of NixOS (which is 21.11), I was greeted by the brand new KDE Plasma 5.23 welcome screen.

KDE Plasma has been running absolutely smooth on my old device (which I still use), which was a Tuxedo InfinityBook 14 Pro v4. Still, I was even more amazed that on the new device, it ran even smoother. There are no glitches, no screen flickering even while plugging in an external display, not the slightest stuttering while moving around. Don't get me wrong, there hasn't been any of these things with my old Tuxedo, too! Still, it felt so new and refreshing on the new installation that I absolutely had to write about it.

Initial setup

The initial setup of my KDE experience involves some work. The default configuration of the KDE desktop experience is really nice, but I need some custom shortcuts to be as productive as I want to be. For example, I want to use the HJKL keys for some tiling stuff. KWin, the KDE window manager, is not a tiling window manager. Still, you can get some basic layouting to work with it (top-right-corner, right, lower-right-corner and so on). Also I need key bindings for fullscreen, switching virtual desktops and bringing up Krunner, KDEs app launcher/search tool/... whatever you call that awesome piece of software!

Krunner

Krunner is awesome. It is much more than just an app launcher. With the (firefox) browser integration, you can search bookmarks, history, open tabs (and switch right to them), you can search windows, passwords (password-store anyone?) and of course you can launch applications from it. It just integrates so nicely with KDE, it is amazing.

Plasma-browser integration and kdeconnect

Plasma browser integration (for firefox) is god-sent. Combined with kdeconnect, which is another god-sent tool, it makes the experience perfect. Notifications from my mobile phone can be synced to the desktop and the other way round (although I disabled this specific setting because I tend to get a lot of notifications on my mobile phone that just annoy me on my desktop, especially when in a call with co-workers). Whenever someone calls, my music or netflix stream (this is made possible via the plasma browser integration) is automatically paused and (of course) resumed as soon as I hang up. I can send websites from my browser to my phone when I want to continue to read while in the bathroom (we all do that, don't laugh!) and of course also the other way round. And so on and so forth...

All the details

The details of course matter. For example: I just found the setting to disable the touchpad while typing. I toggled it and it just works like a charm. I added a script that executes ssh-add on my ssh keys to the autostart scripts and it justs works, asking me for the password of my ssh key to add it to ssh-agent after login. Enabling the integrated redshift for KDE was literally one click in the settings, now I get a redish (is that a word?) screen in the evening, which is more eye-friendly.

Conclusion

My conclusion is clear and obvious: Love! I don't know why I would ever switch away from KDE again. It is the same as with my NixOS experience, that started in 2014. I just don't see why I would switch away from something that is so good.

Maybe this article was a bit annoying to you now, me fanboying about KDE. I don't know. It's just something that I wanted to share.

Enola Homes is a 2020 (netflix) mystery film.

I have to say that I am a big fan of Sherlock Homes, the Benedict Cumberbatch version. So I was a bit skeptical whether “Enola Homes” would entertain me. Though, my fears were proven unfounded, as the movie was fun and exciting!

Plot

Enola Holmes is the youngest sibling in the famous Holmes family. She is extremely intelligent, observant, and insightful, defying the social norms for women of the time. Her mother, Eudoria, has taught her everything from chess to jujitsu and encouraged her to be strong-willed and to think independently.

wikipedia

... one day, her mother goes missing. Naturally, Enola tries to find her.

I won't share more here, as always. Giving away too much of the plot just reduces the entertainment if you, dear reader, watch the movie.

Reception

The movie has a 7.1/10 rating on rottentomatoes, according to wikipedia, which is quite good.

I would rate it with 8/10. Also, a sequel was announced in May 2021!

I am co-maintaining a few crates in the Rust ecosystem. Some very passively, some (config-rs) more actively. From time to time, and lately more frequently, I see more and more “conventional commits”. I hate them with a passion and for the repositories I frequently ask people to rewrite their commit message. I even went as far as picking their commits to my local repository and rewriting the commit messages by hand (yes, FOR THEM even though it is not my job).

What “Conventional Commits” are

Conventional commits is a (pseudo)standard. Its tagline is

A specification for adding human and machine readable meaning to commit messages

and it advertises itself as a “lightweight convention on top of commit messages” (source).

The idea behind conventional commits is that one can write tools to parse commit messages and process the found data, for example to generate changelogs. Other uses come to mind, for example for gathering statistics (“who writes the most 'feature' commits?”).

The Premise is wrong!

The premise that generating a changelog from git commits is a good idea is utterly wrong, though.

First of all, commit messages are there for developers of a software to understand why you did what to achive what goal (see also: 1, 2, 3). Generating changelogs from commits results in not very much more than git shortlog lastrelease..currentrelease. Changelogs are mainly for the users of the software. These users might be developers, if the project is a library, but the point stands. A user of a software should never have to concern themselves with stuff that happened during the development of the next release of that software. They are concerned about what changed for them. These things might overlap, yes, but they are never equal!

Conventional Commits hurt!

From the real world out there – from maintaining a few software projects – I can tell you this: Not ONE SINGLE conventional commit message I've seen in recent years did actually a good job. None, yes I say it again: NONE, has actually described what the commit was about!

That's of course not necessarily a fault of the idea of having machine-readable commits, but a direct result. Why? Because people start thinking that now that they're writing a “machine readable” format in their commit message, they provide more value in the commit message than before. This results in shorter commit messages with fewer details.

Fun is, that the website for conventional commits actually markets this:

feat: allow provided config object to extend other configs

BREAKING CHANGE: extends key in config file is now used for extending other config files

That's the first example on the website. What does this commit message actually tell us? It tells us that in the software project at hand, there is a “config object” and that now this object can be used to extend other configs.

Fine.

It does not tell us why this change was made (other than that it is a new feature now) and it does not tell us what was done for this to become possible. It tells us that there is a breaking change, but it does not tell us why there was this breaking change, whom this may concern, why this might be a problem even, or how users should react to this breaking change.

Further, I deduct that this change might be a complex one. Of course, nobody can tell from the commit message alone, but lets just assume for one minute that introducing this change actually entailed a few hundret lines of code added to the codebase of the project and another few tens of lines changed.

I can almost guarantee you (haha, you may think... guarantee with a fictional software project – yes! Please stay with me here), that implementing this change in not one commit but maybe three or more seperate commits, one atomic change after another, would result in a way better history! Way better discoverability for developers!

After the change was accepted, the cover-letter, pull/merge request description or merge commit itself can of course contain a detailed description that later might end up in a CHANGELOG.md file (although some argue that having such a file is not beneficial in any way).

How to do better

It is so easy to do better than conventional commits! Actually, there are only seven rules you must follow for nice commit messages! Just read this article – or, if you're lazy, I copy them for you here:

  1. Separate subject from body with a blank line
  2. Limit the subject line to 50 characters
  3. Capitalize the subject line
  4. Do not end the subject line with a period
  5. Use the imperative mood in the subject line
  6. Wrap the body at 72 characters
  7. Use the body to explain what and why vs. how

It's as simple as that.

I would even add another rule: Use --signoff when committing for using the Developer Certificate of Origin (see also 1, 2).

I didn't post a movie review for a long time. So let's have one again. This time I want to write about “Outside the Wire” which is an 2021 Action movie.

Plot

As always, only a short teaser from the Wikipedia page of the movie:

In 2036, a civil war between pro-Russian insurgents and local resistances in Ukraine leads the US to deploy peacekeeping forces. During an operation, a team of United States Marines and robotic soldiers are ambushed. Disobeying an order, drone pilot 1st Lt. Harp deploys a Hellfire missile in a drone strike against a suspected enemy launcher, killing two Marines caught in the killzone but saving the 38 Marines who would have been killed by the launcher. As punishment, Harp is sent to Camp Nathaniel, the US base of operations in Ukraine.

The plot is nothing usual, but also nothing special in the end. I liked it a lot, though!

Reception

I cannot agree with the rottentomatoes reviews on this one! On rottentomatoes, this movie has a 4.9/10, but I would rate a solid 7/10. There is a lot of action, not too much emotion, which is good for this genre, and a fair bit of “race against time”, but nothing too heavy.

I can recommend this one.

With the end of the year, I will be changing jobs. This was not an easy decision to make for me, but in the end I guess it turned out to be the right decision for my career path.

First of all, I would like to stop for a moment and thank my (soon to be ex) colleagues at science+computing ag for the last (almost) three years! During my time at science+computing I learned a lot, not only about technical things, but also about how things work in the industry and related topics, and I was able to grow a lot (as far as I can tell). The problems we solved were challenging and gave me the opportunities I needed to enhance my skills in the field of Linux, packaging, programming and development, but also in negotiating with colleagues or customers on both technical and social issues!

I especially want to thank my team for these fun times, awesome team-dynamics and a team lead that was always there when needed, easy to talk to and for the freedom they gave the team in making their own decisions!

Next...

Starting next year, I will be joining a new company (I am not yet sure whether I am allowed to talk about details) which will give me even more options to grow my development skills, especially in the Rust ecosystem – which is I am really looking forward to! I am intrigued about what challenges I will be asked to solve and am really looking forward to meeting my new colleagues.

If I am allowed to talk about details of my work (which might actually be allowed), I will post here and, of course, on my mastodon account!

I have been playing with functional languages a few times now. I have tried Haskell, Elm and Elixir so far, but also played a bit with a LISP-like language that is implemented in Rust for being easily embeddable into Rust programs.

Lately, I also played with “roc” (https://www.roc-lang.org/), which is a new approach for a functional programming language that can compile to binary (using LLVM) that also has some new ideas.

One of these ideas, that I quite like to be honest, is the idea of “platforms”. A developer has to write a minimal platform the program they want to write runs on. This platform is nothing more and nothing less than the interface between roc and the outside world – which is stateful! So the platform deals with allocation and deallocation, talks to the operating system to, for example, read from the commandline or handle incoming network traffic. The platform has to be very minimal, and must ensure that there is no state leaked through to the roc program!

roc itself has a syntax that is rather nice, although I think there can be improvements. The idea of the authors is that roc should be easy to use, like Elixir or Elm, spark joy in the programmer and still be fast. In fact, it has been shown (in a very unscientific benchmark IIRC, but that's more due to the fact that roc is in very early development as in due to other reasons) that roc can in fact outperform imperative languages in some cases! Leveraging the power of LLVM is one of the reasons for that, but also that roc enables performance optimizations that are not possible or very hard in other circumstances.

To conclude, I am really looking forward to roc and hope that it will be more “you can play with this”-ready than it is today. Right now, compiling everything from source all the time (roc is written in Rust) and having only very few pieces of documentation available, makes playing with roc hard. I hope that will improve soon.

To quote myself:

So my ideal #functional #language #programminglanguage would be a pure functional language with traits/interfaces, ergonomics like #ruby or #elm or #elixir, performance like #rust because it compiles to binary with #llvm, with the “platform” approach #roc #roclang currently has, so one can provide minimal interfaces to the OS ...

Which would make it a perfect language for #containers and #microservices but also #CLI tooling and even websites via #wasm (if it can compile to wasm)!

... and I think roc can be that language!


Please note that roc is not released as opensource codebase at the time of writing this article, but it will be as soon as the author thinks it is time. I wrote “roc” in lowercase letters in this article because – and only because – I think that's how it is intended.

Some people might have noticed that I like to go hiking from time to time. During my hikes, I normally listen to music, techno or trance most of the time. That kind of music gives me a certain push to walk faster or keep walking, but also gives me enough “free space” in my head (is not too distracting for me like for example metal is). That's perfect for thinking about topics that concern my life at the moment.

Most of the things I am day-dreaming about are not too serious. This article is about one of them.

From a normal daydream...

My normal daydreams start off at my current situation and goes from there into a future I would like to live. Normally, it is about minimalism, being able to go hiking in other countries, for example the USA or Canada, but also Iceland, Norway or sometimes Spain (I'm more a “Go-North” kind of hiker) or having a camper van and exploring countries in Europe with it, all while being able to work while being “on the road”. That's what (digital) nomadism is, but in a more “light” variant, as (digital) nomads normally do not have a home-base (as far as I know, some of them might beg to differ).

On my last hike, though, I thought about how an utopian future life would look like, how I would like to experience the future. Some of these things might be achievable, but most of them are probably not.

And of course, all thoughts were ...

... starting with minimalism

The concept of minimalism is not only an idea that improves your life on a psychological level, but also (and maybe even more so) on a practical one, of course. If you have less things, less things can brake, can go missing or have to be taken care of.

That's of course nothing new.

But what if you have so few things that you can enable a whole new lifestyle? I wrote about “extremist minimalists” before, and maybe that's the direction these thoughts are going. Having only 100 things is most certainly complete overkill and maybe not even possible in European culture. But having, say, less than one thousand things, enables you to just pack everything you have into a (rental) car and just drive away from your current location, leaving everything behind.

On the realistic side, though, it is not that easy, is it? One must cancel their rent, must de-register their water supply, power supply, one probably must change their contact settings in their bank account, several insurance accounts. Ones employer must know about their whereabouts, even if it is only for taxes. People are not allowed to be unregistered in Germany (or even in Europe?), so they must notify the Citizens Registration Office somehow about where they are... which might not even be possible if there is no address (think of living in a camper)!

So being a minimalist is the one thing, but being able to move is a whole other story, save moving ones things around.

Being able to just move away

Being able to just hit the road and drive to another country never has been so easy in Europe. The Schengen-Abkommen made it possible for millions of Europeans to just sit in their car and drive to their neighbor country for vacation, all without actually having to go through a tedious process at the border! Crossing the border in Europe is the same as crossing from your kitchen to your living-room! Accepting a job in another country is easy in Europe (AFAIK, IANAL). One just has to accept an offer, get a flat nearby (or not, if its a remote position) and that's basically it.

Or is it? What about insurance? Will my German insurance pay if I fall down the stairs in my Paris apartment? Will my doctor in Vienna be payed by my insurance if I have to visit them? Who pays if I hit a car with my bicycle in Madrid? What if my flat in Bergen burns down, does my german insurance cover that? Probably not!

I don't know the answers to any of these questions, and although they are hypothetical, they bug me whenever I think about (digital) nomadism.

But the general idea is amazing to me. Having the option to move to Norway for a summer, to southern Spain for a winter, just because you want to is really an awesome idea and I hope I can pursue that idea at some point, maybe with a camper or maybe even without one.

From time to time (read: daily), I get messages from recruiters on platforms like LinkedIn or Xing. 99% of them do not even care to read my profile. I don't know whether this is just because they're bots, or because every recruiter uses the shotgun-approach and just sends out invitations like crazy because they actually do not care.

So here is a bullet point list for you, dear recruiters:

  • If you can't pay what my profile says, leave me alone!
  • If you cannot even read what technologies I'm interested in, leave me alone!
  • If you don't want to “hire me, but win me for your team”, leave me alone!
  • If you cannot provide a 100% remote work position, leave me alone!
  • If you think that “new opportunities with Microsoft insert any MS product here” would be interesting for me, leave me alone!

Also: If you read this in 2021 or 2022, leave me alone as well! I'm perfectly happy right now!

I've been playing with thoughts about kubernetes a lot lately. Today I finally found the courage and motivation to just try out to write some services and deploy them.

The idea was to write some simple “hello-world” style application, deploy it on some kubernetes and serve them locally on my machine – just to get the hang of the ecosystem and how it all works.

And because I'm running NixOS of course, I wanted to leverage the power of the nix package manager to ease my deployment mechanisms as far as possible.

Building docker images can be done by nixpkgs, so that's not an issue at all. There's also the great kubenix project, which can be used to generate kubernetes deployment configuration files using nix. Plus we're using kind, which is used to spawn a full kubernetes cluster inside a docker container on my notebook – that's really nice for development!

But first, we need to implement the

Services

Writing the service(s) was rather simple (because Rust, yay)! I decided to make it not completely trivial, and to write three services:

  1. A service that serves “Hello”
  2. A service that serves “World”
  3. A service that uses the other two services and joins the strings they serve together and serve the result

The implementation of these services are rather simple and don't need any explanation for the experienced Rustacean. And because I'm assuming a fair bit of Rust knowledge here, I'm not quoting the source here.

The “echo-style” services are implemented using actix-web in version 3, the “joiner” service is implemented using it in version 4 (beta 9), because version 3 does not support calling the tokio runtime and I need to do that to be able to query the other services asyncronously without too much hassle.

All services expect a HOST and PORT environment variable to be set, which they use to bind to. The “joiner” service also expects HELLO_SERVICE and WORLD_SERVICE, which should point to the services serving the “Hello” and “World” strings respectively.

All three binaries are built using the most simple nix expression:

{ pkgs ? import <nixpkgs> {} }:

with pkgs.stdenv;
with pkgs.lib;

pkgs.rustPlatform.buildRustPackage rec {
  name = "hello-service";
  src  = pkgs.nix-gitignore.gitignoreSourcePure "target\n" ./.;

  cargoSha256 = "sha256:0nam3yr99gg0lajdha0s9pijqwblgwggqi94mg7d3wz7vfhj8c31";

  nativeBuildInputs = with pkgs; [ pkg-config makeWrapper ];
  buildInputs       = with pkgs; [ openssl ];
}  

(the other default.nix files look similar)

Deployment

I started learning about how to write the deployment following the great article from tweag.io – Configuring and Testing Kuberentes Clusters with kubenix and kind.

That article is truly the main resource I used and you should definitively read it if you want to reproduce what I did here. It explains some details way better than I could!

One minor inconveniance though, is that kubenix does only support kuberentes 1.18, but I was using kubernetes 1.22 for this example service. It worked, but my implementation might stop working with kubernetes 1.23!

That said, kind can use older kubernetes versions with the --image flag when creating the cluster, which might work to get a kuberentes 1.18 up and running!

The layout of the repository is as follows:

configuration.nix
default.nix
nix/deploy-to-kind.nix
nix/kubenix.nix
service-hello
service-hello/Cargo.lock
service-hello/Cargo.toml
service-hello/default.nix
service-hello/src
service-hello/src/main.rs
...

As you can see, the service implementation is just a subdirectory. The individual services can be build using nix-build ./service-hello/ for example.

The deployment gets generated by configuration.nix, whereas default.nix is used to orchestrate the whole thing and build some neat helpers.

Building docker images

Nix has awesome tooling in nixpkgs for building docker images. We can use that to build docker images with our binaries without actually pulling in too much:

  helloImage = pkgs.dockerTools.buildLayeredImage {
    name = "hello-service";
    tag = "latest";
    config.Cmd = [ "${helloService}/bin/service-hello" ];
  };

That goes into our default.nix.

These images are later loaded into the kind cluster (automatically, thanks to nix) when starting the cluster.

Generating the deployment

Lets have a look at the configuration.nix! The first few lines of that file are simple definitions about the services. We define their name (label), which port they run on, how much CPU the pods may use they are running in and their environment:

  helloApp = rec {
    label = "hello";
    port  = 3000;

    cpu = if type == "dev"
    then "100m"
    else "1000m";

    imagePolicy = if type == "dev"
    then "Never"
    else "IfNotPresent";

    env = [
      { name = "HOST"; value = "0.0.0.0"; }
      { name = "PORT"; value = "${toString port}"; }
    ];
  };

These values are later used to write the deployment of the individual services. The neat thing is: The “joiner” service needs to know (for example) which ports the other services run on. But we don't need to duplicate that data, because we can re-use it from the definition of said services:

  joinerApp = rec {
    label = "joiner";
    # ...
    
    env = [
      # ...
      { name = "HELLO_SERVICE"; value = "${helloApp.label}:${toString helloApp.port}"; }
      { name = "WORLD_SERVICE"; value = "${worldApp.label}:${toString worldApp.port}"; }
    ];
  };

Using the values, we can then implement the deployments of each of the apps with all the bells and whistles as well as implementing the services in the cluster.

Last, but not least, we need to add an ingress to route traffic from outside the cluster to the “joiner” service.

Deploying

That's all nice and dandy, but we also need some mechanism to deploy the whole thing, you mean?

That's where nix comes in handy! What we can do is, let nix write a script that handles all the deployment steps for us. That script gets the images we just built using docker as input, and copies them into the kind cluster when run. It also gets the generated configuration for the cluster, which it applies automatically as soon as the cluster is created (it also prints it as JSON for discoverability). Lastly, it ensures that an ingress controller is available in the cluster, which is needed for routing the incoming traffic to our “joiner” service.

Putting it all together

Finally, the default.nix file puts it all together. There are even some more possibilities than the file implements (I never actually tried to run the deploy-and-test shell).

I simply used the shell implemented by the file and ran deploy-to-kind to start the kind instance and deploy everything inside.

Wrapping up

It took me one whole day to figure out all the details, but finally I got it working. This has been a really nice experience and although kubenix seems to be unmaintained as of two years, it worked and was not too complex to use for that simple usecase.

As always, nix is a pleasure to work with, as is Rust! I hope to be able to use both professionally at some point – lets see what the future brings ;–)

“Unlocked” is a 2017 British-American action thriller movie starring Noomi Rapace and Orlando Bloom.

I had this movie on my watch list for a rather long time. Too long, to be honest. But first, let me lose some words about the

Plot

As always, I am giving away only a bare minimum of the plot so that I do not spoiler you.

CIA officer Alice works undercover at a community center in London. She passes on intel to the security services. The CIA and MI5 learn that radical imam Yazid Khaleel plans a biological attack on an American target on British soil in collaboration with American-born Islamic convert David Mercer.

That's boiled down from the plot on wikipedia.

Reception

On rottentomatoes the movie only has a rating of 4.31/10:

Unlocked strands an all-star cast in a spy thriller whose embrace of old-school formula might be refreshing if it weren't bogged down in genre clichés and a predictable plot.

I can only partly understand that. Of course the plot is a bit foreseeable, still, I was really well entertained. I did not yet see many movies with Orlando Bloom (safe Lord of the Rings and Pirates of the Caribbean of course) and he has a really nice role in this movie.

I would rate this movie with a solid 7/10!