<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://seconddrawer.com.au/</id>
  <title>Second Drawer</title>
  <updated>2010-08-21T17:00:00Z</updated>
  <link rel="alternate" href="http://seconddrawer.com.au/"/>
  <link rel="self" href="http://seconddrawer.com.au/atom.xml"/>
  <author>
    <name>Felix Hanley</name>
    <uri>http://seconddrawer.com.au</uri>
  </author>
  <entry>
    <id>tag:seconddrawer.com.au,2010-08-22:/blog/2010/08/webfonts-with-nginx/</id>
    <title type="html">Webfonts with Nginx</title>
    <published>2010-08-21T17:00:00Z</published>
    <updated>2010-08-21T17:00:00Z</updated>
    <link rel="alternate" href="http://seconddrawer.com.au/blog/2010/08/webfonts-with-nginx/"/>
    <content type="html">&lt;p&gt;I just made some changes on my site to use webfonts for the main menu and any Lahu language sections of the site. I have chosen to serve the font files directly from my server as most of the other webfont servers don&amp;#8217;t provide a good Unicode 5 version of any font required for Lahu display.&lt;/p&gt;

&lt;p&gt;This does mean that I needed to update my Nginx mime types to serve the font files with the correct mime type. I added the following to my mime.types file in the Nginx config directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;application/x-font-ttf                ttf;
font/opentype                         otf;
application/vnd.ms-fontobject         eot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and reloaded Nginx. Now they are served correctly instead of &amp;#8216;application/octet-stream&amp;#8217;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:seconddrawer.com.au,2010-08-21:/blog/2010/08/logwatch-with-runit/</id>
    <title type="html">Logwatch, socklog and svlogd</title>
    <published>2010-08-20T17:00:00Z</published>
    <updated>2010-08-20T17:00:00Z</updated>
    <link rel="alternate" href="http://seconddrawer.com.au/blog/2010/08/logwatch-with-runit/"/>
    <content type="html">&lt;p&gt;&lt;a href='http://smarden.org/runit/'&gt;Runit&lt;/a&gt; is a great package that provides process supervision and can be used as a replacement for &amp;#8216;sysvinit&amp;#8217;. The author of the package has also made a syslogd replacement called &lt;a href='http://smarden.org/socklog/'&gt;socklog&lt;/a&gt; which works well with runit.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://logwatch.org/'&gt;Logwatch&lt;/a&gt; is a collection of scripts that can be used to notify you of changes to your logs. Out of the box on a Debian machine, though, logwatch will not be able to read all the logs spat out by socklog. The default setup produces logs that have the log facility and level appended to the log entry and the hostname removed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;authpriv.info: Aug 21 20:45:44 sshd: pam_unix(sshd...&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I recently had to modify Logwatch for some other reasons and thought I would post my existing scripts here for others to see also. These should be placed in the /etc/logwatch directory so they are not overwritten on package upgrades.&lt;/p&gt;

&lt;p&gt;conf/logfiles/messages.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile = 
Archive = 
LogFile = socklog/*/current
Archive = socklog/*/@*

*RemoveFacility
*ExpandRepeats
*RemoveService = talkd,telnetd,inetd,nfsd,/sbin/mingetty
*ApplyStdDate&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/syslog.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Logfile = 
Archive = 
LogFile = socklog/*/current
Archive = socklog/*/@*

*RemoveFacility
*ExpandRepeats
*RemoveService = talkd,telnetd,inetd,nfsd,/sbin/mingetty
*ApplyStdDate&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/secure.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile = 
Archive = 
LogFile = socklog/auth/current
Archive = socklog/auth/@*

*RemoveFacility
*ExpandRepeats
*ApplyStdDate&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/maillog.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile =
LogFile = socklog/mail/current
Archive =
Archive = socklog/mail/@*

*RemoveFacility&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;conf/logfiles/kernel.conf&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;LogFile = socklog/kern/current
Archive = socklog/kern/@*
*RemoveFacility
*ExpandRepeats
*ApplyStdDate&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There may be others needed for your own system. All these configurations reference the script &lt;em&gt;RemoveFacility&lt;/em&gt; does the bit of removing the facility and level from each log entry.&lt;/p&gt;

&lt;p&gt;scripts/shared/removefacility&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/perl

