<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>matthew manning</title>
    <link>http://mwmanning.com/</link>
    <atom:link href="http://mwmanning.com/rss.xml" rel="self" type="application/rss+xml" />
    <description>matthew manning</description>
    <language>en-us</language>
    <pubDate>Thu, 19 Jan 2012 15:59:22 +0000</pubDate>
    <lastBuildDate>Thu, 19 Jan 2012 15:59:22 +0000</lastBuildDate>

    
    <item>
      <title>Cloud Goodness With the DNSimple ALIAS Record</title>
      <link>http://mwmanning.com/2012/01/18/Cloud-Goodness-with-DNSimple-ALIAS-Record.html</link>
      <pubDate>Wed, 18 Jan 2012 00:00:00 +0000</pubDate>
      <author>matt.manning@gmail.com (Matt Manning)</author>
      <guid>http://mwmanning.com/2012/01/18/Cloud-Goodness-with-DNSimple-ALIAS-Record</guid>
      <description>&lt;p&gt;This is the third in a &lt;a href='/2011/11/29/Run-Your-Jekyll-Site-On-Heroku.html'&gt;series&lt;/a&gt; of &lt;a href='/2011/12/04/Jekyll-on-Heroku-Part-2.html'&gt;posts&lt;/a&gt; about setting up this Jekyll-backed blog on Heroku.&lt;/p&gt;

&lt;p&gt;Cloud computing and second-level domains a.k.a. root domains (example.com) don&amp;#8217;t play nicely together. This is because of &lt;a href='http://www.ietf.org/rfc/rfc1034.txt'&gt;RFC 1034&lt;/a&gt; section 3.6.2: &amp;#8220;If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different.&amp;#8221; Since root domains tend to have several types of records &amp;#8211; &amp;#8220;other data&amp;#8221; &amp;#8211; like NS or MX records, you can&amp;#8217;t use a CNAME for them. That means you&amp;#8217;re left with A records, which must specify IP addresses. Hence the rub with cloud computing, which tries to abstract away servers and IP addresses.&lt;/p&gt;

&lt;p&gt;Heroku deals with root domains by providing &lt;a href='http://devcenter.heroku.com/articles/custom-domains#dns_setup'&gt;3 public IP addresses&lt;/a&gt; for routing web requests. For SSL, the extremely cloud-unfriendly &lt;a href='http://addons.heroku.com/ssl'&gt;IP-based SSL add-on&lt;/a&gt; is used, which provisions a dedicated server instance to serve your certificate. While these solutions work, they&amp;#8217;re not really optimal. For example, if Heroku ever changes those IP addresses, as would be necessary in the case of a large-scale DDoS attack, or a datacenter failure, your root domain would no longer resolve. The IP-based SSL add-on has these same downsides, plus it&amp;#8217;s a scaling bottleneck and costs $100/mo. Bummer.&lt;/p&gt;

&lt;p&gt;DNSimple has introduced a really clever mechanism for dealing with this problem, the &lt;a href='http://blog.dnsimple.com/introducing-the-alias-record/'&gt;ALIAS record&lt;/a&gt;. An ALIAS record is set up much like a CNAME, but it resolves the name it points to and returns its IP addresses as if you had set up A records for them. This provides the flexibility of a CNAME without violating the RFC. You can see it working for this site using the &lt;code&gt;host&lt;/code&gt; command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[~/code/blog] host mwmanning.com
mwmanning.com has address 107.20.209.232
mwmanning.com has address 107.22.180.220
mwmanning.com has address 107.20.154.48
mwmanning.com has address 107.22.181.229
mwmanning.com has address 107.22.173.156
mwmanning.com has address 50.17.208.142
mwmanning.com has address 107.22.180.255
mwmanning.com has address 107.22.178.183&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Besides the routing flexibility afforded by using an ALIAS record, you can take advantage of &lt;a href='http://devcenter.heroku.com/articles/http-routing#the_herokuappcom_http_stack'&gt;Heroku&amp;#8217;s new HTTP stack&lt;/a&gt;, which is only available at [appname].herokuapp.com, and not at the 3 IPs mentioned previously. You can also use an ALIAS record to provide SSL at your root domain without using the IP-SSL add-on. If you use the Endpoint SSL add-on (available in the Beta program), you can actually have SSL at your root domain for free!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Jekyll on Heroku Part 2: Rack 'Em</title>
      <link>http://mwmanning.com/2011/12/04/Jekyll-on-Heroku-Part-2.html</link>
      <pubDate>Sun, 04 Dec 2011 00:00:00 +0000</pubDate>
      <author>matt.manning@gmail.com (Matt Manning)</author>
      <guid>http://mwmanning.com/2011/12/04/Jekyll-on-Heroku-Part-2</guid>
      <description>&lt;p&gt;This is a follow up to my previous post, &lt;a href='/2011/11/29/Run-Your-Jekyll-Site-On-Heroku.html'&gt;Run Your Jekyll Site On Heroku&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='ditching_rackjekyll'&gt;Ditching rack-jekyll&lt;/h2&gt;

