A really simple way to archive your Tweets

  1. You have a gmail account don’t you? Visit Google Reader now.
  2. Click on the “Add a Subscription” button.
  3. Type in the web address of your Twitter profile. Mine is http://twitter.com/donncha.
  4. Click Add.
  5. There is no #5.
Since Google Reader doesn’t have the 3,200 post limit that Twitter has you can always get access to your old tweets, even when you go over that limit. On the downside, your Twitter account can’t be private and Google will find out yet more about you (but they probably already indexed your Twitter account anyway so no loss there!)

Speed up WordPress with Apache and Varnish

Varnish is an open source, state of the art web application accelerator.

What it does is make your existing site faster by caching requests so your web server doesn’t have to handle them. This helps because your web server may be a lumbering giant like Apache that is loaded up with extra functionality like PHP, the GD library, mod_rewrite and all the other tools you need to make your website. All these modules unfortunately make your general purpose web server slower and heavier so by avoiding it your site spits out pages much faster!

Varnish sits in front of your webserver. Most documentation I’ve read on the subject suggest having Apache listen on any port other than port 80 and then have Varnish listen on port 80 of the external IP address. There’s no need to do this as I configured Apache to listen on port 80 of the 127.0.0.1 or localhost address while Varnish sits on the external IP.

Installing Varnish

Setting up Varnish is fairly easy. I’m going to assume that you’re already using Apache and On a Debian based system just use this to install it (as root)

apt-get install varnish

Apache

You need to configure Apache first. It has to listen on port 80 of the localhost interface. Edit /etc/apache2/ports.conf and change the following settings:

NameVirtualHost 127.0.0.1:80
Listen 127.0.0.1:80

Normally Apache listens on port 80 of all interfaces so you’ll probably just have to add “127.0.0.1:” in front of the 80.

Varnish

By default Varnish won’t start. You need to edit /etc/default/varnish. Change the following options in that file:

START=yes

DAEMON_OPTS="-a EXTERNAL_IP_ADDRESS:80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"

Replace EXTERNAL_IP_ADDRESS with the IP of your external IP address.

Now edit /etc/varnish/default.vcl. The file should already exist but most of it is commented out. First of all change the “Backend default”:

backend default {
    .host = "127.0.0.1";
    .port = "80";
}

This tells Varnish that Apache is listening on port 80 of the localhost interface.

I’m going to define several functions in the default.vcl now. Comments in the code should explain what most of it does.

# Called after a document has been successfully retrieved from the backend.
sub vcl_fetch {
    # Uncomment to make the default cache "time to live" is 5 minutes, handy 
    # but it may cache stale pages unless purged. (TODO)
    # By default Varnish will use the headers sent to it by Apache (the backend server)
    # to figure out the correct TTL. 
    # WP Super Cache sends a TTL of 3 seconds, set in wp-content/cache/.htaccess

    # set beresp.ttl   = 300s;

    # Strip cookies for static files and set a long cache expiry time.
    if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$") {
            unset beresp.http.set-cookie;
            set beresp.ttl   = 24h;
    }

    # If WordPress cookies found then page is not cacheable
    if (req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)") {
        set beresp.cacheable = false;
    } else {
        set beresp.cacheable = true;
    }

    # Varnish determined the object was not cacheable
    if (!beresp.cacheable) {
        set beresp.http.X-Cacheable = "NO:Not Cacheable";
    } else if ( req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)" ) {
        # You don't wish to cache content for logged in users
        set beresp.http.X-Cacheable = "NO:Got Session";
        return(pass);
    }  else if ( beresp.http.Cache-Control ~ "private") {
        # You are respecting the Cache-Control=private header from the backend
        set beresp.http.X-Cacheable = "NO:Cache-Control=private";
        return(pass);
    } else if ( beresp.ttl < 1s ) {
        # You are extending the lifetime of the object artificially
        set beresp.ttl   = 300s;
        set beresp.grace = 300s;
        set beresp.http.X-Cacheable = "YES:Forced";
    } else {
        # Varnish determined the object was cacheable
        set beresp.http.X-Cacheable = "YES";
    }
    if (beresp.status == 404 || beresp.status >= 500) {
        set beresp.ttl = 0s;
    }

    # Deliver the content
    return(deliver);
}

