Devops. I've never asked for this.

Make keepalived play nicely with netplan/ systemd-network

TL;DR: Use use_vmac directive in keepalived when using multicast and your carrier allows multiple MAC addresses per interface. If that’s not an option, migrate away from netplan/systemd-networkd, e.g. to ifupdown.

Saturday night, 06:00:
I was torn from my sleep by the lovely voice of my colleague, uttering the words dreaded among the ops community: “We’re down, Chris.”

After opening the lid of my notebook, I started digging into the issue.

We’re running several high availability services with the help of keepalived. When a service goes down, keepalived switches over services to a standby instance. This is usually done by assigning a dedicated virtual IP address (VIP) to a service which can then be migrated on the fly between instances. This is achieved by keepalived using the Virtual Router Redundance Protocol (VRRP) as described in RFC5789, and has proved itself to be very reliable in the last years.

Not so today. The primary server somehow lost its VIP, without any notice in the log files. Just like that. I reassigned the VIP manually, verified that we’re back up and went back to sleep.

We then did a post-mortem on Monday. Obviously, we wanted to know what the heck had happened, and how we could prevent it from happening again in the future.

cache_warmer - tool to warm-up HTTP caches

I’ve written a small tool to warm-up HTTP caches, e.g. services like nginx.

Get it

Source code as well as compiled releases are available at Github.

Comparison to other tools

While most tools in this area are designed to apply a certain load to a web server (often for a specified time), cache_warmer is designed to explicitly GET a set of URLs from a file to warm-up a cache.

sslsecure.vim - Highlight insecure SSL/TLS cipher suites and protocols as errors in your editor

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on.

Edward Snowden

When configuring or programming SSL/TLS servers, at some point a SSL/TLS cipher suite and a list of supported protocols have to be chosen. Unfortunately, not all configuration options are safe. :(

Meet sslsecure.vim! A plugin for the Vim editor, that marks insecure SSL/TLS cipher suites and protocols as errors. See all potentially insecure options right in your editor!


  • Mark insecure SSL ciphers as errors
  • Mark insecure SSL protocols as errors
  • Works with all configuration files (web servers, mail servers, …)
  • Works with all source code (independently on the used programming language)
  • Works on top of regular syntax highlighting

Better syntax highlighting and snippets for nginx in vim

I’m editing nginx configuration files. A lot. Naturally, I’ve tried several plugins for my favorite editor vim - but ran around a lot of problems:

  • Most of the plugins available are outdated.
  • Even syntax highlighting of the current vim plugin distributed with the nginx release has some deficits.
  • I’ve been tired of copying around secure ssl_cipher directives, etc.

So, I’ve created a new, super-cool and mega-advanced vim plugin for nginx!

Ladies and gentlemen: Please welcome, chr4/nginx.vim!


The plugin is based on the recent vim plugin distributed with nginx-1.12.0 and additionally features the following syntax improvements:

  • Highlight IPv4 and IPv6 addresses
  • Mark insecure ssl_protocols as errors
  • Inline template syntax highlight for ERB and Jinja
  • Inline syntax highlight for LUA
  • Improve integer matching
  • Syntax highlighting for proxy_next_upstream options
  • Syntax highlighting for sticky options
  • Syntax highlighting for upstream server options
  • More to come!


  • Remove annoying delimiters, resulting in strange word boundaries


A server block with highlighted insecure SSL options:

nginx server block with SSL configuration

Cross-compile and link a static binary on macOS for Linux with cargo and rust

One Go feature which I’m using regularly is cross-compiling Go code to other platforms (usually from macOS to linux-amd64).

In Go, this is a built-in feature that “just works”. The following command produces a statically linked ELF binary which can simply be copied and run on a Linux machine:

$ GOARCH=amd64 GOOS=linux go build
$ file api
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

Rust doesn’t have built-in support for such a feature. Edit: Rust core-commiter Steve Klabnik pointed out, that actually what I’m showing off here is the built-in Rust support :)

I’ve been looking for a while how to achieve this using Cargo and Rust. And (spoiler-alert!) I’ve found one, which is relatively simple to set up.

Writing An Interpreter In Rust (Part 2)

Note: This is a follow-up post to Writing An Interpreter In Rust

Thanks for all your feedback, explainations and pull requests! I’m pretty overwhelmed by the feedback and I can confirm that the Rust community is very friendly and extremly helpful.

In this post, I want to quickly review some of the changes to my implementation of the Monkey interpreter I’ve made with your help. I’ve implemented a small benchmark (Disclaimer: I’ve just put next_token() into a #[bench], I’m not sure whether that’s the best practise for this kind of tests), and the results are really impressive so far!

First implementation:

$ cargo bench
test tests::bench_next_token ... bench: 30,614 ns/iter (+/- 2,177)

Current implementation:

$ cargo bench
test tests::bench_next_token ... bench: 3,863 ns/iter (+/- 627)

The new implementation is almost ten times faster than the first one! Let’s have a look at the changes:

Writing An Interpreter In Rust

Last month, Thorsten Ball released his first book: Writing An Interpreter In Go. It’s an awesome book that teaches its readers how to write their own programming language, step by step. It comes bundled with the complete Go code, including tests.

While reading it, I was looking for a challenge. I’m a huge fan of Rust, a safe systems programming language by Mozilla, so I thought it might be a good exercise to port the Go implementation of the programming language “Monkey” to Rust.

Here’s an example of what Monkey code looks like (you can find more examples here):

// Bind values to names with let statements
let version = 1;
let name = "Monkey programming language";
let myArray = [1, 2, 3, 4, 5];
let coolBooleanLiteral = true;

// Use expressions to produce values
let awesomeValue = (10 / 2) * 5 + 30;
let arrayWithValues = [1 + 1, 2 * 2, 3];

Use and automate letsencrypt certificates (ACME) in an high availability environment

Mozilla launched a “free, automated and open” certificate authority called Let’s encrypt. As the name suggests, it provides free certificates trusted by all (major) browsers and operating systems. I’m using it heavily (on this blog, for example).

This blog post shows how Syncthing can be used to deploy letsencrypt certificates in an environment with multiple servers (e.g. in a round-robin scenario) without adding a single-point-of-failure.

entren - I just stumbled upon a traffic analyser I wrote in C when I was like 17

Around the year 2000-2002 (back in the days when Snort was still super young (and I haven’t heard of it yet), I decided to write a small network traffic analyser, which could serve as a “poor man’s intrusion detection system”. It was basically a C daemon configured with a ini-like configuration file, watching for network events.

If I remember correctly, I wanted a way to detect the (then pretty new and fancy) nmap stealth scan mechanisms (like half open, xmas, etc), and counter them with alerts and on demand firewall rules.

I just stumbled upon the old C source on my harddrive ssd on my macOS machine and tried make just to see what would happen. Back then I operated some FreeBSD/ OpenBSD and Linux servers, and I didn’t really expect much to happen besides tons of errors.

As it apparently still compiles and runs today (even on macOS), I’ve decided to upload the code to Github.