# removes the facility and level from logfiles generated by socklog
if ( $ENV{&amp;#39;LOGWATCH_DEBUG&amp;#39;} &amp;gt; 4 ) {
   print STDERR &amp;quot;DEBUG: Inside RemoveFacility\n&amp;quot;;
}

while (defined($ThisLine = &amp;lt;STDIN&amp;gt;)) {
   $ThisLine =~ s/^[a-z]+.[a-z]+: //i;
   print $ThisLine;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and also the onlyhost script which is used to restrict entries by host but since the hostname is not even there we just return them all:&lt;/p&gt;

&lt;p&gt;scripts/shared/onlyhost&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/perl

use strict;

my $line;
while (defined($line = &amp;lt;STDIN&amp;gt;)) {
    print $line;
}&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>tag:seconddrawer.com.au,2010-07-04:/blog/2010/07/rack-map-and-subdomains/</id>
    <title type="html">Rack map and subdomains</title>
    <published>2010-07-03T17:00:00Z</published>
    <updated>2010-07-03T17:00:00Z</updated>
    <link rel="alternate" href="http://seconddrawer.com.au/blog/2010/07/rack-map-and-subdomains/"/>
    <content type="html">&lt;h2 id='the_situation'&gt;The situation&lt;/h2&gt;

&lt;p&gt;You are using subdomains for locales such as &lt;em&gt;en.example.com&lt;/em&gt; and &lt;em&gt;th.example.com&lt;/em&gt;. Your app is Rack based and is behind Nginx with a &amp;#8216;wildcard&amp;#8217; &lt;em&gt;server_name&lt;/em&gt; directive such as:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;server {
  server_name .example.com;
  ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You are also using Rack&amp;#8217;s map abilities to have two different applications mounted on different paths on your domain. This could be done like this in your &lt;em&gt;config.ru&lt;/em&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;map &amp;#39;/users&amp;#39; do
  run Example::Admin
end

map &amp;#39;/&amp;#39; do
  run Example::Public
end&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='the_problem'&gt;The problem&lt;/h2&gt;

&lt;p&gt;If the URL &lt;em&gt;http://th.example.com&lt;/em&gt; is hit, Nginx will set &amp;#8216;HTTP_HOST&amp;#8217; as &amp;#8216;th.example.com&amp;#8217; but &amp;#8216;SERVER_NAME&amp;#8217; will be &amp;#8216;example.com&amp;#8217;. What his means is that tests within Rack fail and result in neither of the above &amp;#8216;maps&amp;#8217; matching so a 404 is returned.&lt;/p&gt;

&lt;h2 id='a_solution'&gt;A solution&lt;/h2&gt;

&lt;p&gt;In Rack apps you are able to modify the environment. This means that &lt;em&gt;one&lt;/em&gt; way to fix this is to simply set the environment&amp;#8217;s&amp;#8217; SERVER_NAME&amp;#8217; to equal &amp;#8216;HTTP_HOST&amp;#8217; by including something like this in your &lt;em&gt;config.ru&lt;/em&gt; file, before your map calls:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module Rack
  class Blah
    def initialize app
      @app = app
    end

    def call env
      env[&amp;#39;SERVER_NAME&amp;#39;] = env[&amp;#39;HTTP_HOST&amp;#39;]
      @app.call env
    end
  end
end
use Rack::Blah

map &amp;#39;/users&amp;#39; do
...etc.&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>tag:seconddrawer.com.au,2010-05-21:/blog/2010/optimising-your-images/</id>
    <title type="html">Optimise your images for performance and consistency</title>
    <published>2010-05-20T17:00:00Z</published>
    <updated>2010-05-20T17:00:00Z</updated>
    <link rel="alternate" href="http://seconddrawer.com.au/blog/2010/optimising-your-images/"/>
    <content type="html">&lt;p&gt;In an effort to reduce your website&amp;#8217;s page size, whether it be to just provide a better experience for the user or to work inline with &lt;a href='http://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html'&gt;Google&amp;#8217;s plans to factor page speed into rankings&lt;/a&gt;, you will inevitably get to the point of dealing with your site&amp;#8217;s images.&lt;/p&gt;

&lt;p&gt;In many sites the images take up a large proportion of the site&amp;#8217;s weight (in bytes). So getting the most out of them is very important. One tool that is essential in this regard is &lt;a href='http://pmt.sourceforge.net/pngcrush/'&gt;pngcrush&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='pngcrush'&gt;pngcrush&lt;/h2&gt;

&lt;p&gt;Pngcrush is a tool that &lt;em&gt;lossless&lt;/em&gt; reduces the size of PNG files. PNG are used mainly for styling the website and so are vital to the look (and often the readability) of the site itself. JPEGs are great for photographs which need no restriction on the number of colours. Compression of JPEGs are dealt with differently. Few modern designers use GIFs anymore now that IE supports alpha transparency in PNGs, so we will assume that we are only dealing with PNGs.&lt;/p&gt;

&lt;p&gt;Pngcrush uses a number of techniques to reduce the size of your PNGs such as reducing the palette or applying different compression algorithms to the image data.&lt;/p&gt;

&lt;h2 id='an_example'&gt;An example&lt;/h2&gt;

&lt;p&gt;A good example of the size difference is the &lt;a href='/images/menu.png'&gt;menu image used on this site&lt;/a&gt;. An initial save of the PNG image was 159Kb. This same image when run through pngcrush resulted in a size of 14.5Kb, with no reduction in quality. It is a simple as this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pngcrush infile.png outfile.png&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or trying more methods to reduce size:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pngcrush -brute infile.png outfile.png&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For my site, I am already using the sprite technique to combine images for my main menu so together I am able to reduce, not only the total amount to be downloaded, but also the number of HTTP requests needed to create my menu.&lt;/p&gt;

&lt;h2 id='alternatives'&gt;Alternatives&lt;/h2&gt;

&lt;p&gt;There are several other alternatives to pngcrush such as its fork, &lt;a href='http://optipng.sourceforge.net/'&gt;optiPNG&lt;/a&gt;. This does pretty much the same job.&lt;/p&gt;

&lt;h2 id='colour_consistency'&gt;Colour consistency&lt;/h2&gt;

&lt;p&gt;One thing that pngcrush does that others do not yet seem to do is reduce the file size by removing the colour correction (or colour profile) data from the file. This can sometimes reduce the size by up to 40%. What this also means is that your images will appear more consistently across browsers. How so?&lt;/p&gt;

&lt;p&gt;Many image manipulation programs will place a colour profile within the image to enable different systems to display the image as close as possible to the original. Firefox, for instance, will use these profiles to adjust the colours before displaying them. Google Chrome, on the other hand, will not. What this means is that some images on your site will appear differently in Firefox and Chrome. It could also mean that colour values in CSS style sheets will not match those colours, while using identical codes, in PNG files.&lt;/p&gt;

&lt;p&gt;The command line to remove all colour profiles from your PNG is as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pngcrush -rem gAMA -rem cHRM -rem iCCP -rem sRGB infile.png outfile.png&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='conclusion'&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;By removing the colour profile data from your images, you not only reduce the file size but you force browsers (such as Firefox) to make do without the profile and so render them more consistently, with other systems &lt;em&gt;and&lt;/em&gt; with CSS colour values. A faster and more colour accurate site.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>tag:seconddrawer.com.au,2010-04-23:/blog/2010/rack-locale-setter-middleware/</id>
    <title type="html">Rack locale setter middleware</title>
    <published>2010-04-22T17:00:00Z</published>
    <updated>2010-04-22T17:00:00Z</updated>
    <link rel="alternate" href="http://seconddrawer.com.au/blog/2010/rack-locale-setter-middleware/"/>
    <content type="html">&lt;p&gt;For a project I am currently working on I am using the nice i18n library &lt;em&gt;&lt;a href='http://github.com/ai/r18n'&gt;r18n&lt;/a&gt;&lt;/em&gt; which provides i18n for &lt;a href='http://rubyonrails.org/'&gt;Rails&lt;/a&gt;, &lt;a href='http://sinatrarb.org/'&gt;Sinatra&lt;/a&gt; and most general Ruby projects. It also is reasonably ORM agnostic and so I am using it quite easily with &lt;a href='http://datamapper.org/'&gt;DataMapper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have decided to use a subdomain to specify the locale rather than having it be part of the path. So instead of this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://example.com/en/foo/&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I have this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://en.example.com/foo/&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I find this makes it easier by being able to specify relative paths everywhere that don&amp;#8217;t need to have the locale played with. Switching the locale for the site is also just a matter of changing the domain.&lt;/p&gt;

&lt;p&gt;That said, r18n expects the locale to be placed in the &amp;#8216;params&amp;#8217; array for Sinatra and I thought a simple Rack middleware would do this well. So here it is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module Rack
  class LocaleSetter
    def initialize(app)
      @app = app
    end

    def call(env)
      req = Rack::Request.new(env)
      if m = req.host.match(/^(?:www\.)?([a-z]{2})\./)
        locale = m[1]
      else
        locale = &amp;#39;en&amp;#39;
      end
      req.params[&amp;#39;locale&amp;#39;] ||= locale
      @app.call env
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Due to many peoples&amp;#8217; habit of putting &amp;#8216;www&amp;#8217; at the start of the domain, this should account for &lt;em&gt;en.example.com&lt;/em&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;em&gt;www.en.example.com&lt;/em&gt;. It also allows for the locale to be specified in the query string. So &lt;em&gt;en.example.com/foo?locale=th&lt;/em&gt; will set the locale to &amp;#8216;th&amp;#8217;.&lt;/p&gt;

&lt;p&gt;There are probably others out there but due to the simplicity of Rack based apps it is very easy to write, and adjust, your own.&lt;/p&gt;</content>
  </entry>
</feed>