&lt;p&gt;The previous post we got going as a Rack app using rack-jekyll. While rack-jekyll is a good project, it does some checking that isn&amp;#8217;t really necessary since we&amp;#8217;re precompiling the site and don&amp;#8217;t need to build anything at runtime.&lt;/p&gt;

&lt;p&gt;I first tried replacing rack-jekyll with Rack::Static, but it only works with explicit filenames. For example, with rack static the URL &lt;a href=''&gt;http://mwmanning.com/index.html&lt;/a&gt; would work fine, but &lt;a href=''&gt;http://mwmanning.com&lt;/a&gt; would return a 404. Luckily I found &lt;a href='http://chriscontinanza.com/2011/06/15/Jekyll-to-heroku.html'&gt;this blog post by Chris Continanza&lt;/a&gt; which clued me in to Rack::TryStatic, which is part of &lt;a href='https://github.com/rack/rack-contrib'&gt;rack-contrib&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Making this switch is pretty easy. Just remove the rack-jekyll gem and add the rack-contrib gem, so your Gemfile looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;source :rubygems

gem &amp;#39;jekyll&amp;#39;
gem &amp;#39;rack-contrib&amp;#39;
gem &amp;#39;RedCloth&amp;#39;
gem &amp;#39;thin&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then change your config.ru file to use Rack::TryStatic. The result should look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require &amp;#39;rack/contrib/try_static&amp;#39;

