For the last 8 years, this blog has been my primary outlet whenever I had the urge to share some written worlds with the world. This resulted in a hodgepodge of 44 articles covering a wide range of topics: technical articles related to my work as a consultant and software developer, as well as personal stuff like my nerdy side projects and my passion for everything fast.

I’ve decided to give my technical writing a new home:

You might wonder, why even bother? Truth be told, nobody ever complained that my blog isn’t focused enough. Probably because they forgot what the last post was about, because on average more than two months did pass between posts.

The key to building an audience is to write consistently about a well defined topic. That’s what I am planning to do on

So if you are interested in Django, Python and software development in general, go check it out and subscribe to the mailing list to get notified of new articles and stuff I work on.

But beware! At some point, I will launch some kind of product and there is a high probability that you will buy it because it will solve a painful problem for you and I have demonstrated my expertise with my technical writing. Sounds like a plan, right?

Frankly, I have no idea yet what this product might look like. For now I focus on writing something helpful on a regular basis.

I will document my journey to product income on this blog, so if you want to see how my grand masterplan works out, just keep this tab open. A slightly more convenient way to stay updated would be to follow me on Twitter.

Why you need a security@ address

If you run any kind of webservice, you should set up a email address, display it prominently on your website and make sure it gets read by an employee with a technical background.

Not convinced? As a case study, check out this post on HackerNews. The OP said he had tried to report a security vulnerability at a messaging and voice services provided, but nobody would listen to him.

The suggestions ranged from full-disclosure to emailing the CTO. I pinged the official Twitter account of the company with a link to the thread, but they brushed it off. Ironically, the company even advertises their service as a security solution on their Facebook page.

After about two hours, a member of the ops team finally chimed in on HackerNews and the issue got addressed. A little later, they also got back to me via Twitter. But the damage was done: people started telling stories of unrelated bad customer service experiences and one person said they are going to evaluate a competitor.

With a security contact prominently visible on the website, the whole thing could have been avoided.

.local domains and Mac OS X 10.10 Yosemite

TL;DR: sudo discoveryutil mdnsactivedirectory yes

After upgrading to Mac OS X 10.10 Yosemite, I found myself unable to access any hosts with a domain name ending in .local

I could resolve the hostname with DNS tools like dig and nslookup, but other tools, namely ssh and ping, refused to do so.

As it turns out, Yosemite (and apparently also iOS 8) changed the way of resolving host names ending in .local to conform to the relatively new RFC 6762.

After much digging I found a fix in the Apple support forums:

sudo discoveryutil mdnsactivedirectory yes

Note that this fix only lasts until the next reboot.

Fixing 1_6.W001 when upgrading from Django 1.5 to 1.7

After upgrading a Django project from Django 1.5 to the current beta of Django 1.7, running the tests triggered a warning:

System check identified some issues:


?: (1_6.W001) Some project unittests may not execute as expected.
	HINT: Django 1.6 introduced a new default test runner. It looks like this project was generated using Django 1.5 or earlier. You should ensure your tests are all running & behaving as expected. See for more information.

This warning is printed by the System Check Framework, which is new in Django 1.7 and checks your project for common problems. You can run it manually with the “check” management command.

python check

After verifying that all my tests are run, I was left wondering how I can silence the warning after reading (okay, let’s be honest: skimming) the release notes of 1.6. The answer is simple, but I had to look in the source of the system check framework to find it. Apparently you have to explicitly define a test runner starting from Django 1.6. To do so, add the following line to your settings:

TEST_RUNNER = 'django.test.runner.DiscoverRunner'

Maxing out a HP4

For my birthday, I treated myself to something special: I rented a BMW HP4 for a day.

Foto 3With 196 HP from 1000 cc, 199 kg and every electronic gizmo you can imagine, the HP4 stands at the pinnacle of German motorcycle engineering. Now, you might wonder who is crazy enough to rent such a monster. As it turns out, Sixt is! Initially, I wanted to rent a S1000RR, which is basically the same minus the magic electronic suspension of the HP4. But when the rental agent offered me an upgrade for just 20 Euros, I couldn’t resist. Read on to find out what that day brought.  Continue reading

Nürburgring Nordschleife: GT5 vs. IRL

For a long time, I wanted to drive the famous Nordschleife of the Nürburgring. Having seen enough crash videos on YouTube, I realized that some preparation would probably be a good idea. I decided that doing some laps on Gran Tourismo should do the trick.

