erdgeist is a Berlin based freelance and open source developer and political activist. Feel free to stroll around in the public parts of his brain.


Write an email to preferredly PGP encrypted, the key, fingerprint: 68D0 5298 6E09 BF62 94B8 4DD0 B8DD 7017 2A6C 30D3. Reach me via Jabber at, where my OTR fingerprint is 7A4BC16B 479D4D10 EAC30B3B B52FD269 ADF818E3.

Follow @erdgeist on Twitter. Listen to the OHM podcast with monoxyd and CCC's monthly radio show Chaosradio. Look out for contributions to Die Datenschleuder and, sporadically also on Frühstücksblog. Get the book 1984.exe.

Software projects

opentracker is a highly scalable tracker software for the bittorrent protocol, currently in use on the largest bulk trackers around.

ezjail is a jail management framework for the FreeBSD operating system, aiming to aid in setting up und updating virtual FreeBSD instances.

jaildaemon is a tool for the FreeBSD operating system to allow flexible and secure communication from jail environments to the host system.

minimunin is a tiny munin-node implementation for FreeBSD written in pure bourne shell providing basic plugin support.

elektropost is an ongoing mail server and webmail frontend project, documented to be set up on a FreeBSD jail and instanced on

el is a unix tool aiding the Telefonbuch project for export and search queries.

anonbox is a web service to generate and maintain throw away email addresses, instanced on, including a javascript implementation of a unicode capable mbox-to-html renderer.

Telefonbuch is a project to quickly dump a certain kind of digital phone books.

vchat-client is a curses based chat client for the arcane vchat protocol.

briefkasten is a web service to anonymously submit messages via the web generating PGP mails and is instanced on the zeit-online briefkasten.

timestretch is a fast implementation for SOLA, a sample time stretching algorithm.

etherpad is a documentation project on how to setup the classic etherpad software in a FreeBSD jail.