use Rack::TryStatic,
    :root =&amp;gt; &amp;quot;_site&amp;quot;,
    :urls =&amp;gt; %w[/],
    :try =&amp;gt; [&amp;#39;.html&amp;#39;, &amp;#39;index.html&amp;#39;, &amp;#39;/index.html&amp;#39;]

run lambda { [404, {&amp;#39;Content-Type&amp;#39; =&amp;gt; &amp;#39;text/html&amp;#39;}, [&amp;#39;Not Found&amp;#39;]]}&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='rewriting_urls'&gt;Rewriting URLs&lt;/h2&gt;

&lt;p&gt;One of the reasons I really wanted Rack was for rewriting URLs. That&amp;#8217;s something the Jekyll server can&amp;#8217;t do. My old blog was a Wordpress site hosted by A Small Orange, and its URL scheme was slightly different. I had a few links and some Google results pointing to my old URLs, and I didn&amp;#8217;t want to throw all of that away, so I turned to &lt;a href='https://github.com/jtrupiano/rack-rewrite'&gt;Rack::Rewrite&lt;/a&gt;. With Rack:Rewrite you get a little DSL that lets you specify routes that are either rewritten or issue redirects. Regular expressions are available for route matching, which suited my needs perfectly for supporting the old blog URL scheme.&lt;/p&gt;

&lt;p&gt;Since I don&amp;#8217;t plan to go back to the old scheme from the Wordpress blog, I dedided to use 301 - Moved Permanently redirects.&lt;/p&gt;

&lt;p&gt;I added the gem to my Gemfile:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;source :rubygems

gem &amp;#39;jekyll&amp;#39;
gem &amp;#39;rack-contrib&amp;#39;
gem &amp;#39;rack-rewrite&amp;#39;
gem &amp;#39;RedCloth&amp;#39;
gem &amp;#39;thin&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and set up the appropriate redirects in my config.ru:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require &amp;#39;rack/contrib/try_static&amp;#39;
require &amp;#39;rack/rewrite&amp;#39;

# Support links to old Wordpress site
use Rack::Rewrite do
  r301 &amp;#39;/2010/11/29/ec2-micro-instance-as-a-remote-bittorrent-client/&amp;#39;, &amp;#39;/2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html&amp;#39;
  r301 &amp;#39;/2009/01/13/timemachine-ubuntu-nas/&amp;#39;, &amp;#39;/2009/01/13/TimeMachine-Ubuntu-NAS.html&amp;#39;
  r301 &amp;#39;/projects/jack-o-led/&amp;#39;, &amp;#39;/projects/jack-o-LED.html&amp;#39;
  r301 %r{/projects/(\S+)/}, &amp;#39;/projects/$1.html&amp;#39;
end

use Rack::TryStatic,
    :root =&amp;gt; &amp;quot;_site&amp;quot;,
    :urls =&amp;gt; %w[/],
    :try =&amp;gt; [&amp;#39;.html&amp;#39;, &amp;#39;index.html&amp;#39;, &amp;#39;/index.html&amp;#39;]

run lambda { [404, {&amp;#39;Content-Type&amp;#39; =&amp;gt; &amp;#39;text/html&amp;#39;}, [&amp;#39;Not Found&amp;#39;]]}&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='caching'&gt;Caching&lt;/h2&gt;

&lt;p&gt;The final piece I wanted for my Rack app was caching. Older Heroku stacks (Aspen and Bamboo, which only support Ruby apps) use &lt;a href='https://www.varnish-cache.org/'&gt;Varnish&lt;/a&gt; and &lt;a href='http://nginx.org/'&gt;nginx&lt;/a&gt; in front of the app server and can be blazing fast. The Cedar stack does not, because they &lt;a href='http://devcenter.heroku.com/articles/http-routing#the_herokuappcom_http_stack'&gt;conflict with some advanced HTTP features it supports&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Luckily, Heroku offers a &lt;a href='http://addons.heroku.com/memcache'&gt;hosted memcache add-on&lt;/a&gt; which can be used with the Rack::Cache middleware. The free version of the add-on gives you 5MB of memory, which is pretty good for my purposes since my whole app (gems included) is only a little over 7MB. To get this working I first added the add-on with this command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;heroku addons:add memcache:5mb&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, I needed a couple of gems, dalli and rack-cache. With those installed my Gemfile looked like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;source :rubygems

gem &amp;#39;dalli&amp;#39;
gem &amp;#39;jekyll&amp;#39;
gem &amp;#39;rack-cache&amp;#39;
gem &amp;#39;rack-contrib&amp;#39;
gem &amp;#39;rack-rewrite&amp;#39;
gem &amp;#39;RedCloth&amp;#39;
gem &amp;#39;thin&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The last bit was to set up Rack::Cache in the config.ru file.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require &amp;#39;dalli&amp;#39;
require &amp;#39;rack/cache&amp;#39;
require &amp;#39;rack/contrib/try_static&amp;#39;
require &amp;#39;rack/rewrite&amp;#39;

$cache = Dalli::Client.new
use Rack::Cache,
  :verbose =&amp;gt; true,
  :metastore =&amp;gt; $cache,
  :entitystore =&amp;gt; $cache

# Support links to old Wordpress site
use Rack::Rewrite do
  r301 &amp;#39;/2010/11/29/ec2-micro-instance-as-a-remote-bittorrent-client/&amp;#39;, &amp;#39;/2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html&amp;#39;
  r301 &amp;#39;/2009/01/13/timemachine-ubuntu-nas/&amp;#39;, &amp;#39;/2009/01/13/TimeMachine-Ubuntu-NAS.html&amp;#39;
  r301 &amp;#39;/projects/jack-o-led/&amp;#39;, &amp;#39;/projects/jack-o-LED.html&amp;#39;
  r301 %r{/projects/(\S+)/}, &amp;#39;/projects/$1.html&amp;#39;
end

use Rack::TryStatic,
    :root =&amp;gt; &amp;quot;_site&amp;quot;,
    :urls =&amp;gt; %w[/],
    :try =&amp;gt; [&amp;#39;.html&amp;#39;, &amp;#39;index.html&amp;#39;, &amp;#39;/index.html&amp;#39;]

run lambda { [404, {&amp;#39;Content-Type&amp;#39; =&amp;gt; &amp;#39;text/html&amp;#39;}, [&amp;#39;Not Found&amp;#39;]]}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I set this up without really thinking too much about it. Caching Is Good™, right? Well I decided to do a quick test with ApacheBench to see what kind of average response times I got. (If you&amp;#8217;re having trouble with ApacheBench on OS X Lion, &lt;a href='https://gist.github.com/1430691'&gt;here&amp;#8217;s how to fix it&lt;/a&gt;). First I wanted to get a baseline number without caching, so I removed that part from config.ru and ran this test on one dyno.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[~/code/blog] ab -n 1000 -c 5 http://www.mwmanning.com/2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html
This is ApacheBench, Version 2.3 &amp;lt;$Revision: 1178079 $&amp;gt;
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.mwmanning.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        thin
Server Hostname:        www.mwmanning.com
Server Port:            80

Document Path:          /2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html
Document Length:        11274 bytes

Concurrency Level:      5
Time taken for tests:   42.249 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      11451000 bytes
HTML transferred:       11274000 bytes
Requests per second:    23.67 [#/sec] (mean)
Time per request:       211.247 [ms] (mean)
Time per request:       42.249 [ms] (mean, across all concurrent requests)
Transfer rate:          264.68 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       29   43  12.6     39     117
Processing:    75  168 127.0    140    1870
Waiting:       32   59  27.4     53     422
Total:        109  211 127.5    184    1913

Percentage of the requests served within a certain time (ms)
  50%    184
  66%    199
  75%    209
  80%    218
  90%    255
  95%    310
  98%    582
  99%    853
 100%   1913 (longest request)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Not bad. The average response time was about 211ms, with 2/3 of requests taking less than 200ms. Next I turned caching back on and ran the same test.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[~/code/blog] ab -n 1000 -c 5 http://www.mwmanning.com/2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html
This is ApacheBench, Version 2.3 &amp;lt;$Revision: 1178079 $&amp;gt;
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.mwmanning.com (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        thin
Server Hostname:        www.mwmanning.com
Server Port:            80

Document Path:          /2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html
Document Length:        11274 bytes

Concurrency Level:      5
Time taken for tests:   49.630 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      11593000 bytes
HTML transferred:       11274000 bytes
Requests per second:    20.15 [#/sec] (mean)
Time per request:       248.152 [ms] (mean)
Time per request:       49.630 [ms] (mean, across all concurrent requests)
Transfer rate:          228.11 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       28   43  60.9     35    1142
Processing:    76  205 262.7    142    3830
Waiting:       41   77 140.4     59    2418
Total:        110  248 285.4    183    3932

Percentage of the requests served within a certain time (ms)
  50%    183
  66%    199
  75%    214
  80%    228
  90%    392
  95%    548
  98%    970
  99%   1279
 100%   3932 (longest request)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What&amp;#8217;s this? Not only were the caching results not any better, the averages were slightly &lt;em&gt;worse&lt;/em&gt;. This was a bit of a facepalm moment. The main purpose of caching is to prevent calculations or database transactions being made by the web app backend, but in this case the web app backend is doing very little other than serving static files off of disk. Plus the Memcached instance being used here is network-attached, so there&amp;#8217;s some unavoidable latency in that connection. In this case serving files off of disk is faster than serving out of memory over a network connection, so I disabled caching. Hooray for the scientific method!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Run Your Jekyll Site On Heroku</title>
      <link>http://mwmanning.com/2011/11/29/Run-Your-Jekyll-Site-On-Heroku.html</link>
      <pubDate>Tue, 29 Nov 2011 00:00:00 +0000</pubDate>
      <author>matt.manning@gmail.com (Matt Manning)</author>
      <guid>http://mwmanning.com/2011/11/29/Run-Your-Jekyll-Site-On-Heroku</guid>
      <description>&lt;p&gt;A few months back I decided I wanted to &lt;a href='http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html'&gt;blog like a hacker&lt;/a&gt;, so I started revamping my old Wordpress blog into a more minimal site generated by &lt;a href='http://github.com/mojombo/jekyll'&gt;Jekyll&lt;/a&gt;. You&amp;#8217;re reading the result of that work right now.&lt;/p&gt;

&lt;p&gt;I was happy with how easy Jekyll was to set up and use, and it&amp;#8217;s a relief to have my post archives as markdown files under Git version control instead of in a proprietary blog engine format in some database.&lt;/p&gt;

&lt;p&gt;One of the cool things about a Jekyll site is that you can push it to Github, and Github will serve it. Not just the source, but the actual site itself. You can see it working with this site. &lt;a href='https://github.com/mattmanning/mattmanning.github.com'&gt;Here is the source&lt;/a&gt;, and &lt;a href='http://mattmanning.github.com/'&gt;here it is running&lt;/a&gt;. While this is pretty cool, Github isn&amp;#8217;t really an app platform. I wanted to run my site on &lt;a href='http://www.heroku.com'&gt;Heroku&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Through some searching and tinkering I figured out a couple of different ways of getting my site running on Heroku. I&amp;#8217;ll share both of them here. The first method is great for its simplicity but is short on configurability and efficiency. The second method is more complicated but is performant and endlessly tweakable.&lt;/p&gt;

&lt;h2 id='method_1_running_the_jekyll_server_on_heroku'&gt;Method 1: Running the Jekyll Server on Heroku&lt;/h2&gt;

&lt;p&gt;Heroku&amp;#8217;s latest application stack, Cedar, provides an amazing amount of flexibility with some very simple configuration techniques. It makes running your Jekyll site on Heroku as simple as running it on your own computer &amp;#8211; you install some gems and run the server.&lt;/p&gt;

&lt;p&gt;I used this &lt;a href='https://github.com/markpundsack/jekyll-heroku'&gt;example app created by Mark Pundsack&lt;/a&gt; as a guide. Its REAME explains the setup process very well. Here is a simple series of steps to get up and running for free on Heroku, assuming you already have a working Jekyll site.&lt;/p&gt;

&lt;h3 id='create_a_heroku_app_on_the_cedar_stack'&gt;Create a Heroku app on the Cedar stack&lt;/h3&gt;

&lt;p&gt;From the top level of your Jekyll site&amp;#8217;s repo, create the Heroku site. This will provision the Heroku site and add a git remote named &amp;#8220;heroku&amp;#8221;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;heroku create -s cedar&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='install_the_gems'&gt;Install the gems&lt;/h3&gt;

&lt;p&gt;Create a Gemfile that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;source :rubygems

gem &amp;#39;jekyll&amp;#39;
gem &amp;#39;RedCloth&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;bundle install&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;to install the gems and create a Gemfile.lock file.&lt;/p&gt;

&lt;h3 id='configure_the_jekyll_server'&gt;Configure the Jekyll server&lt;/h3&gt;

&lt;p&gt;Apps on the Cedar stack define their process types via a &lt;a href='http://devcenter.heroku.com/articles/procfile'&gt;Procfile&lt;/a&gt;. Your Procfile needs one line defining the Jekyll server like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;web: bundle exec jekyll --server -p $PORT&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='deploy_to_heroku'&gt;Deploy to Heroku&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;git push heroku master&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#8217;s it! Now your Jekyll site is running on Heroku.&lt;/p&gt;

&lt;h2 id='method_2_running_your_site_as_a_rack_app'&gt;Method 2: Running Your Site As a Rack App&lt;/h2&gt;

&lt;p&gt;While the method above is simple and straightforward, it&amp;#8217;s not the ideal way to run the site. The Jekyll server isn&amp;#8217;t meant for production as it generates pages on the fly for every request. I wanted to take advantage of the real power of Jekyll, its ability to generate a static site that can be served efficiently.&lt;/p&gt;

&lt;p&gt;Instead of using the Jekyll server, I really wanted to serve my site as a Rack app. That way I could choose my own app server and have a great deal more control over things like caching using Rack middleware.&lt;/p&gt;

&lt;h3 id='setting_up_rackjekyll'&gt;Setting Up rack-jekyll&lt;/h3&gt;

&lt;p&gt;Luckily this can be done quite easily using the &lt;a href='https://github.com/adaoraul/rack-jekyll'&gt;rack-jekyll&lt;/a&gt; project. Here&amp;#8217;s how to set it up.&lt;/p&gt;

&lt;p&gt;First add the gem to your Gemfile. I also added the &lt;a href='http://code.macournoyer.com/thin/'&gt;Thin&lt;/a&gt; gem, so I could use it as my server. Now your Gemfile should look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;source :rubygems

gem &amp;#39;jekyll&amp;#39;
gem &amp;#39;rack-jekyll&amp;#39;
gem &amp;#39;RedCloth&amp;#39;
gem &amp;#39;thin&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next set up a config.ru file that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require &amp;#39;rack/jekyll&amp;#39;

run Rack::Jekyll.new&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, modify your Procfile to run your new Rack app. With Thin, mine looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;web: bundle exec thin start -p $PORT -e $RACK_ENV&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='building_your_site_the_right_way'&gt;Building Your Site the Right Way&lt;/h3&gt;

&lt;p&gt;The documentation for rack-jekyll suggests building the files and then committing the _site directory to your repo before deploying to Heroku. While that will work, it&amp;#8217;s a bit messy. I really didn&amp;#8217;t want builds to be checked into version control.&lt;/p&gt;

&lt;p&gt;An alternative would have been letting Jekyll build the site on the first request to each dyno, but that&amp;#8217;s no good either, because it &lt;a href='http://www.12factor.net/build-release-run'&gt;mixes the build and run phases&lt;/a&gt;. Plus, depending on writes across multiple requests is not the intended use of Heroku&amp;#8217;s &lt;a href='http://devcenter.heroku.com/articles/dyno-isolation#ephemeral_filesystem'&gt;ephemeral writable filesystem&lt;/a&gt; and could lead to bugs.&lt;/p&gt;

&lt;p&gt;What I really needed was to build the site during Heroku&amp;#8217;s build phase. This can actually be done by leveraging a new experimental feature known as a &amp;#8220;custom buildpack.&amp;#8221; Buildpacks are the key to Heroku&amp;#8217;s polyglot platform. Each language or framework supported on Heroku such as &lt;a href='https://github.com/heroku/heroku-buildpack-ruby'&gt;Ruby&lt;/a&gt;, &lt;a href='https://github.com/heroku/heroku-buildpack-nodejs'&gt;Node.js&lt;/a&gt;, or &lt;a href='https://github.com/heroku/heroku-buildpack-clojure'&gt;Clojure&lt;/a&gt; has it&amp;#8217;s own buildpack containing the tools necessary to build an app.&lt;/p&gt;

&lt;p&gt;In a normal deployment Heroku automatically detects what buildpack to apply, but you can actually tell Heroku to use a specific buildpack. Either pass an option for it when you create the app:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;heroku create -s cedar --buildpack [URL]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or provide the URL for the buildpack repo using the BUILDPACK_URL config variable.&lt;/p&gt;

&lt;p&gt;Since it already had all the tools for Rack apps, I &lt;a href='https://github.com/mattmanning/heroku-buildpack-ruby-jekyll'&gt;forked the Ruby buildpack&lt;/a&gt; and added &lt;a href='https://github.com/mattmanning/heroku-buildpack-ruby-jekyll/commit/e86ac4f4e7c839b6f977ed6de22e1ecb6c94b723'&gt;a few lines&lt;/a&gt; so that my Jekyll site will be built by Heroku during slug compilation. Finally I set my BUILDPACK_URL with the following command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;heroku config:add BUILDPACK_URL=http://github.com/mattmanning/heroku-buildpack-ruby-jekyll.git&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now when I deploy I see an extra &amp;#8220;Building jekyll site&amp;#8221; line in the output,&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[~/code/blog] git push heroku master
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 1.10 KiB, done.
Total 8 (delta 4), reused 0 (delta 0)

-----&amp;gt; Heroku receiving push
-----&amp;gt; Fetching custom build pack... done
-----&amp;gt; Ruby/Rack app detected
-----&amp;gt; Installing dependencies using Bundler version 1.1.rc
       Running: bundle install --without development:test --path vendor/bundle --binstubs bin/ --deployment
       Fetching gem metadata from http://rubygems.org/.......
       Using RedCloth (4.2.8)
       Using posix-spawn (0.3.6)
       Using albino (1.3.3)
       Using fast-stemmer (1.0.0)
       Using classifier (1.3.3)
       Using daemons (1.1.4)
       Using directory_watcher (1.4.1)
       Using eventmachine (0.12.10)
       Using kramdown (0.13.3)
       Using liquid (2.3.0)
       Using syntax (1.0.0)
       Using maruku (0.6.0)
       Using jekyll (0.11.0)
       Using rack (1.3.5)
       Using thin (1.3.1)
       Using bundler (1.1.rc)
       Your bundle is complete! It was installed into ./vendor/bundle
       Cleaning up the bundler cache.
       Building jekyll site
-----&amp;gt; Discovering process types
       Procfile declares types     -&amp;gt; web
       Default types for Ruby/Rack -&amp;gt; console, rake
-----&amp;gt; Compiled slug size is 7.2MB
-----&amp;gt; Launching... done, v47
-----&amp;gt; Deploy hooks scheduled, check output in your logs
       http://www.mwmanning.com deployed to Heroku

To git@heroku.com:mattmanning.git
   8f84bc4..9350a12  master -&amp;gt; master&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;and my site runs as a Rack app without polluting the repo with build files!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>EC2 Micro Instance as a Remote Bittorrent Client</title>
      <link>http://mwmanning.com/2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client.html</link>
      <pubDate>Mon, 29 Nov 2010 00:00:00 +0000</pubDate>
      <author>matt.manning@gmail.com (Matt Manning)</author>
      <guid>http://mwmanning.com/2010/11/29/EC2-Micro-Instance-as-a-Remote-Bittorrent-Client</guid>
      <description>&lt;p&gt;Bittorrent is an efficient, fault-tolerant way to distribute files across the Internet. When a file is popular, it can get shared really quickly as lots of users swarm to download and upload the file simultaneously. When a file is less popular, however, it can take hours or even days to download because of a diminished number of seeders. If you use a desktop computer that runs 24/7 and is always connected to a reliable Internet connection this is no problem, but if your primary machine is a laptop and especially if you use it on the go, slow torrents can turn into a problem.&lt;/p&gt;

&lt;p&gt;Wouldn’t it be nice if you had a remote Bittorrent client running on a reliable server somewhere? You could start a download any time from any computer, then pull down the file over a fast, reliable connection when it’s finished. You could even be nice and seed the file for a few days, all the while using (or more importantly NOT using) your laptop as normal.&lt;/p&gt;

&lt;p&gt;Amazon’s new, cheap — or in limited cases free — &amp;#8220;micro&amp;#8221; EC2 instances make this a possibility. Below you’ll find a step-by-step guide to set up your own remote bittorrent client using the Transmission application on an EC2 micro instance running Ubuntu.&lt;/p&gt;

&lt;h2 id='amazon_web_services'&gt;Amazon Web Services&lt;/h2&gt;

&lt;p&gt;First you’ll need to create an Amazon Web Services (AWS) account. If you already have an AWS account you can skip ahead to the server creation. If not head on over to &lt;a href='http://aws.amazon.com/free/'&gt;http://aws.amazon.com/free&lt;/a&gt; and sign up for an account and get your free Linux-based micro instance (this is what we’ll be using to run our client).&lt;/p&gt;

&lt;h2 id='creating_and_booting_an_instance'&gt;Creating and Booting an Instance&lt;/h2&gt;

&lt;p&gt;Now that you’re all signed up, we need to create and boot an EC2 micro instance to run our client. EC2 instances are based on Amazon Machine Image (AMI) files. For this guide, we’ll be using one of the official Ubuntu 10.4 LTS AMIs found here. You should chose a 32-bit, EBS-based AMI from a region geographically close to you. I chose ami-480df921.&lt;/p&gt;

&lt;p&gt;Once you have the ID of the AMI you want to use, create a new instance based on it. Log into the AWS management console and click on the &amp;#8220;Instances&amp;#8221; link in the left navbar, then click the &amp;#8220;Launch Instance&amp;#8221; button.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-launch.png'&gt;&lt;img height='216' src='/images/remotebt-launch.png' width='384' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &amp;#8220;Community Instances&amp;#8221; tab in the wizard that pops up and paste your AMI ID into the search field. Click the &amp;#8220;Select&amp;#8221; button next the the search result for your image.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-ami.png'&gt;&lt;img height='198' src='/images/remotebt-ami.png' width='692' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Change the &amp;#8220;Instance Type&amp;#8221; to &amp;#8220;Micro (t1.micro, 613 MB) and click &amp;#8220;Continue.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-micro.png'&gt;&lt;img height='468' src='/images/remotebt-micro.png' width='698' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &amp;#8220;Continue&amp;#8221; on the next screen to use the default Kernel ID and RAM Disk ID.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-kernel.png'&gt;&lt;img height='468' src='/images/remotebt-kernel.png' width='694' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next screen, give your instance a name. I called mine &amp;#8220;Remote Bittorrent.&amp;#8221; Click &amp;#8220;Continue.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-name.png'&gt;&lt;img height='468' src='/images/remotebt-name.png' width='694' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don’t already have a key pair set up, click the &amp;#8220;Create New Key Pair&amp;#8221; radio button and follow the directions to create a new key pair.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-keypair.png'&gt;&lt;img height='342' src='/images/remotebt-keypair.png' width='686' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next screen, click the &amp;#8220;Create a New Security Group&amp;#8221; radio button. Here we will open port 22 so we can SSH into the server for administration. Add an entry for SSH by choosing it from the select in the &amp;#8220;Application&amp;#8221; column and clicking the &amp;#8220;Add Rule&amp;#8221; button. Click &amp;#8220;Continue.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-ssh.png'&gt;&lt;img height='468' src='/images/remotebt-ssh.png' width='694' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally click the &amp;#8220;Launch&amp;#8221; button to start your instance. It may take a few minutes to launch your instance for the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-launch2.png'&gt;&lt;img height='468' src='/images/remotebt-launch2.png' width='688' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Return to the management console and click &amp;#8220;Security Groups&amp;#8221; in the left navbar. Click the name of the security group we just created; we need to a few more rules to it.&lt;/p&gt;

&lt;p&gt;First we’ll open port 9091, which is the port used by the Transmission web client. To do this choose &amp;#8220;Custom&amp;#8221; from the &amp;#8220;Connection Method&amp;#8221; select box. Chose TCP as the Protocol, From Port and To Port should be 9091, and the source IP should be 0.0.0.0/0. Click the &amp;#8220;Add Rule&amp;#8221; button. If you don’t see the new rule in the list right away, click the &amp;#8220;Refresh&amp;#8221; button near the top of the page.&lt;/p&gt;

&lt;p&gt;Next we’ll open a range of ports for the actual bittorrent application to use. Again chose &amp;#8220;Custom&amp;#8221; as the Connection Method, TCP as the Protocol, 49152 as the From Port, 65535 as the To Port, and 0.0.0.0/0 as the Source IP. Click &amp;#8220;Add Rule.&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-security.png'&gt;&lt;img height='252' src='/images/remotebt-security.png' width='774' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id='updateinstallation'&gt;Update/Installation&lt;/h2&gt;

&lt;p&gt;Now we’ll connect to our new server and configure all of the software we’ll be using. Click &amp;#8220;Instances&amp;#8221; in the left navbar. Select your instance and select &amp;#8220;Connect&amp;#8221; under the &amp;#8220;Instance Actions&amp;#8221; select box. Follow the directions to SSH into your server, but use the user &amp;#8220;ubuntu&amp;#8221; instead of &amp;#8220;root&amp;#8221;.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-connect.png'&gt;&lt;img height='396' src='/images/remotebt-connect.png' width='234' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ssh -i bittorrent.pem ubuntu@ec2-184-72-148-12.compute-1.amazonaws.com&lt;/p&gt;

&lt;p&gt;Now we’ll upgrade all of the installed packages. Issue the following commands:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ubuntu@ip-10-203-65-125:~$ sudo aptitude update
ubuntu@ip-10-203-65-125:~$ sudo aptitude upgrade&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, install the Transmission packages&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ubuntu@ip-10-203-65-125:~$ sudo aptitude install transmission-cli transmission-daemon&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id='configuration'&gt;Configuration&lt;/h2&gt;

&lt;p&gt;Now we want to stop transmission-daemon so we can edit its config.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ubuntu@ip-10-203-65-125:~$ sudo /etc/init.d/transmission-daemon stop&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Open the settings.json config file with your favorite editor.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ubuntu@ip-10-203-65-125:~$ sudo nano /etc/transmission-daemon/settings.json&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Save downloaded files in a more convenient place: &amp;#8220;download-dir&amp;#8221;: &amp;#8220;/home/ubuntu/Downloads&amp;#8221;&lt;/p&gt;

&lt;p&gt;Come up with a password to protect your server: &amp;#8220;rpc-password&amp;#8221;: &amp;#8220;mysecretpassword&amp;#8221;. (Don’t worry. This password will be obscured to a hash once we restart the transmission-daemon.) Turn off the rpc-whitelist so we can access this client from any IP: &amp;#8220;rpc-whitelist-enabled&amp;#8221;: false,&lt;/p&gt;

&lt;p&gt;Now start transmission-daemon back up:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ubuntu@ip-10-203-65-125:~$ sudo /etc/init.d/transmission-daemon start&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we need to create the /home/ubuntu/Downloads directory and give transmission-daemon the ability to write to it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ubuntu@ip-10-203-65-125:~$ mkdir /home/ubuntu/Downloads/
ubuntu@ip-10-203-65-125:~$ chown ubuntu:debian-transmission /home/ubuntu/Downloads/
ubuntu@ip-10-203-65-125:~$ sudo chmod g+w /home/ubuntu/Downloads/&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And we’re done!&lt;/p&gt;

&lt;p&gt;Now point your browser at your instance on port 9091. You can find the URL by clicking on your instance in the AWS management console and checking the value of the &amp;#8220;Public DNS&amp;#8221; field. For my instance, the URL is http://ec2-184-72-148-12.compute-1.amazonaws.com:9091. You will be prompted to log in. The username is &amp;#8220;transmission&amp;#8221; (unless you changed it in settings.json) and the password is whatever password you chose in settings.json.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-login.png'&gt;&lt;img height='198' src='/images/remotebt-login.png' width='398' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have a client that you can browse to at any time on any computer. You can upload torrent files directly, or you can simply enter the URL of the torrent file and have the client do the rest.&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-dl.png'&gt;&lt;img height='216' src='/images/remotebt-dl.png' width='436' /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amazon gets pretty decent download speeds too :)&lt;/p&gt;

&lt;p&gt;&lt;a href='/images/remotebt-speed.png'&gt;&lt;img height='162' src='/images/remotebt-speed.png' width='785' /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;script type='text/javascript'&gt;
  disqus_url = 'http://mwmanning.com/2010/11/29/ec2-micro-instance-as-a-remote-bittorrent-client/';
&lt;/script&gt;</description>
    </item>
    
    <item>
      <title>TimeMachine + Ubuntu NAS</title>
      <link>http://mwmanning.com/2009/01/13/TimeMachine-Ubuntu-NAS.html</link>
      <pubDate>Tue, 13 Jan 2009 00:00:00 +0000</pubDate>
      <author>matt.manning@gmail.com (Matt Manning)</author>
      <guid>http://mwmanning.com/2009/01/13/TimeMachine-Ubuntu-NAS</guid>
      <description>&lt;p&gt;So after a few months of hem-hawing around, I finally implemented a respectable backup solution for my Mac. It&amp;#8217;s getting old enough (almost 4 years) that I&amp;#8217;m starting to worry about random hardware failures, so having a reliable backup is very important.&lt;/p&gt;

&lt;p&gt;At home, I have a computer running Ubuntu Linux that I use as a file/media/print server. It has four 250 GB drives in a RAID5 configuration. Since RAID5 can be rebuilt if a drive dies, I feel like this is a pretty safe place to store backups, although eventually I hope to have an offsite backup (ex: Amazon S3) as well.&lt;/p&gt;

&lt;p&gt;A while back a little command that would let TimeMachine use network drive started floating around the Internet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I already had SAMBA set up, but I had some problems, so I ended up following this tutorial — which I highly recommend — and setting up netatalk so I could share the volume over AFP. Looking back, I don&amp;#8217;t think SAMBA was the problem, I think the issue was with creating the initial backup disk image. I had to make the image locally and copy it over, as is explained in the troubleshooting section, but after that everything worked perfectly.&lt;/p&gt;</description>
    </item>
    

  </channel> 
</rss>