sub vcl_hash {
    # Each cached page has to be identified by a key that unlocks it.
    # Add the browser cookie only if a WordPress cookie found.
    if ( req.http.Cookie ~"(wp-postpass|wordpress_logged_in|comment_author_)" ) {
        set req.hash += req.http.Cookie;
    }
}

# Deliver
sub vcl_deliver {
    # Uncomment these lines to remove these headers once you've finished setting up Varnish.
    #remove resp.http.X-Varnish;
    #remove resp.http.Via;
    #remove resp.http.Age;
    #remove resp.http.X-Powered-By;
}

# vcl_recv is called whenever a request is received
sub vcl_recv {
    # remove ?ver=xxxxx strings from urls so css and js files are cached.
    # Watch out when upgrading WordPress, need to restart Varnish or flush cache.
    set req.url = regsub(req.url, "\?ver=.*$", "");

    # Remove "replytocom" from requests to make caching better.
    set req.url = regsub(req.url, "\?replytocom=.*$", "");

    remove req.http.X-Forwarded-For;
    set    req.http.X-Forwarded-For = client.ip;

    # Exclude this site because it breaks if cached
    #if ( req.http.host == "example.com" ) {
    #    return( pass );
    #}

    # Serve objects up to 2 minutes past their expiry if the backend is slow to respond.
    set req.grace = 120s;
    # Strip cookies for static files:
    if (req.url ~ "\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$") {
        unset req.http.Cookie;
        return(lookup);
    }
    # Remove has_js and Google Analytics __* cookies.
    set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");
    # Remove a ";" prefix, if present.
    set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
    # Remove empty cookies.
    if (req.http.Cookie ~ "^\s*$") {
        unset req.http.Cookie;
    }
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
                error 405 "Not allowed.";
        }
        purge("req.url ~ " req.url " && req.http.host == " req.http.host);
        error 200 "Purged.";
    }

    # Pass anything other than GET and HEAD directly.
    if (req.request != "GET" && req.request != "HEAD") {
        return( pass );
    }      /* We only deal with GET and HEAD by default */

    # remove cookies for comments cookie to make caching better.
    set req.http.cookie = regsub(req.http.cookie, "1231111111111111122222222333333=[^;]+(; )?", "");

    # never cache the admin pages, or the server-status page
    if (req.request == "GET" && (req.url ~ "(wp-admin|bb-admin|server-status)")) {
        return(pipe);
    }
    # don't cache authenticated sessions
    if (req.http.Cookie && req.http.Cookie ~ "(wordpress_|PHPSESSID)") {
        return(pass);
    }
    # don't cache ajax requests
    if(req.http.X-Requested-With == "XMLHttpRequest" || req.url ~ "nocache" || req.url ~ "(control.php|wp-comments-post.php|wp-login.php|bb-login.php|bb-reset-password.php|register.php)") {
        return (pass);
    }
    return( lookup );
}

Notes:

  1. Varnish caches Javascript and CSS files without the cache buster ?ver=xxxx parameter. Varnish doesn’t cache any url with a GET parameter so those files weren’t getting cached at all.
  2. The code removes the Cookies for Comments cookie after it checks for GET and HEAD requests. This improved caching significantly as web pages are not cached with and without that cookie. They are all cached without it. The cache hit/miss ratio went up significantly when I made these two changes.
  3. I have a private site on this server that requires login. I had to stop Varnish caching this site as the privacy plugin thought I wasn’t logged in. See the example.com code above.
  4. If pages were purged Varnish could store cached pages for much longer.

As I didn’t modify WordPress so it would issue PURGE commands there are probably issues with the cache keeping slightly stale pages cached but I haven’t seen it happen or receive complaints about that.

PHP

Since all requests to Apache come from the local server PHP will think that the remote host is the local server. By using an auto_prepend_file set in your php.ini or .htaccess file you can tell PHP what the real IP is with this code:

if ( isset( $_SERVER[ "HTTP_X_FORWARDED_FOR" ] ) ) {
        $_SERVER[ 'REMOTE_ADDR' ] = $_SERVER[ "HTTP_X_FORWARDED_FOR" ];
}

You’ll see a huge improvement if you use Apache, especially if you don’t use a full page caching plugin like WP Super Cache on your WordPress site.

