Piwik, nginx and self-signed certificates

To keep track of some website statistics I use Piwik, an excellent free web analytics tool that provides you with detailed reports on your website’s visitors, your marketing campaigns and much more.

Obviously I want to make sure that information is secure and shielded from unauthorized access. After too many Certificate Authorities recently dropped the ball (TurkTrust and Diginotar but Google for more) it makes more sense to use self-signed certificates and client certificate authentication.

Unfortunately Piwik does not support client certificate authentication in its tracker code so how can self-signed certificates and client certificate authentication still be used?

They can not… sorta.

Nginx to the rescue. The fast growing webserver ( actually an HTTP and reverse proxy server, as well as a mail proxy server) is tremendously flexible and granular and allows you to provide limited non-SSL access to piwik.js and piwik.php while the actual webinterface behind index.php is only available on an SSL link with client certificate authentication. While I would prefer to see support for SSL with self-signed certificates & client certificate authentication in Piwik’s tracker code, this should do for now.

Example configuration:

I’ll leave the SSL enabled full Piwik configuration as an exercise to the reader. Piwik on nginx is well documented as is the SSL part.

If you know a way to make Piwik’s tracker code work with SSL with self-signed certificates & client certificate authentication then please leave a comment.

Fail2ban ERROR Invariant check failed

I bumped into the following cryptic Fail2ban error:

fail2ban.actions.action: ERROR iptables -n -L INPUT | grep -q ‘fail2ban-NoScript[ \t]’ returned 100
fail2ban.actions.action: ERROR Invariant check failed. Trying to restore a sane environment

Cause: a race condition in fail2ban-client.
Solution: add a small amount of sleep.

Open /usr/bin/fail2ban-client and around line 144 add the line “time.sleep(0.1)” right before “beautifier.setInputCmd(c)”. Make sure you use tabs and not spaces! Here is what it should look like:

Enjoy all those bans automagically handed out to the bad guys.