So I went out to acquire a PlayStation 3, a Logitech steering wheel and a copy of Gran Tourismo 5. To my horror, the Nordschleife was not available out of the box! Had I just spend 400 € for nothing? As it turns out, you have to complete the AMG driving school special event to unlock the Nordschleife. It’s a good way to get to know the track, although you will probably not do your first laps in a historic Mercedes 300 SL.

This brings me to one of the most important aspects of your Nordschleife experience: the car. My problem: I don’t have one. One could probably drive in a regular rental car, but you will probably have issues with the insurance in case of a crash on the Ring.
There are several rental companies around the Nürburging that offer cars specifically for driving on the Nordschleife, most notably RentRaceCar and Rent4Ring. The cars are usually equipped with better brakes, suspension, tires and a roll cage and, most importantly, are properly insured for the Ring. That said, all cars that you can rent still have quite a hefty deductible. Before you sign the contract, make sure that a crash would not be a total financial disaster.

I had set my sight on a Suzuki Swift from RentRaceCar. 130 hp and 1000 kg curb weight promised a lot of fun at a reasonable price. I deliberately chose a low-powered, front-wheel-drive car for my first laps on the ring.

As a consequence, I used the Swift for almost all of my virtual driving. It might be tempting to do a hot lap in the Zonda R, but I wanted to keep it as real as possible.

My plan was to go the Ring once I could complete 10 consecutive laps under 10 minutes without crashing. My best time for a full lap on the PS3 with the Swift was 9:25, but I never managed more than three laps without impact. As the months went by and the days became shorter, I decided that I had enough training and scrapped the plan of 10 under 10.

October 20, 2011 was the big day. (Yes, 2011, this post spent a lot of time in the drafts folder). It was a Thursday. The car was reserved, the weather forecast was looking good and I was eager as rarely before. A good friend of mine agreed to drive me to the Ring and act as codriver. It probably helped that I forgot to mention my failed plan of 10 under 10.

As we got closer to Nürburg, the road got more and more wet. However, there was no way back and we soon arrived at Rent Race Car. After handling the formalities, the friendly staff gave me a quick introduction to the car and valuable tips for my first laps. The customer service leaves nothing to be desired, but note that the cars only have a roll bar (not a roll cage) and the deductible is a whopping 2500 €. Rent4Ring offers a Swift with a full roll cage for a slightly higher price.

We arrived at the entrance of the Nordschleife about 20 minutes before the track opened, enough time for a coffee to increase the nervousness and a quick stroll over the parking lot where a couple of fellow track enthusiasts had gathered. It was a calm day with maybe thirty cars in total, including a couple of nice Porsches and Lotuses.

Then it was time. The track opens. You roll up to the toll gate. You drive through the corridor of pylons. Accelerate. Past the bridge. This is where the time starts. On the slight downhill to Hohenrain, you quickly built up speed. On the first turn, it becomes immediately clear that this is the real thing and no amount of time sitting on your couch twisting your fancy force-feedback wheel prepare you for it. With a wet track, there was quite a bit of understeer on the last turn before the start line. That’s scary and reassuring at the same time. It’s scary, because it shows how little grip there was on the damp track. It’s reassuring because you could actually do something about it. The little Swift is forgiving and leaves a lot of room for errors. After the twists at Hatzenbach and Hoheneichen, we approached the first fast section, from Quiddelbacher Höhe to Flugplatz. In the game, you go can go flat out all the way to Schwedenkreuz, which just seemed ridiculous while we were flying down the narrow track at 180 km/h (~110 mph). After passing the turn at Aremberg, the biggest shortcoming of virtual driving became obvious: the elevation. You can feel the pressure in your ears increase as you fall down Fuchsröhre. At increasing speed, you approach the bend in the dip, which seemed much more threatening than in the game, even at 3/4 of the speed. The tight turns at Adenauer Forst seem easy, but that is mostly caused by your incredibly slow speed. You line still sucks. Accelerating towards Metzgesfeld. In the game, you maybe lift, but on the track you definitely brake. Taking it easy through Kallenhard and Wehrseifen, where you always crash in the game. The scars in the wall at Breidscheid remind you that there is no reset button this time. Staying wide at the tricky, tightening turn at Bergwerk. Trying to find some dry spots racing through Kesselchen. Again, slight bends turn out to be proper turns that warrant braking. The fact that the car is much faster than in the game doesn’t help. After another tricky turn at Klostertal, you get the best, but also shortest carousel ride of your life. Considering how the whole car shakes, it seems a miracle that you leave Karussell in one piece. But there is no time to breathe, as you race up to Hohe Acht. You are thrown from side to side, the little Swift diving deep into the suspension at Eschbach. Your stomach complains that nobody told him that he’s going on a rollercoaster ride while you pass Brünnchen. Approaching Pfalzgarten I, where spectators are almost guaranteed spectacular crashes on busy days. Down a massive descent towards Pfalzgarten II, ABS stepping in as you cowardly brake over the small jump. Suddenly a blind turn, where you were expecting a mostly straight line towards Schwalbenschwanz. As you rattle over the second, small carousel, you lose ESP. Only a few past turns on Galgenkopf left, then you approach the gantry, the unofficial finish line for the tourist drive. This was your first lap of the Nürburgring. The probably most intense 20 kilometers of your life lie behind you. Your knees tremble a bit, but a big smile is stuck on your face.