Unless state otherwise, the software is released under beerware license. Some project's documentation is not yet migrated. You can also browse around my gitweb.


  • Steueranachronismus

    Nachdem mir neulich schon das wundersame Relikt des Kirchgelds über den Wahrnehmungshorizont purzelte, mit dem sich die traurigen Reste des sich dem Laizismus wiedersetzenden Staatskirchentums ihre Pfründe auch von all denen zusammenschmarotzen, die auch nur das Leben mit einem Partner teilen, der seinen Kirchenaustritt nicht mehr belegen kann oder als EU-Bürger in Deutschland in bürokratische Hamsterräder verwickelt wird. Nach der Wende wurde arbeitslos gemeldeten Freunden gar die Kirchensteuer standardmäßig einbehalten mit dem Verweis darauf, dass eine präzise Nachforschung im Einzelfall zu hohen Aufwand bedeuten würde.

    Heute nun weist mich die Sparkasse in einem Kundenschreiben auf Folgendes hin

    Diese Information ist für Sie nur dann von Bedeutung, wenn sie einer
    Religionsgemeinschaft angehören, für die Kirchensteuer abgezogen wird.
    Sofern dies der Fall ist, führen wir für Kirchenmitglieder ab 2015 die
    Kirchensteuer auf Kapitalertragsteuer automatisch an das Finanzamt ab,
    sofern die Kapitalerträge oberhalb eines uns erteilten Freistellungsauf-
    trages liegen, spätestens also oberhalb des gesetzlichen Sparerpauschbe-
    trages (Ledige: 801 EUR, Zusammenveranlagte: 1602 EUR). Zur Vereinfachung
    fragen wir Ihre Religionszugehörigkeit jährlich beim Bundeszentralamt für
    Steuern (BZSt) ab.
    Möchten Sie nicht, dass das BZSt uns Ihre Religionszugehörigkeit ver-
    schlüsselt übermittelt, können Sie der Datenweitergabe bis zum 30.06. eines
    Jahres widersprechen (,"Kirchensteuer").

    Kann sich diese Sekte nicht einfach mal aus dem Leben Unbescholtener raushalten, solange diese sich nicht explizit bei denen melden? Ich zumindest will mit denen nichts zu tun haben und finde, in ihrer Geschichte haben sie genug Unheil angerichtet und könnten sich gefälligst in ihrer selbstpropagierten Demut üben. Danke.

  • Write the flogging manual

    More than thirteen years ago I set up my personal website. Proudly aligning everything with tables, hand writing HTML with pico vi, using "clever" apache server side includes to inherit styles from parent directories and making everything so artsy bordering unreadability. And while in the beginning writing in HTML seemed fun, in the end it became so tedious, that updating the blog came to a grinding halt (we're all not getting younger).

    So in order to be able to publish again, I needed something more seasonable, with a responsive theme and simple enough to last another thirteen years. But my site accumulated so much cruft others depended on, replacing the apache alone with something more modern seemed unfeasible. Yet, my rather static content would best be served as static files by a simple web server – using an insecure scripting language on top of a complex database setup was completely out of the question. I once went through the pain of setting up and maintaining a wordpress site for my dad, there's no need to repeat that agony for something I'd like to use on a daily basis.

    But all the projects out there that would allow me to generate a static site from a simple markup language, like blogofile or pelican too narrowly focussed on the use case they were born from – to generate a somewhat dynamic blog, with an optional static about page – this was not how I imagined my content to be assembled together. I wanted something richer, teasers for my blog posts on my front page, lists of all projects and songs, without the need to write my own code to do that. So – I made tomster write some code to accomplish that. However, after writing enough code to scratch his own itches, he left the code for good ;)

    scratching MY itch

    Enter nikola. After a good soul implemented custom post lists, I finally could describe what I imagined my site should look like in a markup language and not in code (although restructured text is not the simplest markup language). It would support bootstrap and bootswatch out of the box, solving all my skinning needs.

    I will not go into much details on how to get a nikola site running, there is an excellent nikola static page primer for that. From there I installed the cosmo bootswatch skin for its free and elegant font Source Sans Pro and its simple yet modern look. nikola bootswatch_theme cosmo and I'm done.

    After creating some pages and posts and giving them tags, a simple rst statement in my index.rst would be enough to list all those posts and render them via my custom template (although the default template will suffice for he sake of experiments):

    .. post-list::
      :tags: project
      :template: list_projects.tmpl
      :id: projects
      :sort: prio

    Note, that the sort parameter was only added in version 7.3.4. In the process of making the pages look good it took some tricks to use the full power of bootstrap. One is to add custom classes to whole sections inline in rst:

    .. class:: col-md-6 pull-left
    Software projects

    The other is to skin the hell out of the default bootswatch theme using my own css themes/erdgeist/assets/css/erdgeist.css and adding it to the bundles file inside the theme.

    short comings

    However, even nikola is not perfect. It uses a dependency system to figure out what to rebuild when content has changed. It will however not know in which order to render pages, so that includes like the blog post previews may be missing when the front page to show them is rendered. A work around is to set the date (in the meta fields) of any page that aggregates posts with the post-list directive to something very ancient, as the site is rendered in reverse timeline order, so the then newer posts will be there when you need them.

  • Hello world

    Colorizing countries I have visited and can remember :)

    This is just to demonstrate my new static blog and web engine nikola

    Pygal [Trip] Argentina: 1 [Urlaub] Austria: 1 [Trip] Australia: 1 [Urlaub] Belgium: 1 [Urlaub] Bolivia, Plurinational State of: 1 [Transit] Brazil: 1 [Urlaub] Canada: 1 [Trip] Switzerland: 1 [Transit] China: 1 [Trip] Cuba: 1 [Trip] Czech Republic: 1 [Urlaub] Denmark: 1 [Trip] Estonia: 1 [Urlaub] Egypt: 1 [Trip] Finland: 1 [Urlaub] France: 1 [Urlaub] United Kingdom: 1 [Urlaub] Greece: 1 [Urlaub] Croatia: 1 [Trip] Iceland: 1 [Trip] Italy: 1 [Urlaub] Japan: 1 [Urlaub] Liechtenstein: 1 [Urlaub] Lithuania: 1 [Urlaub] Latvia: 1 [Trip] Morocco: 1 [Trip] Netherlands: 1 [Trip] New Zealand: 1 [Urlaub] Oman: 1 [Urlaub] Peru: 1 [Trip] Poland: 1 [Urlaub] Portugal: 1 [Transit] Russian Federation: 1 [Trip] Rwanda: 1 [Trip] Sweden: 1 [Transit] Slovenia: 1 [Trip] Thailand: 1 [Urlaub] Tunisia: 1 [Urlaub] Turkey: 1 [Urlaub] United States: 1 TripTransitUrlaub
  • Using libressl

    I’ve been committing some code to the ressl project. I’ve found it worth to spend some time on that project that aims to make securing your communication more secure. But still people have some misconceptions about whether they can trust the new library and should make their code depend on libressl.

    I have prepared a simple FAQ for them:

    • Q: Should I base new code on the libressl API?
    • A: No.

    The reason is as simple as it gets. libressl was designed as a drop-in-replacement for openssl to protect the only asset openssl still has: an API that (even though it’s broken as hell) still is used widely. While they’re doing this, they try to do everything right that can be done right in a 201*-ish project.

    Thing is, openssl is not actually there to provide you with secure software, but to implement the “nobody ever has been fired for using openssl”-aspect of your average “crypto”-library. It’s – well it’s there and it has some FIPS certification. But let’s face it: the code is terrible, the “maintainers” haven’t done any maintenance besides reselling their FIPS-asset, the API is terrible, the cipher-defaults are terrible, the interfaces into certificate checking are next to unusable, the core functionally works hard to cloak their badness from any modern bug detection heuristics, covering most of their bugs, and openssl’s maintainers ignore bug reports, because fixing them would break their certification, hurting their business of selling FIPS-consultancy.

    Now, the OpenBSD guys were facing a tough challenge: write just another SSL library with a sane API that no one is going to use, or clean up the library that is de-facto standard and hard to rip out of each and every tool that tries to connect to the interwebs securely.

    Most users of the openssl library come there, because they stumbled across transport security as an afterthought. Maybe because it’s been another tick on their compliance chart, or because they’ve seen the passwords flowing through their wireshark window – throw some crypto on it, they thought. What they need to realize is, that they actually need three separate libraries in the first place – which openssl conveniently layer-violates into one (and even adds dangerous cruft like kerberos):

    a secure and sanely configured certificate exchange-, parser- and checker- library, a library of sane (and BY DEFAULT SECURE) crypto primitives that can apply ciphers on a data stream, a set of standard conforming heuristics that will (re-)negotiate cipher suites based on 1) and the availability of ciphers from 2) openssl fails in every single aspect of this. 99,999 percent of users nowadays do use openssl to secure their socket-based communication on servers or clients talking with each other via TCP. The whole BIO abstraction provided by openssl is wasted on them. The stack-like approach to look at “chains” of certificates falls short on modern setups with several expired and unexpired certs of the same CA in a single key store. You still can – as a MITM – trick most openssl setups into using null ciphers or weak algorithms. Checking CRLs still is a black art done right by no one. openssl still implements each and every memory allocation level bug ever displayed on “software security 101” in your favorite university.

    Now I will – judging by the current progress – give ressl a year until they matured enough to acknowledge them having picked all low hanging fruit. Then OpenBSD can proudly (and rightfully) announce that software linked agains libressl on their (and other) platforms is much more secure than before. And after looking into the source code I also understand that fixing it while also inventing a saner API exceeds the OpenBSD team’s capacities. So I urge you to consider what exactly you need secured and what tools provide you exactly what.

    If you’re up to implementing secure communication between your app and your server or between your appliances, first check if you really need all the TLS features – like the whole set of X.509 features that openssl gives you (and if so, check back which license of the available TLS implementations could possible also suite your needs) – or if you can just go with a public domain library like NaCl and put a little thought into what cryptographic primitives it gives you and where you need it.

    Until then rest assured that securing your application is not just a case of linking in another unreviewed lib.

  • Self-righteous spam police

    For over 15 years I’ve been – together with friends – running, a community mail server that provides free email accounts and mailing lists for friends, family, several NGOs and small companies – so they don’t have to turn to google mail or worse. We pride ourself in being good netizens, providing spam filtering, discarding our double bounces and so on.

    Imagine our surprise when we suddenly were served bounces like

    Remote host said: 554 5.7.1 Service unavailable; Client host [] blocked using; Blocked - see

    basically denouncing us as spammers. When investigating the issue, we were informed that

    Causes of listing: System has sent mail to SpamCop spam traps in the past week (spam traps are secret, no reports or evidence are provided by SpamCop).

    our system has sent an email to a secret mail address guaranteed to only receive spam emails. Any protest is futile, the website told us,

    Dispute Listing: If you are the administrator of this system and you are sure this listing is erroneous, you may request that we review the listing. Because everyone wants to dispute their listing, regardless of merit, we reserve the right to ignore meritless disputes.

    basically saying: All the bad guys say that they are not the bad guys, so … sure, go on, drop us an note, whining about how bad the world is and we ignore it. Because you are a spammer. And we know because we said so.

    At this point I would have just ignored them, after all the internet told me that they even put gmail on their RBL. But it turned out that several larger sites actually use the lists provided by spamcop and the amount of bounces started to hurt our community mail server.

    I dug a little deeper and found that the spamcop project actually makes money selling it’s block list to other mailers in need of immediate updateso for US$ 1000: and, worse they even sell email accounts for US$30 per year which clearly indicates a conflict of interests. “Unfortunate mis-listing” of other free mail servers now appears as defamation of potential competition. So they better have their facts straight! But – have they? How to find that out, if they never want to present their proof of me being a spammer?

    After failing to provide my email address as abuse-contact for our mail server at – due to our mail server being on the black list (oh, the irony), I focussed on writing the most brown-nosing post on their feedback system. I explained, that we kept our system tidy for over a decade and would appreciate some assistance in resolving their claim. After a while I received an email, again explaining, that

    This IP is listed because it is sending spam to our traps. Traps are addresses on our systems that have never existed and could never subscribe to be on any mailing list. Any mail to them is spam. We will not provide any information that identifies our traps or their locations.

    but also providing a sample of the spam they received. And indeed

        Received: from ([])
                by <removed>; Tue, 21 Jan 2014 17:xx:xx -0800
        Date: Wed, 22 Jan 2014 08:xx:xx +0700
        Message-ID: <>
        From: Online Casino <>
        To: <x>
        Subject: Ihr Ziel: Profit

    this very much looks like spam, originating from our mail server. I also found some traces of that email in my rather sparse mail server logs and was flabbergasted for a moment, how this could have been relayed through the server without anyone authenticating. Fortunately I found a corresponding incoming spam mail to one of our users accounts, I found a mail forward set for this user to the address that obviously now serves as one of spamcops spam traps and from then on it all became clear. That user has set up a dedicated vacation account and forwarded all emails from that account to a satellite mail provider. The user also wrote several blog posts, pointing potential co-travelers to this address. The provider shut down the account a while ago and now decided that since nearly every email to this account looks spam-ish, it would make a perfect spam trap.

    Now, even our overeager friends at spamcop have noticed that re-using a once legitimate address is a stupid idea, from

    Traps must consist of email addresses which have never been used for legitimate email. They should not be "recycled" user accounts.

    However, they never seem to verify, if their contributors actually follow those guidelines. In our case, a simple google search would have warned them.

    I just wrapped up all this in an email to the hard-working “deputies” they employ over there at spamcop HQ and hope for a quick de-listing, and maybe – just maybe – for an apology.

    In the end all left to conclude is: Do no put the burden of fighting spam on others. My users actually experienced bounced emails, I experienced two days of debugging and fixing other peoples amateurish setup, our project’s reputation was damaged. Spamcop, your secret spam traps are a stupid idea and they hurt the community, in our case possibly driving users away from a privacy-aware project to other freemailer providers that are large enough to have resources to deal with problems like you.

  • Repositioning

    As a developer nowadays using a source code management system is non-optional. I’ve been a happy user of cvs for quite a while now, as it is complex enough for all my use cases and simple enough to allow fixing things with a text editor without breaking other people’s checkouts. I’ve had little reason to change this, as cvs was available everywhere and with ezjail – one of my more important projects – it was even essential providing means to checkout its latest development state on a vanilla FreeBSD installation, where cvs was the only scm system provided.

    However, time moves on. The FreeBSD project chose to remove cvs from base system in its next major release 1 and OSX Developer Tools ship without cvs from OSX 10.8 onward. So it was time for me to move on, as well. The choice to migrate FreeBSD development to subversion 2 seemed not such a bad idea back in 2008, but for me svn has always been a world of pain. It adds complexity without providing any benefit and removed the option for simple repository manipulation when things went awry. In 2013 the only sane option – despite a creeping headache considering the license – is git. Its increased complexity pays off by having integrity checks, a well established user base, an almost fanatical devotion to the pope and in the end I can use it as I used cvs.

    I set up gitolite 3 with a UMASK of 0022 4 (to save me trouble later with tools like cgit and gitdaemon) and created empty repositories for each project to migrate. After playing around with several tools, I found cvs2git 5 the best option, allowing me to import the cvs repositories onsite with this tiny script:

    git clone${project}
    mkdir -p dumps/
    cvs2git --blobfile=dumps/${project}-git-blob.dat --dumpfile=dumps/${project}-git-dump.dat --username=cvs2git --fallback-encoding=utf8 ${CVSROOT}/${project}
    # Use a text editor the fix committer’s emails, etc here in the dumps/${project}-git-dump.dat file
    cd ${project}
    cat ../dumps/${project}-git-blob.dat ../dumps/${project}-git-dump.dat | git fast-import
    git checkout master
    git gc --prune=now
    git push origin master
    cd ..

    This scripts needs to be run as a user who can read CVSROOT and has commit rights to the gitolite repositories.

    Being the polite hacker that I am, I wanted to avoid breaking other people's checkouts with my migration. I also need to provide backward compatibility to users of FreeBSD installations that still come with cvs only. This means that the pserver URIs need to remain intact. However, the tool I hoped would solve this problem – git-cvsserver 6 – comes with some surprising mapping of cvs modules into git branches. Which basically renders it unusable as a legacy support mechanism. This left me with little choice but keeping the old cvs repositories as write-only copies. I wrote a git commit hook that commits every change 7 to cvs using a dummy checkout in /home/cvs/${project}, after granting the git user commit rights to cvs. This works well, the only drawback is that it makes all commits appear to come from git in the cvs view. But I think this is an acceptable price.

    In order to provide an additional update commit hook and not break gitolite’s builtin hook, I needed to add a so-called VREF 8 to the repo config, which looks like this in my conf/gitolite.conf:

    repo ezjail opentracker minimunin jaildaemon
        RW+              = id_dsa
        R                = @all
        -   VREF/cvspush = @all

    My git repos reside in /usr/local/git/, so I put my commit hook script to /usr/local/git/.gitolite/local/VREF/cvspush and fixed my /usr/local/git/.gitolite.rc to have an entry:

    LOCAL_CODE => "$ENV{HOME}/.gitolite/local",

    The hook itself is here (don’t forget to set +x permissions. Also if you checkout your cvs repositories somewhere other than /home/cvs, you need to change this, as well):

    # ignore changes not for master branch
    [ "$1" = "refs/heads/master" ][] || exit 0
    # see if we have a legacy CVS repository to commit to
    [ -d "/home/cvs/${GL_REPO}/CVS/" ][] || exit 0
    export GIT_DIR="${GL_REPO_BASE}/${GL_REPO}.git"
    cd "/home/cvs/${GL_REPO}/" || exit 0
    # get all the commits leading up to that push
    for commit in `git rev-list "$2".."$3"`; do
      git cvsexportcommit -k -u -c -v ${commit}

    And finally all my project description pages were updated to reflect the new way to checkout the source code, as was the web interface 9. All thats left now is to provide read only svn access to the projects, for all FreeBSD users running 10.

  • ezjail 3.4 is out

    Due to changes in how the FreeBSD port system handles the install target, certain ports fail to install with the error "pkg_create: make_dist: tar command failed with code 256" in Jails installed with the current version of ezjail. ezjail from version 3.4 fixes this. Until then you should execute the command mkdir -p /var/ports/packages as a workaround in all jails you want to install ports in.


See the lecture about opentracker on 24C3 (slides), Wahlcomputer in Erlangen, Format String Exploits, see the interviews and TV show contributions (todo).

Skypixels are helium balloons lit by independent LED boards remote controlled by a NFR2401 controller.

GodMachine was an installation in the Dresden Museum of hygiene, allowing visitors to control the weather by gestures.

Laserharfe is a music instrument built together with friends. It converts hands moving in laser beams to MIDI signals and works on off the shelf electronics.

Some rather personal content, songs I wrote or recorded, some in my former band, Pumpanickle. Poetry I wrote. Recently into selecting or writing intros for podcasts alternativlos, turing galaxis, Frühstücksblog podcast, Neusprech, Fnord News Show and OHM podcast.