To see exactly how well Varnish is working use varnishstat and watch the ratio of cache hit and miss requests. This will vary depending on your TTL and by how much time Varnish has had to populate the cache. You can also configure logging using varnishncsa as described on this page:

varnishncsa -a -w /var/log/varnish/access.log -D -P /var/run/varnishncsa.pid

Now use multitail to watch /var/log/varnish/access.log and your web server’s access log.

I used a number of sites for help when setting this up. Here are a few:

I have tried Nginx in the past but could not getting it working without causing huge CPU spikes as PHP went a little mad. In comparison, Varnish was simple to install and set up. Have you tried Varnish yet? How can I improve the code above?

Edit: It looks like someone else has done the hard work. I must give the WordPress Varnish plugin a go.

This plugin purges your varnish cache when content is added or edited. This includes when a new post is added, a post is updated or when a comment is posted to your blog.

Batman The Movie Theme by Powerglove

Ah, one of my favourite movies of all time. Batman The Movie, released in 1989 with a fabulous Danny Elfman soundtrack. Videogame metal band Powerglove covered the main theme tune and put a crazy video game behind it.

Here’s the original theme, much shorter. Powerglove added bits of their own. Metal fans will love it!

And here’s an excellent cover by the Cincinnati Pops Orchestra, conducted by Erich Kunzel.

Now, when’s the next Batman movie coming out? (via)

Living with CyanogenMod 7 for Samsung Galaxy S

My phone, a Samsung Galaxy S, has been running CyanogenMod 7 for the past week or so. The first week was a bit rocky. The phone ignored vibration settings at first and would vibrate when ringing, and when I hung up. In one call I couldn’t hear the caller at all! It also ignored my ringtone setting and used the first mp3 on the phone (not so bad, it was a Fun Lovin’ Criminals track!)

Anyway, I practically had to upgrade. I was running an earlier version of the Voodoo rom which unfortunately didn’t behave. Wifi kept turning itself off and I used my allowance of 3G bandwidth a couple of times. I did try to update Voodoo but screwed up and had to do a factory reset. Thankfully I had a backup done with Titanium Backup! After restoring my apps I decided to take the plunge to CM7. Why? Gingerbread!

CyanogenMod is an aftermarket firmware for a number of cell phones based on the open-source Android operating system. It offers features not found in the official Android based firmwares of vendors of these cell phones.

Initially I installed the 7.1.0 RC1 but there were problems as I mentioned above. There are nightly builds however and they’re supposed to be fairly easy to install. I screwed that up too but eventually got everything working! I’m now running nightly #67 and things have been fairly smooth.

CyanogenMod 7 is a very good mod. My phone is flying along and while it does offer advantages over the stock kernel (updated more often plus other features) you do miss out on the excellent Samsung Camera app, and battery life is slightly worse. The FM radio doesn’t work either but I haven’t bothered to investigate that as I rarely use it.

Flashing a new rom isn’t for the unadventurous. If the idea of rebooting into recovery mode, possibly changing radio drivers and knowing you might run into a world of pain scares you, don’t do it! Gingerbread, the latest Android firmware for phones, is making its way to the SGS and if you haven’t got it yet run KIES and you may find it waiting for you. The advantage of using CM7 is that they can move to the very latest Gingerbread (2.3.5 at the time of writing, my phone company only offers 2.3.3). Nightly build #70 introduced that version of the OS. You might want to keep an eye on this thread on the XDA forums too. There are problems with the nightlies but of course most of those who have no problem won’t be posting there so you’re bound to see a concentration of negativity. #67 works fine for me. YMMV!

How fast is my Samsung Galaxy S now? I ran Quadrant Standard three times, with progressively better scores.

  1. 1612
  2. 1977
  3. 2015
For comparison, the original Samsung Galaxy S had a score of 750. I would be very interested to hear how the stock Samsung Galaxy S with the Samsung Gingerbread firmware compares.

It’s still not quite as fast as the Galaxy S with the venerable “One Click Lag Fix” I benchmarked a while back. That used EXT2 however, a filesystem lacking journaling features important to maintaining data in the event of a system crash or problem.