Cut to the chase, what was the time? Unfortunately, only the second and the third of the four laps that I did that day were recorded. My second lap was 11:30 from bridge to gantry, and my guess for the first lap is somewhere north of 12 minutes. Way slower than my time on the PS3, way slower than anything I had seen on YouTube, way slower than Jeremy Clarkson in a diesel or a girl in a van.

Does it matter? Not really. Driving on the Nordschleife was one of the best experiences of my life, period.

Were those hours playing Gran Tourismo 5 well spent? You bet! Although playing the game doesn’t even come close to reality, it helped tremendously to know the track layout and to have a rough idea of how fast a turn can be taken. But there are many subtle differences, so take it easy on your first laps and don’t expect to beat your virtual times.

Have fun and stay safe!

Firmware update gone horribly wrong

A couple of days ago, my 15″ Macbook Pro from early 2011 started to misbehave. It didn’t wake up from sleep and froze regularily.

Macbook SurgeryAfter a lot of headscratching, grepping of logs, cursing of TimeMachine and googling, I finally identified my 256 GB Crucial M4 SSD, firmware rev. 009, as the likely culprit. A new firmware version 070H claimed fix a bug that was triggered after 5184 hours of uptime. Sure enough, the uptime reported by SMART on my 15 month old disk was way above this threshold (note to self: spend less time in front of computer).

So I decided to update the firmware. This is where the fun part begins. Updating the firmware is usually not a big deal: burn an image to a CD or write it to an USB stick and reboot the machine, confirm some scary warnings and presto, you are done. But not so quick. Continue reading

10 days and counting – preparing for Ironman Frankfurt 2012

A long time ago, a good friend and I agreed to do an Ironman Triathlon when we turn 30 years old. I can’t pinpoint that agreement to an exact date, all I know is that at the time, the magical number 30 lay in a distant future. Somewhen at the end of 2010, we began to talk about it again and we agreed to take on the challenge and to sign up for the Ironman European Championship 2012 in Frankfurt. It was set to take place on July 8th, 4 days before my 30th birthday. Now, for those not familiar with the term, an Ironman Triathlon is a long distance triathlon consisting of a 3.8 km swim, 180 km bike and 42.2 km run.

By my standards, I was in pretty bad shape at the time. My last race was the Cologne Marathon in 2009, which I finished in 03:58:04. My best result was a 03:22:53 in Mannheim in 2008, so that time was quite disappointing to me. In 2010, I had not trained a lot, so there was clearly a lot of work to be done before I could even consider doing an Ironman. Oh, and did I mention that I had never competed in a triathlon before?

So I thought it would be a good idea to do one or two triathlons in 2011 to get some experience. On June 5th, 2011, I completed my first ever triathlon in Mussbach, my home town. It took me 03:04:00h, my split times for 1.5 km in the pool, 40 km on the bike and 10 km running were 00:31:09h, 01:36:52h, and 00:55:59h respectively. My swimming time was better than expected and the time on the bike was okay, as the course was pretty tough. I had expected a much better result for the run, but I had totally underestimated the switch from cycling to running. The extreme temperatures of the day didn’t help either. All in all, the result was okay given my preparation, but it left a lot of room for improvement.

On June 23th, I signed up for the Ironman 2012. Now there was no way back. I also signed up for the Cologne226half, a triathlon over the middle distance in September, and the Cologne marathon in October.

In the first week of July, I spent a week with my girlfriend in Italy. With my batteries recharged, I started 8 weeks of intense training for the triathlon. To get an idea where I was starting from, I did a 10 km run on July 15th, which I finished in 00:44:16.

