<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>TJ Stein</title>
 
 <link href="http://tjstein.com/" />
 <updated>2012-04-05T12:52:32-07:00</updated>
 <id>http://tjstein.com/</id>
 <author>
   <name>TJ Stein</name>
   <email>thomasjstein@gmail.com</email>
 </author>

 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/tjstein" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="tjstein" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Running WordPress on Heroku + Amazon RDS</title>
   <link href="http://tjstein.com/2011/09/running-wordpress-on-heroku-and-amazon-rds" />
   <updated>2011-09-16T00:00:00-07:00</updated>
   <id>http://tjstein.com/2011/09/running-wordpress-on-heroku-and-amazon-rds</id>
   <content type="html">&lt;p&gt;&lt;img src="/images/heroku-logo.png" class="alignleft"&gt;With the &lt;a href="http://blog.heroku.com/archives/2011/9/15/facebook/" target="_new" rel="external"&gt;announcement&lt;/a&gt; of the Heroku and Facebook partnership yesterday, Heroku quietly confirmed support for two new languages, Python and PHP. The self-proclaimed polyglot platform, Heroku's &lt;a href="http://devcenter.heroku.com/articles/cedar" target="_new" rel="external"&gt;Celadon Cedar Stack&lt;/a&gt; now has a considerable advantage over newcomers like &lt;a href="https://phpfog.com/" target="_new" rel="external"&gt;PHP Fog&lt;/a&gt;, and &lt;a href="http://orchestra.io/" target="_new" rel="external"&gt;Orchestra.io&lt;/a&gt; by avoiding mostly separate, language-specific products.&lt;/p&gt;

&lt;p&gt;To test out Heroku's PHP support (version 5.3.6), I deployed WordPress. One of the current limitations is the lack of native MySQL support, outside of hooking into the &lt;a href="http://xeround.com/" target="_new" rel="external"&gt;Xeround Cloud DB&lt;/a&gt; or &lt;a href="http://aws.amazon.com/rds/" target="_new" rel="external"&gt;Amazon RDS&lt;/a&gt;. I've found one blog post that suggested using the default PostgreSQL backend that Heroku provides with the 'PG4WP' WordPress plugin, enabling WordPress to be used with a PostgreSQL database. While this may work, it lacks most plugin support and is more of a bandaid for the platform limitations. Instead, you can use Amazon's Relational Database Service (RDS) addon.&lt;/p&gt;