Would I recommend CyanogenMod 7? If you’re a techie and can live without the Samsung Camera App then yes. Go for it. If you’re an Open Source fan who hates proprietary software you should definitely go for it. You even have to install Google Apps separately because they are proprietary software!

If you just use your phone to take photos, check Twitter and make phone calls, then don’t go near CyanogenMod 7 (or any firmware TBH!) just yet.

Tabbed SSH Sessions in Putty

If you’re a Windows user who uses Putty to ssh to your server you may be annoyed by the fact that you must have a separate window for each ssh session. I know I am, as tabbing through windows to find the right browser window is made just a little bit harder by flipping through those black screens.

Anyway, I went searching. There are ways to fix this. Unfortunately only one worked for me.

  1. Putty Connection Manager – is a nice interface that imported my Putty sessions automatically. Unfortunately double clicking on them launched the session but, apart from a new tab showing, the terminal window itself remained grey.
  2. Superputty – is very similar to Putty Connection Manager but didn’t work either. It doesn’t import Putty sessions automatically, it had to be done manually through a menu. Even though I didn’t have any sessions it warned that imported sessions might overwrite Superputty sessions. When I double clicked on a session it loaded Putty in a new window.
  3. WinTabber is a general purpose tabbing app that makes it easy to tab any sort of windows. However, during the install it offers to install Putty so they know their market! You can use CTRL and the number keys to switch quickly between tabs, just like I’m used to on other operating systems. This worked fine, but the free version has a limit of 4 tabs. Don’t worry, the registered version only costs $5 so it’s not going to break the bank.

In Mac OS X and Linux the terminals I use support tabs so I’ve always thought it odd there wasn’t an ssh client bundled with Windows. How do you handle ssh sessions in Windows?

Cookies for Comments 0.5.4

Cookies for Comments is a WordPress plugin that can be used alongside Akismet to significantly reduce or even kill completely comment spam.

Version 0.5.4 adds a rejections page in case human visitors trip over the cookie check. You can modify the message shown to visitors and it’s obviously only useful if you don’t use the cookie check in your .htaccess file.

It happens sometimes, usually when the visitor has cookies turned off, but very occasionally for some other reason. (That I don’t know of yet)

This plugin isn’t a replacement for Akismet as it is easily bypassed. Thankfully 99% of spam bots don’t bother checking so this plugin works quite well!

My Favourite Android Apps

I’ve used a Samsung Galaxy S since August last year and in that time I’ve downloaded and played with lots of apps and games. Here are a few of my favourites.

  1. Tweetdeck
  2. Dolphin Browser HD
  3. Kindle and FBReader
  4. Amazon Appstore and Android Market
  5. Reddit is Fun
  6. GO Contacts/Dialer/Launcher EX/SMS Pro
  7. CardioTrainer
  8. WordPress
  9. aCar
  10. Juice Defender
And some games
  1. Galaxy Domination (not on the market any more, now here!)
  2. Cut the Rope
  3. Guns ‘n’ Glory

Besides those, there are so many apps on my phone now that it’s ridiculous. I recently started using the Google+ app, and the Amazon Appstore gives away a free paid app every day so that’s my first port of call shortly after 8am every morning. There’s also getjar.com who have a free ad-supported version of Cut the Rope, as well as many other apps and games.

I used to play a lot more games, I’d dive into Galaxy Domination any chance I’d get but now I’d rather read a book in the Kindle app or FBReader, or check out the latest Reddit posts on “Reddit is Fun”.

If you have a phone with a fairly big screen (the Galaxy S has a 4 inch screen) then reading on them is a rare pleasure. No more fiddling with bookmarks or holding the spine of a thick volume open. Go on, head over to Amazon now and pick up a cheap ebook. You might just like it!

You might wonder how much has this all cost me? I’ve bought quite a few books on the Kindle store (I still think it’s wonderful that I can visit Amazon from my phone and buy a book), but I’ve only bought 2 apps. Those would be aCar (purchased through the author’s website) and just last night I bought Juice Defender Plus. As I mentioned in a previous post on battery saving tips that app shuts off the various radios in your phone when not in use, switching them on momentarily for syncing on a regular basis. The free version turns off the 3G connection when the screen is locked, but not wifi. The paid for version  does that and it’s well worth it. Battery life sky rockets after using this app!