In the eight weeks before the triathlon, I averaged about 6 workouts per week. I tracked about 1100 km on the bike and 20 hours of running time using my Ciclosport HAC4. I probably should have done more, but it was already hard to find the time. Unfortunately, I haven’t tracked my swimming at all, all I can say is that I definitely had deficits. I could blame it on my local pool being closed for two weeks, but the main reason is that I just don’t like it. It is so incredibly boring! I had worked on my technique a bit using the book Total Immersion, but I just didn’t spend enough time in the pool. To make matters worse, the triathlon took place in a lake and I had an irrational fear of swimming in open water. On the weekend before the race, I bought a neoprene suit and one evening after work, I drove to a nearby lake to do a test swim in the dusk. I had planned to swim 1000 m, but I just couldn’t cover any distance, because I would panic once I could not see the ground any more. I settled for floating around a bit and getting a feel for the suit. It really makes a huge difference. If you plan on competing in a race with a neoprene suit, you absolutely must swim with it before.

September 1st 2011 was the big day. My father and my sister accompanied me to the start, were we met with a former colleague of him. In 2004, we had done the Quelle Challenge Roth together as a relay. My father borrowed me a set of nice Dura-Ace wheels, which were probably worth more than my whole bike.

Changing onto the bike at the Cologne226halt triathlon

After my so-so triathlon debut, I didn’t expect much. I was pretty confident that I would stay below 6 hours and hoped for something below 5:30. 45 minutes for 1.9 km swimming, 3.5 hours for 90 km cycling and 1:45 hour for the half marathon seemed realistic. I was pleasantly surprised when I left the water after 35:02 min! On the bike, I felt like I was flying. Before the race, I had hoped to average 30 km/h, and now I was constantly pushing 40+ km/h without much effort. The wind was favorable and the wheels seemed to make a big difference. I tried not to get carried away, because I didn’t want to exhaust myself on the bike and suffer through running later. Unfortunately, my pulse watch had died in the water, so I had no reference on how hard I was pushing. I went off the bike after 02:33:53 h, averaging 35 km/h, way better than expected. Running went okay as well with a 01:47:17 h. My endtime was 05:05:06 h, putting me in the upper third of all finishers. As you can imagine, I was really happy with the result.

After the triathlon, it took me quite a while to recover and I couldn’t train as hard for the Cologne marathon as I had planned. However, I wanted to finally beat the barrier of 3:15 hours and planned my race pace accordingly. But, as they say, no plan survives the first contact with the enemy. After the first 1000 m I was already behind my target time. That had never happened before in any race. The smart decision would have been to take it a bit easier and maybe finish in 3:30 h. Instead I tried to make up the lost time, with the result that I was totally exhausted after one third of the distance. Worse than the physical exhaustion was the mental one. For the first time, I seriously contemplated giving up a marathon. Luckily, I stuck with it and finished in 3:57:59 hours. A whole 5 seconds faster than my result in 2009, but a far cry from my target time. In retrospect, I should have known before that 3:15 hours was just not realistic.

Recovery from the mental exhaustion after the marathon took even longer than the recovery from the physical exhaustion after the triathlon. I pushed myself a lot in preparation for the triathlon and the marathon was just too much. For the rest of 2011, I exercised once, maybe twice, a week. As christmas was approaching, I decided it was time to reboot my training regimen. Within two weeks after christmas, I had probably exercised more than in the two months before. The Ironman was due in six months, so it was about time.

During January and February, I focused on swimming. I tried to go to the swimming pool three times per week. During January, the weather was way too bad to go road cycling, so I went mountain biking every weekend. Unfortunately, I was fighting a sinusitis in February, which cost me about two weeks. As soon as I felt well and the weather became bearable, I hit the road. I also finally took the time to calibrate my Polar RS 800 CX and it turned out that I wasn’t as slow as I thought.

On March 13th, I ran my first race in 2011. I competed in a half-marathon which conveniently took place about 500m from my home. I finished in 1:35:20 hour and I’m quite happy with that. I ran the first 10 km in 43:52 min, which was faster than the 10 km run I did in July 2011.

My running and swimming were on track but I still had some deficits in the bike department. At the end of March, I spent 8 days cycling in Mallorca with a group of 17 people from Karlsruhe. During these 8 days, we covered a distance of 1000 km and 10000 m in altitude. Unfortunately, we also had two accidents, the first one being pretty scary. One guy went off the road on a descent and crashed head first into a wall peppered with sharp-edged stones. Despite wearing a helmet, he suffered some deep cuts on the forehead and had to go to the hospital. It looked pretty bad, but luckily he was okay and back on the bike after two days. The second accident was less spectacular, but it involved almost half of the group, me included. We were just 10 km into the tour of the day when a wet spot in a 90° turn caught us by surprise. One set of wheels was destroyed, but nobody suffered major injuries. A few guys returned to the hotel, but most of us could continue after a short stop at the pharmacy. On the last day, five of us decided to break the 200 km mark. It was the first time ever I cycled longer than the 180 km I will have to do during the Ironman. I had a great time in Mallorca and my endurance made a huge leap forward.