&lt;p&gt;Amazon RDS is a service that allows you to set up, operate and scale a dedicated MySQL database server on top of EC2. In addition to standard MySQL features, RDS offers the following functionality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated backups&lt;/li&gt;
&lt;li&gt;Point-in-time recovery&lt;/li&gt;
&lt;li&gt;Seamless vertical scaling between instance types&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The free Amazon RDS add-on lets you connect your Heroku app to an RDS instance and seamlessly use it in place of the standard, Heroku-provided PostgreSQL database. To get started, you should configure the RDS &lt;a href="http://docs.amazonwebservices.com/AmazonRDS/latest/CommandLineReference/" target="_new" rel="external"&gt;command line toolkit&lt;/a&gt; and &lt;a href="http://devcenter.heroku.com/articles/heroku-command" target="_new" rel="external"&gt;Heroku gem&lt;/a&gt; if you haven't already. Let's start by creating the RDS database instance on your local machine:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rds-create-db-instance --db-instance-identifier &lt;span class="o"&gt;[&lt;/span&gt;name&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
  --allocated-storage 5 &lt;span class="se"&gt;\&lt;/span&gt;
  --db-instance-class db.m1.small  &lt;span class="se"&gt;\&lt;/span&gt;
  --engine MySQL5.1 &lt;span class="se"&gt;\&lt;/span&gt;
  --master-username &lt;span class="o"&gt;[&lt;/span&gt;user&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  --master-user-password &lt;span class="o"&gt;[&lt;/span&gt;pw&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  --db-name &lt;span class="o"&gt;[&lt;/span&gt;name&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  --headers
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This will take a few minutes. Once the database is provisioned, add your local IP address to the security group -- assuming your workstation’s public IP is 1.1.1.1:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rds-authorize-db-security-group-ingress default --cidr-ip 1.1.1.1/32
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Heroku also needs to be able to access your RDS instance. To allow Heroku’s cloud through the RDS firewall, run the following command:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rds-authorize-db-security-group-ingress default &lt;span class="se"&gt;\&lt;/span&gt;
    --ec2-security-group-name default &lt;span class="se"&gt;\&lt;/span&gt;
    --ec2-security-group-owner-id 098166147350
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now we can begin building the application layer. Since we're going to be using Git for version control, I'd suggest cloning WordPress from Mark Jaquith's &lt;a href="https://github.com/markjaquith/WordPress" target="_new"&gt;GitHub&lt;/a&gt; repository; it is synced from Automattic's SVN repository every 30 minutes, including branches and tags:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git clone git://github.com/markjaquith/WordPress.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WordPress
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Before we start making any changes to file structure, we should make our own Git repository and start committing. Note here that you'll want to populate the wp-config.php with the MySQL credentials from the &lt;code&gt;rds-create-db-instance&lt;/code&gt; command above:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;git init
mv wp-config-sample.php wp-config.php
git add .
git commit -m &lt;span class="s1"&gt;&amp;#39;initial commit&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, create the stack and enable the RDS addon with your MySQL credentials. Once the stack has been created, you can deploy:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;heroku create --stack cedar
heroku addons:add amazon_rds &lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysql://user:pass@rdshostname.amazonaws.com/databasename
git push heroku master
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The output should look something like this:&lt;/p&gt;

&lt;pre class="terminal"&gt;
➜ wp-heroku-test git:(master) git push heroku master
Counting objects: 985, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (965/965), done.
Writing objects: 100% (985/985), 3.65 MiB | 221 KiB/s, done.
Total 985 (delta 66), reused 0 (delta 0)

-----&gt; Heroku receiving push
-----&gt; PHP app detected
-----&gt; Bundling Apache v2.2.19
-----&gt; Bundling PHP v5.3.6
-----&gt; Discovering process types
       Procfile declares types -&gt; (none)
       Default types for PHP   -&gt; web
-----&gt; Compiled slug size is 24.9MB
-----&gt; Launching... done, v4
       http://evening-waterfall-3372.herokuapp.com deployed to Heroku

To git@heroku.com:evening-waterfall-3977.git
 * [new branch]      master -&gt; master
&lt;/pre&gt;




&lt;h4&gt;Notes&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A commenter on HackerNews noted that the slug is still read-only, but the ephemeral filesystem is writable. The slug is what gets deployed on each new dyno spawned. The ephemeral filesystem is the individual file system on each dyno. So a plugin like WP Super Cache would be able to write to the file system, but that cache would only exist for the individual dyno that wrote it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because of the usage concerns of media and content uploads, I'd suggest using a CDN or Amazon S3 for storing images and attachments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The zlib extension for PHP is not compiled on the Celadon Cedar Stack. Theme and plugin uploads through the WordPress admin panel will fail. To get around this, set up your themes and plugins on your local workstation first, commit and deploy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not include a phpinfo page in the document root as it will contain your database credentials in plain text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you want to have pretty permalinks, create the .htaccess file on your local machine and populate the mod_rewrite rules prior to deploying.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Live Data Replication Using lsyncd</title>
   <link href="http://tjstein.com/2011/08/live-data-replication-using-lsyncd" />
   <updated>2011-08-29T00:00:00-07:00</updated>
   <id>http://tjstein.com/2011/08/live-data-replication-using-lsyncd</id>
   <content type="html">&lt;p&gt;One of my favorite Linux utilities I've discovered recently is &lt;a href="http://code.google.com/p/lsyncd/" title="lsyncd - Live Syncing (Mirror) Daemon" rel="external"&gt;lsyncd&lt;/a&gt;, a live syncing (mirror) daemon. Following the traditional Unix philosophy, it does data replication simply and it does it very well. Using some fancy inotify magic, lsyncd will spawn one or more processes to synchronize the targets after changes have been made.&lt;/p&gt;

&lt;p&gt;After determining that a client would need multiple web-servers running in sync, I evaluated a few different tools that perform data replication and live syncing. This is one of the larger problems I've encountered with scaling web applications horizontally -- storage management among multiple web services. In traditional deployments, it might make sense to use something like NFS or even DRBD, operating on the block device level. While this works for write-heavy systems under high load, it isn't practical mirroring a whole block device for a high-traffic WordPress site -- I just needed a basic client-server model.&lt;/p&gt;

&lt;p&gt;This is where lsyncd really shines. The lsyncd configuration file is written in Lua and super easy to set up. Below is the &lt;code&gt;lsyncd.conf&lt;/code&gt; that duplicates &lt;code&gt;/var/www/tjstein.com&lt;/code&gt; on the master server to the 4 targets with the same path:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="lua"&gt;&lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;delay&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;maxProcesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;statusFile&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;/tmp/lsyncd.status&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;logfile&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;/var/log/lsyncd.log&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;targetlist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;10.0.1.23:/var/www/tjstein.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;10.0.1.24:/var/www/tjstein.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;10.0.1.25:/var/www/tjstein.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;10.0.1.26:/var/www/tjstein.com&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;ipairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetlist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rsync&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;/var/www/tjstein.com&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rsyncOpts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="s"&gt;-rltvupgo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To make the rsyncing seamless, you'll need to send the public key generated on the master server to all of the duplicated nodes for easy access. With the client I was working with, we were also using Nginx to load balance across the web nodes. Since we only wanted writes going to the primary master server, we redirected all requests to /wp-admin to the primary node. Then, any changes made through the WordPress backend were synced over to the targets in less than 1 second. Here is the Nginx configuration:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="s"&gt;.0.1.20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;#master&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="s"&gt;.0.1.21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;#www-01&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="s"&gt;.0.1.22&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;#www-02&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="s"&gt;.0.1.23&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;#www-03&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="s"&gt;.0.1.20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.tjstein.com&lt;/span&gt; &lt;span class="s"&gt;tjstein.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt;  &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/wp-admin/*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt;  &lt;span class="s"&gt;http://admin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h4&gt;Notes&lt;/h4&gt;


&lt;p&gt;You'll want to install lsyncd from source on most distributions. Older versions (pre 2.x) contained gross XML style configuration; the most recent version, as of 8/30/2011, is 2.0.5.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>APC Cache Purge Plugin for WordPress</title>
   <link href="http://tjstein.com/2011/08/apc-cache-purge-plugin-for-wordpress" />
   <updated>2011-08-23T00:00:00-07:00</updated>
   <id>http://tjstein.com/2011/08/apc-cache-purge-plugin-for-wordpress</id>
   <content type="html">&lt;p&gt;After a recent WordPress update, I noticed that the admin panel did not correctly reflect the new version as indicated in the footer of the backend panel. I realized that the &lt;a href="http://php.net/manual/en/book.apc.php" title="APC" target="_new"&gt;APC opcode cache&lt;/a&gt; was not flushed and therefore held on to cached versions of many updated files. I thought about what other ways this cache could be flushed without restarting the web server or PHP daemon (PHP-FPM) without compromising service availability.&lt;/p&gt;

&lt;p&gt;Some subsequent googling later, I found a &lt;a href="http://konstruktors.com/blog/wordpress/2382-clear-apc-cache-button-for-wordpress/
" title="‘Clear APC Cache’ Button for WordPress" target="_new"&gt;dirty hack&lt;/a&gt; that, although helpful, was somewhat limited by design -- it suggests adding the script to the functions.php file of your theme. This means you'd need to manually insert the code for each theme. Also, &lt;code&gt;apc_clear_cache()&lt;/code&gt; did not work by default with APC version 3.1.3p1. From this, I created a simple, single purpose WordPress plugin to flush the APC cache.&lt;/p&gt;

&lt;p&gt;Once activated, you'll get a 'Purge APC' option under the tools menu. Once the option is clicked, the APC cache is flushed and the entries are displayed on the page:&lt;/p&gt;

&lt;p&gt;Feel free to fork or submit pull requests to the &lt;a href="https://github.com/bummercloud/apc-cache-purge" title="GitHub" target="_new"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="sd"&gt;/**&lt;/span&gt;
&lt;span class="sd"&gt; * @package APC Cache Purge&lt;/span&gt;
&lt;span class="sd"&gt; * @version 0.1&lt;/span&gt;
&lt;span class="sd"&gt; */&lt;/span&gt;
&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt;Plugin Name: APC Cache Purge&lt;/span&gt;
&lt;span class="cm"&gt;Plugin URI: http://tjstein.com&lt;/span&gt;
&lt;span class="cm"&gt;Description: This is a simple, single purpose plugin to flush the APC cache.&lt;/span&gt;
&lt;span class="cm"&gt;Author: TJ Stein, inspired by Kaspars Dambis of konstruktors.com&lt;/span&gt;
&lt;span class="cm"&gt;Version: 0.1&lt;/span&gt;
&lt;span class="cm"&gt;Author URI: http://tjstein.com&lt;/span&gt;
&lt;span class="cm"&gt;License: GPLv2&lt;/span&gt;
&lt;span class="cm"&gt;*/&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;apc_purge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;apc_clear_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;opcode&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Add Purge APC menu under Tools menu&lt;/span&gt;
&lt;span class="nx"&gt;add_action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;admin_menu&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;php_apc_info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;php_apc_info&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;add_submenu_page&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tools.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Purge APC&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Purge APC&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;activate_plugins&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;flush_php_apc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;php_apc_options&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
        
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;php_apc_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apc_purge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;apc_purge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;p&amp;gt;Success!&amp;lt;/p&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;p&amp;gt;Clearing Failed!&amp;lt;/p&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;pre&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;print_r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apc_cache_info&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;/pre&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Add Purge APC in the favorite actions dropdown&lt;/span&gt;
&lt;span class="nx"&gt;add_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;favorite_actions&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;clear_apc_link&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;clear_apc_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$actions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$actions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tools.php?page=flush_php_apc&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Purge APC&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;edit_posts&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;h4&gt;Installation&lt;/h4&gt;


&lt;ul&gt;
&lt;li&gt;Upload &lt;code&gt;apc-cache-purge.php&lt;/code&gt; to the &lt;code&gt;/wp-content/plugins/&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;Activate the plugin through the ‘Plugins’ menu in WordPress&lt;/li&gt;
&lt;li&gt;When needed, flush the cache by clicking on ‘Purge APC’ under the Tools section&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Alsatian Darn</title>
   <link href="http://tjstein.com/2011/04/alsatian-darn" />
   <updated>2011-04-22T00:00:00-07:00</updated>
   <id>http://tjstein.com/2011/04/alsatian-darn</id>
   <content type="html">&lt;p&gt;"Alsatian Darn" from the album "Tomboy" (2011) performed by Panda Bear.&lt;/p&gt;

&lt;div class="video"&gt;&lt;object width="596" height="360"&gt;&lt;param name="movie" value="http://www.youtube.com/v/MyygB6nWbvY?fs=1&amp;amp;hl=en_US&amp;amp;rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/MyygB6nWbvY?fs=1&amp;amp;hl=en_US&amp;amp;rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="610" height="360"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;


&lt;br&gt;

</content>
 </entry>
 
 <entry>
   <title>Classy Web Development with Sinatra and Heroku</title>
   <link href="http://tjstein.com/2011/04/classy-web-development-with-sinatra-and-heroku" />
   <updated>2011-04-01T00:00:00-07:00</updated>
   <id>http://tjstein.com/2011/04/classy-web-development-with-sinatra-and-heroku</id>
   <content type="html">&lt;p&gt;&lt;img src="/images/sinatra.gif" class="alignleft"&gt;Since my recent switch from WordPress to Jekyll, I've really enjoyed playing around with Ruby. Although I don't have much programming experience, I've been fascinated with one particular Ruby framework, &lt;a href="http://www.sinatrarb.com/" rel="external" target="_blank"&gt;Sinatra&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sinatra is a DSL (domain-specific language) for quickly creating web applications in Ruby with very little effort. It is a minimalist framework, built right on top of &lt;a href="http://rack.rubyforge.org/" rel="external" target="_blank"&gt;Rack&lt;/a&gt;, a standard interface for Ruby web frameworks. Unlike rails, you won't find many bells and whistles here. There are no models, views or controllers by default, but that's where Sinatra really shines. You can use Sinatra to create lean, focused web applications in just a few lines of code.&lt;/p&gt;

&lt;p&gt;So this morning, I published a Sinatra &lt;a href="https://github.com/bummercloud/sinatra-heroku-template"&gt;template&lt;/a&gt; for Heroku with Haml, Sass &amp;amp; jQuery. The repository includes a base HTML 5 template for Sinatra, ready for Heroku deployment. Use &lt;code&gt;bundle install&lt;/code&gt; to grab all of the gem dependencies. If you get lost during deployment, check out &lt;a href="http://devcenter.heroku.com/articles/quickstart"&gt;Getting Started with Heroku&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the fun parts of the project was using Haml in place of erb. I'm still pulling up the Haml reference here and there but it's a breeze to work with. Here is an example of the layout page:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="haml"&gt;&lt;span class="nn"&gt;!!! 5&lt;/span&gt;
&lt;span class="nt"&gt;%html&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;html_attrs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;en-en&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
  &lt;span class="nt"&gt;%head&lt;/span&gt;
    &lt;span class="nt"&gt;%meta&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:&amp;#39;http-equiv&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;text/html; charset=utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;%meta&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;lang&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:content&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;%title&lt;/span&gt; Sinatra Template for Heroku w/ Haml, Sass &amp;amp; jQuery | TJ Stein
    &lt;span class="nt"&gt;%link&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:href&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;assets/css/style.css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:rel&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;text/css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}/&lt;/span&gt;
  &lt;span class="nt"&gt;%body&lt;/span&gt;
    &lt;span class="nc"&gt;.container&lt;/span&gt;
    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;haml&lt;/span&gt; &lt;span class="ss"&gt;:analytics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:layout&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The actual application file doesn't have much in it. It loads the required gems, builds the routes including the Sass support. You can add or modify any of the routes to create new pages or functions:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sinatra&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;haml&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sass&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="ss"&gt;:haml&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:format&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:html5&lt;/span&gt;

&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;haml&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/:path&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;haml&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;to_sym&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/style.css&amp;#39;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;text/css&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:charset&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;
  &lt;span class="n"&gt;scss&lt;/span&gt; &lt;span class="ss"&gt;:style&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you prefer using a Rakefile to deploy, I've included an example Rakefile with a rake task for deployment to Heroku using &lt;code&gt;rake deploy&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="ruby"&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rake&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Deploy to Heroku.&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
   &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;heroku&amp;#39;&lt;/span&gt;
   &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;heroku/command&amp;#39;&lt;/span&gt;
   &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;~/.heroku/credentials&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Heroku&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;BaseWithApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;remotes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;git_remotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/../..&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="n"&gt;remote&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;remotes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;detect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;APP&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;remote&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nil?&lt;/span&gt;
   &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Could not find a git remote for the &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;APP&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; app&amp;quot;&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;

   &lt;span class="sb"&gt;`git push &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;remote&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; master`&lt;/span&gt;

   &lt;span class="n"&gt;heroku&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you end up using the template in your own application or want to contribute, send a pull request or just fork the project. Keep it classy.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Mounting S3 Buckets Using FUSE</title>
   <link href="http://tjstein.com/2011/02/mounting-s3-buckets-using-fuse" />
   <updated>2011-02-22T00:00:00-08:00</updated>
   <id>http://tjstein.com/2011/02/mounting-s3-buckets-using-fuse</id>
   <content type="html">&lt;p&gt;Over the past few days, I've been playing around with &lt;a href="http://fuse.sourceforge.net/" rel="external"&gt;FUSE&lt;/a&gt; and a FUSE-based filesystem backed by Amazon S3, &lt;a href="http://code.google.com/p/s3fs/" rel="external"&gt;s3fs&lt;/a&gt;. Until recently, I've had a negative perception of FUSE that was pretty unfair, partly based on some of the lousy FUSE-based projects I had come across. I'm sure some of it also comes down to some partial ignorance on my part for not fully understanding what FUSE is and how it works.&lt;/p&gt;

&lt;h4&gt;What is FUSE?&lt;/h4&gt;


&lt;p&gt;FUSE is a loadable kernel module that lets you develop a user space filesystem framework without understanding filesystem internals or learning kernel module programming. This basically lets you develop a filesystem as executable binaries that are linked to the FUSE libraries. So, if you're not comfortable hacking on kernel code, FUSE might be a good option for you.&lt;/p&gt;

&lt;h4&gt;FUSE + Amazon S3&lt;/h4&gt;


&lt;p&gt;So, now that we have a basic understanding of FUSE, we can use this to extend the cloud-based storage service, S3. Using a tool like s3fs, you can now mount buckets to your local filesystem without much hassle. Although your reasons may vary for doing this, a few good scenarios come to mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your server is running low on disk space and you want to expand&lt;/li&gt;
&lt;li&gt;You want to give multiple servers read/write access to a single filesystem&lt;/li&gt;
&lt;li&gt;You want to access off-site backups on your local filesystem without ssh/rsync/ftp&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;To get started, we'll need to install some prerequisites. I've set this up successfully on Ubuntu 10.04 and 10.10 without any issues:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;aptitude -y install build-essential libfuse-dev fuse-utils libcurl4-openssl-dev 
aptitude -y libxml2-dev mime-support pkg-config
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now you'll need to download and compile the s3fs source. As of 2/22/2011, the most recent release, supporting reduced redundancy storage, is 1.40. Check out the &lt;a href="http://code.google.com/p/s3fs/downloads/list" rel="external"&gt;Google Code&lt;/a&gt; page to be certain you're grabbing the most recent release.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/local/src
wget http://s3fs.googlecode.com/files/s3fs-1.40.tar.gz
tar zxvf s3fs-1.40.tar.gz &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;s3fs-1.40
./configure
make &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make install
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This will install the s3fs binary in &lt;code&gt;/usr/local/bin/s3fs&lt;/code&gt;. You can add it to your .bashrc if needed:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;export s3fs=&amp;#39;/usr/local/bin/s3fs&amp;#39;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now we have to set the &lt;code&gt;allow_other mount&lt;/code&gt; option for FUSE. Using the &lt;code&gt;allow_other mount&lt;/code&gt; option works fine as root, but in order to have it work as other users, you need uncomment &lt;code&gt;user_allow_other&lt;/code&gt; in the fuse configuration file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="perl"&gt;&lt;span class="n"&gt;perl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;s|#user_allow_other|user_allow_other|g;&amp;#39;&lt;/span&gt; &lt;span class="sr"&gt;/etc/&lt;/span&gt;&lt;span class="n"&gt;fuse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To make sure the s3fs binary is working, run the following:&lt;/p&gt;

&lt;pre class="terminal"&gt;
root@tjstein.com:~# s3fs
s3fs: missing BUCKET argument
Usage: s3fs BUCKET MOUNTPOINT [OPTION]...
&lt;/pre&gt;


&lt;p&gt;So before you can mount the bucket to your local filesystem, create the bucket in the AWS control panel or using a CLI toolset like &lt;a href="http://s3tools.org" rel="external"&gt;s3cmd&lt;/a&gt;. Then, create the mount directory on your local machine before mounting the bucket:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;s3cmd mb s3://bucketname
mkdir -p /mnt/s3
s3fs bucketname -o &lt;span class="nv"&gt;use_cache&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp -o allow_other /mnt/s3
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To allow access to the bucket, you must authenticate using your AWS secret access key and access key. You can either add the credentials in the s3fs command using flags or use a password file. Depending on what version of s3fs you are using, the location of the password file may differ -- it will most likely reside in your user's home directory or /etc.&lt;/p&gt;

&lt;p&gt;I also suggest using the &lt;code&gt;use_cache&lt;/code&gt; option. If enabled, s3fs automatically maintains a local cache of files in the folder specified by &lt;code&gt;use_cache&lt;/code&gt;. Whenever s3fs needs to read or write a file on S3, it first downloads the entire file locally to the folder specified by &lt;code&gt;use_cache&lt;/code&gt; and operates on it. When FUSE release() is called, s3fs will re-upload the file to s3 if it has been changed, using md5 checksums to minimize transfers from S3.&lt;/p&gt;

&lt;p&gt;To confirm the mount, run &lt;code&gt;mount -l&lt;/code&gt; and look for /mnt/s3.&lt;/p&gt;

&lt;h4&gt;Notes&lt;/h4&gt;


&lt;p&gt;While this method is easy to implement, there are some caveats to be aware of.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Because of the distributed nature of S3, you may experience some propagation delay. So, after the creation of a file, it may not be immediately available for any subsequent file operation. To read more about the "eventual consistency", check out the following post from &lt;a href="http://shlomoswidler.com/2009/12/read-after-write-consistency-in-amazon.html" rel="external"&gt;shlomoswidler.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can't update part of an object on S3. If you want to update 1 byte of a 5GB object, you'll have to re-upload the entire object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The software documentation for s3fs is lacking, likely due to a commercial version being available now.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Minimum Viable Frameworks</title>
   <link href="http://tjstein.com/2011/02/minimum-viable-frameworks" />
   <updated>2011-02-18T00:00:00-08:00</updated>
   <id>http://tjstein.com/2011/02/minimum-viable-frameworks</id>
   <content type="html">&lt;p&gt;During the process of redesigning my personal blog, I evaluated several pieces of software including &lt;a href="http://jekyllrb.com/" rel="external"&gt;Jekyll&lt;/a&gt;, &lt;a href="http://flask.pocoo.org" rel="external"&gt;Flask&lt;/a&gt; (a Python micro-framework) and &lt;a href="http://cloudhead.io/toto" rel="external"&gt;Toto&lt;/a&gt; among a few others. I decided to go with Jekyll as it seemed to meet most of my requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No database; posts are stored in plain text, markdown or some other equivalent&lt;/li&gt;
&lt;li&gt;No server-side language requirements&lt;/li&gt;
&lt;li&gt;Can integrate easily with Git&lt;/li&gt;
&lt;li&gt;Can be themed and extended&lt;/li&gt;
&lt;li&gt;Has well-written documentation and good community adoption&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Since the redesign, I've really embraced this type of site-building platform and I think many others are starting to see it's appeal. The popularity of these micro-frameworks has grown tremendously over the last year or two. I've read numerous blog posts from users leaving larger CMS-based blogging platforms like WordPress in favor of more minimalist, git-powered projects. Their reasons for switching vary, but one common theme is apparent: &lt;strong&gt;It's simple.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;blockquote&gt;&lt;p&gt;"I really wanted something simpler than WordPress. I didn’t need a CMS. I barely need a blogging engine. I update so infrequently. I want something that creates well formed html (hah), static content and is easy to use."&lt;/p&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="http://www.nata2.org/2010/08/17/jekyl-for-the-win/" rel="external"&gt;Harper Reed&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A few web service providers are also catching on, offering extremely affordable (and sometimes free) hosting. Amazon &lt;a href="http://aws.typepad.com/aws/2011/02/host-your-static-website-on-amazon-s3.html" rel="external"&gt;recently announced&lt;/a&gt; the availability of website hosting on S3, their storage service. Heroku has offered a free, albeit somewhat diminutive, tier for rapid-prototyping, staging, and testing purposes, as well as actually running lightweight apps. &lt;a href="http://code.google.com/appengine/" rel="external"&gt;Google App Engine&lt;/a&gt; also offers cloud-based solutions, which can be pushed further with tools like &lt;a href="http://drydrop.binaryage.com/" rel="external"&gt;DryDrop&lt;/a&gt;. DryDrop enables you to host your static site on Google App Engine and update it by pushing to GitHub. That's pretty rad.&lt;/p&gt;

&lt;p&gt;If you're looking into micro-frameworks, check out the following articles for more information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://fadeyev.net/2010/05/10/getting-started-with-toto/" rel="external"&gt;
Getting Started With Toto, a Tiny WordPress Killer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://paulstamatiou.com/how-to-wordpress-to-jekyll" rel="external"&gt;How To: WordPress to Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://openfoo.org/blog/jekyll-s3.html" rel="external"&gt;Jekyll with Amazon S3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html" rel="external"&gt;Blogging Like a Hacker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nestacms.com/"&gt;Nesta: A Ruby CMS. Built with Sinatra.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Helplessness Blues</title>
   <link href="http://tjstein.com/2011/01/helplessness-blues" />
   <updated>2011-01-31T00:00:00-08:00</updated>
   <id>http://tjstein.com/2011/01/helplessness-blues</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;"What's my name, what's my station. Oh just tell me what I should do. I don't need to be kind to the armies of night. That would do such injustice to you."&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: &lt;a href="http://fleetfoxes.com/helplessness-blues.html" rel="external" target="_blank"&gt;Fleet Foxes | Helplessness Blues&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using WebFont Loader</title>
   <link href="http://tjstein.com/2011/01/using-webfont-loader" />
   <updated>2011-01-22T00:00:00-08:00</updated>
   <id>http://tjstein.com/2011/01/using-webfont-loader</id>
   <content type="html">&lt;p&gt;In the process of designing this site, I decided to use some custom fonts using the @font-face CSS attribute. In comparison to some of the other web font options (Cufon, sIFR, FLIR), the @font-face CSS method is simple, easy to implement and well supported in most modern browsers. Although the &lt;a href="http://code.google.com/apis/webfonts/" title="Google Font API" rel="external"&gt;Google Font API&lt;/a&gt; is probably the most well-known web font library, I decided to roll my own kit from Font Squirrel and self-host the fonts. The really nice part about &lt;a href="http://www.fontsquirrel.com/" title="Font Squirrel" rel="external"&gt;Font Squirrel&lt;/a&gt; is that they provide all of the different font formats (TTF, EOT, OTF, and SVG), compatible with every browser on the market.&lt;/p&gt;

&lt;p&gt;For all of my H1-H6 headings, I use the following markup:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;YanoneKaffeesatzRegular&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;YanoneKaffeesatz-Regular-webfont.eot&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;local&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;☺&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/fonts/YanoneKaffeesatz-Regular-webfont.woff&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;woff&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/fonts/YanoneKaffeesatz-Regular-webfont.ttf&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;truetype&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/fonts/YanoneKaffeesatz-Regular-webfont.svg#webfont1BSMunJa&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;svg&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nt"&gt;font-weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;normal&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nt"&gt;font-style&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;normal&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I then load the font in like I would any other family:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h6&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;YanoneKaffeesatzRegular&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Everything looked great besides one small, yet extremely annoying, caveat.&lt;/p&gt;

&lt;p&gt;I noticed in Firefox and Opera that for a split second, just before the page finished rendering, unstyled text would be displayed. This drove me crazy. Some subsequent Googling let me know that this was common, often referred to as FOUT (Flash of Unstyled Text). The fix was pretty trivial. What you can do is use the WebFont Loader from Google &amp;amp; Typekit.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://code.google.com/apis/webfonts/docs/webfont_loader.html" title="WebFont Loader - Google Font API - Google Code" rel="external"&gt;WebFont Loader&lt;/a&gt; is a JavaScript library that gives you more control over font loading than the Google Font API provides. The key is using the events system to hide the font until it's ready to be shown. There are quite a few implementation options so I'd suggest checking out some of the following articles for help:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://24ways.org/2010/using-the-webfont-loader-to-make-browsers-behave-the-same" title="Using the WebFont Loader to Make Browsers Behave the Same" rel="external"&gt;Using the WebFont Loader to Make Browsers Behave the Same&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://sixrevisions.com/css/font-face-guide/" title="The Essential Guide to @font-face" rel="external"&gt;The Essential Guide to @font-face&lt;/a&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;a href="http://code.google.com/apis/webfonts/docs/webfont_loader.html" title="WebFont Loader - Google Font API - Google Code" rel="external"&gt;WebFont Loader - Google Font API - Google Code&lt;/a&gt;
    &lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you see a horizontal scroll-bar after implementing the WebFont Loader on body text, try adding overflow attributes:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="css"&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DroidSansRegular&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;overflow&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;moz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;scrollbars&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;vertical&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;overflow-x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;overflow-y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;scroll&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>WordCamp LA</title>
   <link href="http://tjstein.com/2011/01/wordcamp-la" />
   <updated>2011-01-18T00:00:00-08:00</updated>
   <id>http://tjstein.com/2011/01/wordcamp-la</id>
   <content type="html">&lt;p&gt;In September of last year, I was invited to speak at &lt;a href="http://2010.wordcamp.la/" target="_blank" rel="external"&gt;WordCamp LA&lt;/a&gt; on developing fast and scalable servers for WordPress. During the 30 or so minute presentation, I covered quite a few topics. I strayed away from the application layer side of things and really focused on server improvements and software considerations that offered the most performance. I got some really nice feedback and met some great people involved with WordPress in the LA area. The two other WordCamps I attended before (New York and their flagship conference, San Francisco) were extremely well organized and WordCamp LA was no different.&lt;/p&gt;

&lt;p&gt;Although I wasn't able to post my slides, I've posted the video here. I look forward to speaking at more events like this and I highly recommend attending a WordCamp event if one comes into your town.&lt;/p&gt;

&lt;div class="video"&gt;&lt;embed type="application/x-shockwave-flash" src="http://s0.videopress.com/player.swf?v=1.02" width="605" height="340" wmode="transparent" seamlesstabbing="true" allowfullscreen="true" allowscriptaccess="always" overstretch="true" flashvars="guid=lIU6iZt4" /&gt;&lt;/div&gt;


&lt;br&gt;

</content>
 </entry>
 
 <entry>
   <title>A Response To Quality</title>
   <link href="http://tjstein.com/2011/01/a-response-to-quality" />
   <updated>2011-01-15T00:00:00-08:00</updated>
   <id>http://tjstein.com/2011/01/a-response-to-quality</id>
   <content type="html">&lt;blockquote&gt;&lt;p&gt;"Doing things the right way is hard, which is why most businesses take the lazy path and settle for mediocrity. People respond to quality, though: they reward it, in no small part because quality is such a rarity in today’s marketplace. Do right by your customers and they’ll do right by you."&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: &lt;a href="http://al3x.net/2011/01/15/user-hostile-platforms.html" rel="external" target="_blank"&gt;Shortchanging Your Business with User-Hostile Platforms&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PHP-FPM Plugin Suite For Munin</title>
   <link href="http://tjstein.com/2010/09/php-fpm-plugin-suite-for-munin" />
   <updated>2010-09-25T00:00:00-07:00</updated>
   <id>http://tjstein.com/2010/09/php-fpm-plugin-suite-for-munin</id>
   <content type="html">&lt;p&gt;Since switching from a spawn-fcgi implementation several months ago, I’ve been really pleased with PHP-FPM. Given some of the new statistical features included in newer versions (5.3.2+), I put together a plugin suite for Munin. I am not proficient in Perl so I encourage feedback and suggestions to make these better. This suite contains plugins to measure average process size, total memory usage, connection count, process count and most importantly, pool status.&lt;/p&gt;

&lt;p&gt;Before installing, make sure you have the most recent version of PHP-FPM:&lt;/p&gt;

&lt;pre class="terminal"&gt;
[www-data@lenny:/var/www]# php-fpm -v
PHP 5.3.2-1ubuntu4.5ppa5~lucid1 (fpm-fcgi) (built: Sep 22 2010 08:04:01)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
    with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH
&lt;/pre&gt;


&lt;p&gt;Now we can get into our plugin directory, clone the plugins from my Git repo and make them executable:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/share/munin/plugins
git clone git://github.com/tjstein/php5-fpm-munin-plugins.git
chmod +x PHP5-FPM-Munin-Plugins/phpfpm_*
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To enable the plugins, you’ll need to create these symlinks:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_average /etc/munin/plugins/phpfpm_average
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_connections /etc/munin/plugins/phpfpm_connections
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_memory /etc/munin/plugins/phpfpm_memory
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_status /etc/munin/plugins/phpfpm_status
ln -s /usr/share/munin/plugins/PHP5-FPM-Munin-Plugins/phpfpm_processes /etc/munin/plugins/phpfpm_processes
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For the phpfpm_status and phpfpm_connections  plugins, you’ll need to enable the status feature included in newer versions (5.3.2+) of PHP-FPM. Open up the php5-fpm.conf, in /etc/php5/fpm, and uncomment line 186 for the pm.status_path directive:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;pm.status_path &lt;span class="o"&gt;=&lt;/span&gt; /status
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Jérôme Loyet from the Nginx forums provided some useful insight on how to get this working with Nginx. You’ll essentially set up the status location directive like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/(status|ping)$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;SCRIPT_FILENAME&lt;/span&gt; &lt;span class="nv"&gt;$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;allow&lt;/span&gt; &lt;span class="mi"&gt;127&lt;/span&gt;&lt;span class="s"&gt;.0.0.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;allow&lt;/span&gt; &lt;span class="s"&gt;stats_collector.localdomain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;allow&lt;/span&gt; &lt;span class="s"&gt;watchdog.localdomain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;deny&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You’ll need to make sure that from within your box, you can curl /status with # curl http://localhost/status. You should get a response similar to this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;accepted conn: 40163
pool: www
process manager: dynamic
idle processes: 6
active processes: 0
total processes: 6
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Once the plugins have been set up, you run any of the plugins manually using the munin-run command line tool:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/munin/plugins &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; munin-run phpfpm_status
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The output should look like this:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;idle.value 6
active.value 0
total.value 6
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The phpfpm_status plugin is particularly useful if you’re using dynamic process management. You can choose static or dynamic in the php5-fpm.conf.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;: libwww-perl&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails 3.0 with RVM, Nginx and Phusion Passenger</title>
   <link href="http://tjstein.com/2010/09/rails-3-with-rvm-nginx-passenger" />
   <updated>2010-09-14T00:00:00-07:00</updated>
   <id>http://tjstein.com/2010/09/rails-3-with-rvm-nginx-passenger</id>
   <content type="html">&lt;p&gt;Rails 3.0 is ponies and rainbows! Well, kinda. I've never been into Rails much but 3.0 has brought on some much needed features over previous versions, some of which deserve bullet points:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Brand new router with an emphasis on RESTful declarations&lt;/li&gt;
    &lt;li&gt;Unobtrusive JavaScript helpers with drivers for Prototype, jQuery,  and more coming (end of inline JS)&lt;/li&gt;
    &lt;li&gt;Explicit dependency management with &lt;a href="http://gembundler.com/" target="_blank"&gt;Bundler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The newest version of Rails came out on August 29 so I decided to jump right in. Since Ruby 1.8.6 and earlier are no longer supported, we'll be using RVM in this article. &lt;a href="http://rvm.beginrescueend.com/" target="_blank"&gt;RVM&lt;/a&gt; is a command line tool which allows us to easily install, manage and  work with multiple ruby environments from interpreters to sets of gems.&lt;/p&gt;

&lt;p&gt;Before we get started, we'll be using a fresh (ve) Server from &lt;a href="http://mediatemple.net/" target="_blank"&gt;(mt) Media Temple&lt;/a&gt; running Ubuntu 10.04 Lucid Lynx for the install. I should also note that we're not installing a full-featured application -- this is simply a tutorial on how to get the Rails 3.0 test application up and running with Nginx + Passenger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;: You'll need these to get through the entire install process for RVM, Nginx and &lt;a href="http://www.modrails.com/"&gt;Phusion Passenger&lt;/a&gt; (mod_rails).&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;aptitude -y install curl git-core build-essential zlib1g-dev libssl-dev
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;aptitude -y install libreadline5-dev libc6 libpcre3 libssl0.9.8 zlib1g
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now we'll need to do a system-wide install of RVM. For your convenience, the dude that wrote RVM provided a script you can run on most that does all the heavy lifting:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;bash &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt; curl -L http://bit.ly/rvm-install-system-wide &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Every piece of documentation and website I read on this had this particular part wrong. I've updated the correct path from the documentation for the purposes of this article:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;[[ -s &amp;#39;/usr/local/lib/rvm&amp;#39; ]] &amp;amp;&amp;amp; source &amp;#39;/usr/local/lib/rvm&amp;#39;&amp;quot;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Doing so ensures RVM is loaded as a function (versus as a binary), ensuring commands such as &lt;em&gt;rvm use&lt;/em&gt; work as expected. Please note that you can confirm this worked correctly by opening a new shell and running:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;type &lt;/span&gt;rvm | head -n1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If this was performed correctly, you should see:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rvm is a &lt;span class="k"&gt;function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So if that looks good, we can continue installing Ruby:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rvm install 1.9.2
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now sit back and relax. This took about 8 minutes on my system. To make sure that the system uses this version, we can use RVM for this and install the rails and passenger gems:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rvm --default ruby-1.9.2
gem install rails passenger
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now comes the fun part of installing Nginx. This will grab the stable binary, bake in Phusion Passenger and compile it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;rvmsudo passenger-install-nginx-module
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You will be presented with two options right from the start. Just choose Option 1 and let passenger download, compile and install Nginx for you. You'll also be prompted to choose a prefix directory. You can leave it as the default, /opt/nginx. When it completes, it should give you some Nginx configuration snippets for your rails apps. Save those as you'll need them later.&lt;/p&gt;

&lt;p&gt;Now, you'll want a init script so you can stop/start/restart Nginx. I've provided mine here:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/init.d
wget -O nginx http://bit.ly/8XU8Vl
chmod +x nginx
/usr/sbin/update-rc.d -f nginx defaults
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;We're almost done. Now we can create the test application:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/nginx/html
rails new testapp
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You'll need to update the Nginx configuration to make sure it's using the right document root now. The file will be located in &lt;em&gt;/opt/nginx/conf/nginx.conf&lt;/em&gt;:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;sed -i&lt;span class="s2"&gt;&amp;quot;.bak&amp;quot;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;47d&amp;#39;&lt;/span&gt; /opt/nginx/conf/nginx.conf
sed -i &lt;span class="s1"&gt;&amp;#39;47 a\&lt;/span&gt;
&lt;span class="s1"&gt;            root   /opt/nginx/html/testapp/public;&amp;#39;&lt;/span&gt; /opt/nginx/conf/nginx.conf
/etc/init.d/nginx start
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The spacing looks a little weird in that middle sed command for a purpose -- to keep the syntax of the nginx.conf file consistent. Now that we've restarted Nginx, we should see the 'Welcome aboard: You're riding Ruby on Rails!' image:&lt;/p&gt;

&lt;p&gt;&lt;img title="You're riding Ruby on Rails!" src="/images/rails3.jpg" alt="You're riding Ruby on Rails!" width="567" height="271" /&gt;&lt;/p&gt;

&lt;p&gt;If you're interested in an all-in-one installation, I've put together the steps above into a &lt;a href="http://gist.github.com/raw/578736/0932236d03b18aff32361ec4718653c12b167209/rails3-nginx-passenger.sh" target="_blank"&gt;simple bash script&lt;/a&gt;. Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Wilco and Intelligentsia Mug</title>
   <link href="http://tjstein.com/2010/08/wilco-and-intelligentsia-mug" />
   <updated>2010-08-22T00:00:00-07:00</updated>
   <id>http://tjstein.com/2010/08/wilco-and-intelligentsia-mug</id>
   <content type="html">&lt;p&gt;I love Wilco. I also love Coffee. So when the coffee-connoisseurs &lt;a href="http://www.intelligentsiacoffee.com" target="_blank"&gt;Intelligentsia&lt;/a&gt; teamed up with Chicago-based band, Wilco, to offer an exclusive Wilco/Intelligentsia co-branded mug, an impulse purchase was made.&lt;/p&gt;

&lt;center&gt;&lt;img title="Wilco &amp;amp; Intelligentsia Mug" src="/images/wilco.jpg" alt="Wilco &amp;amp; Intelligentsia Mug" width="567" height="271" /&gt;&lt;/center&gt;


&lt;p&gt;If you're interested in purchasing one, head over to the Intelligentsia &lt;a href="http://www.intelligentsiacoffee.com/store/product/id/10949" target="_blank"&gt;store&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>APC Plugin For Munin</title>
   <link href="http://tjstein.com/2010/05/apc-plugin-for-munin" />
   <updated>2010-05-25T00:00:00-07:00</updated>
   <id>http://tjstein.com/2010/05/apc-plugin-for-munin</id>
   <content type="html">&lt;p&gt;If you're like me, you want to monitor and graph every little piece of your server. Until recently, I've been relying on a simple PHP script to display APC statistics. Although the tool worked well, I wanted to integrate the statistics into Munin, as most all other server properties and system services are monitoring with it. The problem was that finding a suitable APC plugin for Munin proved to be very difficult. Fortunately I stumbled across &lt;a href="http://geb.german-elite.net/blog.php?b=106" target="_new"&gt;this&lt;/a&gt; German gem (Vielen Dank, dass Sie  meine deutsche Freundin!) that met my needs. To set this up on your system, just follow the directions below:&lt;/p&gt;

&lt;p&gt;First, let's set up the apcinfo.php file in the document root of your web server and retrieve the file from a private gist:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/www/html
wget -O apcinfo.php http://goo.gl/Lgfmz
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, make the file executable:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;chmod +x apcinfo.php
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The script itself is very simple. It simply ouputs the total cache memory, memory available and memory used:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="php"&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$mem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apc_sma_info&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$mem_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mem&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;num_seg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;$mem&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;seg_size&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$mem_avail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mem&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;avail_mem&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$mem_used&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mem_size&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;$mem_avail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;size: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%.2f&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$mem_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;used: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%.2f&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$mem_used&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;free: &amp;#39;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%.2f&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$mem_avail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To confirm that the script is working, check out /apcinfo.php on your site. You should see something like the following:&lt;/p&gt;

&lt;blockquote&gt;size: 31457200.00 used: 19478104.00 free: 11979096.00&lt;/blockquote&gt;


&lt;p&gt;Now, let's set up the Munin plugin that will use that information:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /usr/share/munin/plugins
wget -O apc http://goo.gl/gUgkj 
chmod +x apc
ln -s /usr/share/munin/plugins/apc /etc/munin/plugins/apc
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;What that does is create the apc plugin, makes it executable and then symlinks it to the proper directory. Now, we'll need to make sure Munin loads the new plugin. To do this, we'll edit the &lt;em&gt;/etc/munin/plugin-conf.d/munin-node&lt;/em&gt; to add the following:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="o"&gt;[&lt;/span&gt;apc*&lt;span class="o"&gt;]&lt;/span&gt;
user root
env.url http://example.com/apcinfo.php
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Obviously, you'll want to replace example.com with the host you intend to use. Once the file has been updated and saved, restart Munin:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;/etc/init.d/munin-node restart
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Once the node is running, it'll take a few minutes for Munin to update so don't worry if you don't see any new graphs right away. One thing to keep in mind is that you will need the &lt;a href="http://search.cpan.org/~gaas/libwww-perl-5.836/lib/LWP/UserAgent.pm" target="_new"&gt;LWP::UserAgent&lt;/a&gt; Perl module. If you are on a Debian/Ubuntu OS, just run the following to install it:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;aptitude install libwww-perl
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, go check your pretty graphs.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Simple Load Balancing Using Nginx</title>
   <link href="http://tjstein.com/2010/04/simple-load-balancing-using-nginx" />
   <updated>2010-04-23T00:00:00-07:00</updated>
   <id>http://tjstein.com/2010/04/simple-load-balancing-using-nginx</id>
   <content type="html">&lt;p&gt;While the concept of load balancing has been around for a while, using Nginx to do this is fairly new to me. Other common load balancers in use today are &lt;a title="LVS" href="http://www.linuxvirtualserver.org/" target="_blank"&gt;LVS&lt;/a&gt;, &lt;a title="HAProxy" href="http://haproxy.1wt.eu/" target="_blank"&gt;HAProxy&lt;/a&gt;, &lt;a title="Perlbal" href="http://www.danga.com/perlbal/" target="_blank"&gt;Perlbal&lt;/a&gt; and &lt;a title="Pound" href="http://www.apsis.ch/pound/" target="_blank"&gt;Pound&lt;/a&gt;. In this example, I am using 3 &lt;a href="http://www.mediatemple.net/webhosting/ve/" target="_new"&gt;(ve) servers&lt;/a&gt; from Media Temple, each running on Ubuntu 9.10. To get started, log into the server you want to set up as the load balancer and install Nginx:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;aptitude install nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Then we'll need to make a new Nginx default virtual host, &lt;em&gt;/etc/nginx/sites-available/default&lt;/em&gt;. In the two server directives under the upstream backend section, be sure to put in the IP addresses or hosts you are balancing:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="s"&gt;.123.123.123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="s"&gt;.123.123.124&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt;  &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This is the simplest configuration possible. After you've completed the proxy configuration, test and restart Nginx:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;nginx -t
/etc/init.d/nginx restart
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;At this point, requests handled by the load balancer will serve equal requests from each upstream server. The really nice thing is that if one of the upstream servers is not responding, the load balancer will automagically stop routing requests to it. So although the configuration has the unavailable server loaded, Nginx sees that it is down and then routes to all other available upstream servers. If all upstreams are down, Nginx will halt the proxy, simply showing a 502 http error. This also makes it a very useful tool for balancing mongrels for those running rails.&lt;/p&gt;

&lt;p&gt;It's also worth noting that you can add as many backend nodes as you want; I'm just using two as an example. This makes using a (ve) server an ideal choice; spin up a new (ve) and simply add it to the upstream pool. There are a few other configuration options that provide the ability to add weight to backends to force an uneven load distribution. You can also use &lt;em&gt;proxy_set_header&lt;/em&gt; to make sure the user's IP address is logged instead of localhost:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="nginx"&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;john.tjstein.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;paul.tjstein.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;ringo.tjstein.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;george.tjstein.com&lt;/span&gt; &lt;span class="s"&gt;weight=30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# George was always my favorite&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.tjstein.com&lt;/span&gt; &lt;span class="s"&gt;tjstein.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt;  &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Nginx provides many other configuration directives so I would recommend checking the official Nginx documentation on the &lt;a href="http://wiki.nginx.org/NginxHttpUpstreamModule" target="_blank"&gt;NginxHttpUpstreamModule&lt;/a&gt; for more information. In the next post, we'll look at using a few file synchronization tools like &lt;a title="Unison" href="http://www.cis.upenn.edu/~bcpierce/unison/" target="_blank"&gt;Unison&lt;/a&gt; and &lt;a title="rsync" href="http://samba.anu.edu.au/rsync/" target="_blank"&gt;rsync&lt;/a&gt; for data replication between backends.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fixing Unsupported Protocol Error with PECL</title>
   <link href="http://tjstein.com/2010/01/fixing-unsupported-protocol-error-with-pecl" />
   <updated>2010-01-26T00:00:00-08:00</updated>
   <id>http://tjstein.com/2010/01/fixing-unsupported-protocol-error-with-pecl</id>
   <content type="html">&lt;p&gt;After setting up PHP 5.2.10, I wanted to install a few additional modules using PECL. I found soon after that I was unable to do so, receiving the following error:&lt;/p&gt;

&lt;blockquote&gt;pear.php.net is using a unsupported protocol - This should never happen. install failed&lt;/blockquote&gt;


&lt;p&gt;The problem seems to exhibit itself with corrupted PEAR installations in PHP 5.2.9 and 5.2.10. To fix this, just backup and update the channels:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;mv /usr/local/lib/php/.channels /usr/local/lib/php/.channels.bak
pear update-channels
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;After that, you should be good to go.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Media Temple (gs) Grid Service Domain &amp; MySQL Backups</title>
   <link href="http://tjstein.com/2009/10/media-temple-gs-grid-service-domain-and-mysql-backups" />
   <updated>2009-10-25T00:00:00-07:00</updated>
   <id>http://tjstein.com/2009/10/media-temple-gs-grid-service-domain-and-mysql-backups</id>
   <content type="html">&lt;p&gt;Having been on many shared hosting platforms before, I am fortunate enough to have a few (gs) Grid Services with (mt) Media Temple. Although no native backup tool currently exists for the (gs), I've created some simple backup scripts to backup the domain directories and MySQL databases. Both are very simple bash scripts that can be set up as cron jobs from with the AccountCenter. The first backup we'll create is for domain backups:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;If you haven't done so already, &lt;a href="http://kb.mediatemple.net/questions/16/" target="_blank"&gt;enable SSH&lt;/a&gt; from the (mt) Media Temple AccountCenter.&lt;/li&gt;&lt;br&gt;

    &lt;li&gt;Once you've logged in via SSH, navigate to the /data directory. Keep in mind you'll need to add your site number in the 00000 for this to work. You can find your site number in the Server Guide &amp;gt; Access Domain section of the AccountCenter.&lt;/li&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /home/00000/data
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



    &lt;li&gt;Run the following commands to create and set permissions of the backup directory:&lt;/li&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;mkdir backup
chmod 777 backup
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



    &lt;li&gt;Create a file called backup.sh and make it executable:&lt;/li&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;touch backup.sh
chmod +x backup.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



    &lt;li&gt;Open the file in a text editor or vim and paste in the following:&lt;/li&gt;
&lt;/ol&gt;




&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;today&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date &lt;span class="s1"&gt;&amp;#39;+%d_%m_%y&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;* Performing domain backup...&amp;quot;&lt;/span&gt;
tar czf /home/00000/data/backup/example.com_&lt;span class="s2"&gt;&amp;quot;$today&amp;quot;&lt;/span&gt;.tar.gz -C / home/00000/domains/example.com
&lt;span class="c"&gt;# Remove backups older than 7 days:&lt;/span&gt;
&lt;span class="nv"&gt;MaxFileAge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7
find /home/00000/data/backup/ -name &lt;span class="s1"&gt;&amp;#39;*.gz&amp;#39;&lt;/span&gt; -type f -mtime +&lt;span class="nv"&gt;$MaxFileAge&lt;/span&gt; -exec rm -f &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;* Backed up...&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This really simple script creates a tar.gz backup of the example.com directory, stamps it with the current date and places it in the the backup folder we just created. It will also prune any backup older than 7 days old. This number can be adjusted by tweaking the &lt;em&gt;MaxFileAge&lt;/em&gt; value. Before saving the file, be sure to make the necessary adjustments for your site number after the /home directory. You'll also need to modify example.com for the actual domain you'll be backing up. Before adding it as a cron, run the script via SSH -- the output should look like this:&lt;/p&gt;

&lt;pre class="terminal"&gt;
example.com@n10:/home/00000/data$ ./backup.sh
* Performing domain backup...
* Backed up...
&lt;/pre&gt;


&lt;p&gt;Depending on the size, the backup may hesitate after the initialization while the domain directory is being compressed. You can now verify that the new backup is in the &lt;strong&gt;/home/#####/data/backup/&lt;/strong&gt; directory with the today's date: &lt;em&gt;example.com_25_10_09.tar.gz&lt;/em&gt;. Once you've confirmed the backup works, add the backup.sh file as a cron within the AccountCenter following this &lt;a href="http://kb.mediatemple.net/questions/243/" target="_blank"&gt;KnowledgeBase&lt;/a&gt; article. You can schedule the cron as frequent as you would like.&lt;/p&gt;

&lt;p&gt;Now, you've probably got at least 1 MySQL database that should be backed up as well. This can be accomplished just as easily.&lt;/p&gt;

&lt;p&gt;SSH back into the /data directory and create a new bash script file:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;touch db-backup.sh
chmod +x db-backup.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, open the file in a text editor or vim and paste in the following:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;code class="bash"&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;#############################&lt;/span&gt;
&lt;span class="nv"&gt;SQLHOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;internal-db.s00000.gridserver.com&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;SQLDB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;db00000_dbname&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;SQLUSER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;db00000&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;SQLPASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;db_user_password&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;SQLFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;db00000_example.com_$(date &amp;#39;+%d_%m_%y&amp;#39;).sql&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;LOCALBACKUPDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/home/00000/data/backup&amp;quot;&lt;/span&gt;
&lt;span class="c"&gt;#############################&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;* Performing SQL dump...&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$LOCALBACKUPDIR&lt;/span&gt;
mysqldump -h &lt;span class="nv"&gt;$SQLHOST&lt;/span&gt; --add-drop-table --user&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;$SQLUSER&amp;quot;&lt;/span&gt; --password&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;$SQLPASS&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;$SQLDB&lt;/span&gt; &amp;gt; &lt;span class="nv"&gt;$SQLFILE&lt;/span&gt;
&lt;span class="c"&gt;# Remove backups older than 7 days:&lt;/span&gt;
&lt;span class="nv"&gt;MaxFileAge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7
find /home/00000/data/backup/ -name &lt;span class="s1"&gt;&amp;#39;*.sql&amp;#39;&lt;/span&gt; -type f -mtime +&lt;span class="nv"&gt;$MaxFileAge&lt;/span&gt; -exec rm -f &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;* Backed up...&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;This bash script uses mysqldump to dump a MySQL database which stamps it with the current date and places it in the the backup folder we created before. This will also prune any database backups that are older than 7 days. Before saving the file, be sure to make the necessary adjustments for your site number and database credentials -- all of this can be found under the Manage Databases section of the AccountCenter. Before adding it as a cron, run the script via SSH -- the output should look like this:&lt;/p&gt;

&lt;pre class="terminal"&gt;
example.com@n10:/home/00000/data$ ./db-backup.sh
* Performing SQL dump...
* Backed up...
&lt;/pre&gt;


&lt;p&gt;Once you've confirmed the script completes without errors, add it as a cron job so you'll never have to worry about losing your MySQL data again!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ditching Apple Mail for Postbox</title>
   <link href="http://tjstein.com/2009/08/ditching-apple-mail-for-postbox" />
   <updated>2009-08-26T00:00:00-07:00</updated>
   <id>http://tjstein.com/2009/08/ditching-apple-mail-for-postbox</id>
   <content type="html">&lt;p&gt;&lt;img class="alignleft" src="/images/postbox.png" alt="Postbox" /&gt;&lt;/p&gt;

&lt;p&gt;Until recently, I've been using Apple Mail for all of my email needs. Although we typically loathe Apple Mail for it's overall bugginess in my workplace, I've been apathetic and used it for nearly 2 years. In doing so has warranted some abuse from my coworkers, all of whom swear by &lt;a title="Thunderbird" href="http://www.mozillamessaging.com/en-US/thunderbird/" target="_blank"&gt;Thunderbird&lt;/a&gt;. My hesitance to switch was purely based on my willful ignorance toward other applications.&lt;/p&gt;

&lt;p&gt;Meet &lt;a title="Postbox" href="http://www.postbox-inc.com/" target="_blank"&gt;Postbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Derived from Thunderbird and Mozilla labs, Postbox is a cross platform e-mail client that brings some of the great features from Gmail to the desktop. Features like tagging, topics, conversation view, tabs, and smart search made this an ideal replacement for Apple Mail. Setting up new accounts was also easy; if you're familiar with Thunderbird, you should feel right at home. Within an hour of installation, I had set up 4 IMAP accounts (2 Work, 2 Personal) and set up mail filters and synchronized additional IMAP folders.&lt;/p&gt;

&lt;p&gt;I'm still running beta 10 however the newest version is said to have significantly decreased CPU and memory usage. AOL Mail account support (ugh) has been added as well. The full list of bug fixes and improvements can be found &lt;a href="http://postbox-inc.com/releasenotes/1.0b11" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>