Two weeks after returning from Mallorca, I competed in the Bonn marathon. The results from my last two marathons where I finished just below 4 hours weren’t very encouraging and this race should serve as a reference for my further training. I crossed the finish line after 3:30:15 h. Not as fast as my personal record, but almost half an hour faster than my last marathon.

On the last weekend of May, I participated in the Tour Eucor, an event organized by the universities of Karlsruhe, Straßburg, Mulhouse, Basel and Freiburg. Starting from Karlsruhe, we made a trip through all these cities in five days. These five days added up to almost 800 km, with 200 km on the final stage from Freiburg to back to Karlsruhe.

One week after the Tour Eucor, that last test before the Ironman was due. For the second time, I participated in the Mussbach triathlon over the olympic distance. My father was kind enough to entrust me with his carbon fibre bike which weights about half of mine. With a whole year of training and the upgraded equipment, I was confident that I could beat my time from last year. The race day didn’t start well. Just as we arrived at the swimming pool, it started pouring rain. That wouldn’t make a big difference for swimming or running, but with the steep descent from the Kalmit hill, the cycling part suddenly became much more exciting. The rain itself had stopped mostly once I came out of the water after 30:06 min, but the road was still wet. I decided to put on a rain jacket despite the unfavorable aerodynamics. The bike stage took me 1:27:38 h including the time for both changes. My average speed was 30 km/h, a massive improvement over the last year. The upside of the rain was that the temperature dropped to a very comfortable level for running. I ran the 10 km in 43:37 min, which adds up to a total of 02:41:21 h. Compared to 2011, I was more than 20 minutes faster and not all of it was due to better bike.

I could say with confidence that I was in the best shape ever, but I still had a lot of respect for the sheer distance of the bike stage. I had already covered the distance twice in a group, but never on my own. So one Sunday, I set out to change this. The route I had chosen more or less matched the profile of the course in Frankfurt, so the times should be comparable. I had to take an unintentional break of about 25 minutes due to a puncture and my inept handling of it (don’t ask), but it still went better than expected. All in all, I was rolling for 6:10h, which is an average speed of about 29 km/h. One more checkbox to check on the long, long list of preparations for the Ironman.

Another checkbox was swimming in open water with the neoprene suit. The suit hadn’t seen open water since Septembre 2011 and neither had I. I had planned to swim an hour or so in a local lake to get used to the open water again and to get a feel for the suit. Unfortunately, it never came that far. Once I stepped into the water and could not see the ground anymore, an irrational fear kicked in. To make matters worse, there were fishes in the water. They were just basses, but to me they looked like giant swimmer-devouring sea monsters. Long story short, I didn’t swim an hour or so.

Last Sunday, I met with my father in Frankfurt to cycle one lap on the bike course. Again, my father lend me one of his bikes, this time a 2010 Cannondale Slice. It’s not as light as the bike I had at the triathlon in Mussbach, but damn, it is quick. Although it was very windy that day and I didn’t push myself, I easily averaged 30 km/h. I reckon that the bike is at least 10% faster than my bike, the difference is really astonishing.

The big day is coming. I’ve been preparing for about a year now. During the last six months, I’ve cycled 3500 km and ran 700 km.  Now there is just one more weekend of intense training left before I slow down to recharge my batteries. As of this writing, there are ten days left until my longest day of the year.  See you in Frankfurt.

Restricting Solr with Jetty to localhost

If you want to try Apache Solr, the easiest way to get started is to use the example the comes with the download. Just run java -jar start.jar and you can start searching like a pro.

However, the integrated Jetty server is configured to bind to port 8983 on all IP adresses by default. This configuration is unsafe: anyone could clear your whole Solr index!

It is a good idea to let the server listen only on localhost, unless your server is in a private network. A quick solution is to set the system properties and jetty.port on startup, e.g. like that:

java -Djetty.port=1337 -jar start.jar

Alternatively, you can edit the configuration at example/etc/jetty.xml. Look for these lines:

<Set name="host"><SystemProperty name="" /></Set>¬
<Set name="port"><SystemProperty name="jetty.port" default="8983"/></Set>