<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>The Life and Times of Michael Shadle</title>
    <link>https://www.michaelshadle.com</link>
    <description>“Lazy people are efficient” - my boss</description>
    <language>en-us</language>
    <lastBuildDate>Sun, 20 Sep 2026 12:49:44 GMT</lastBuildDate>
    <atom:link href="https://www.michaelshadle.com/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Log configuration for Laravel multi-line backtrace logs in Datadog</title>
      <link>https://www.michaelshadle.com/2021/04/12/log-configuration-for-laravel-multi-line-backtrace-logs-in-datadog</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2021/04/12/log-configuration-for-laravel-multi-line-backtrace-logs-in-datadog</guid>
      <pubDate>Tue, 13 Apr 2021 04:15:00 GMT</pubDate>
      <description>Thanks to this link I was able to find this snippet to help quick. I wanted to share this with the world, since it was the only result Google had for this. Here is my full YAML…</description>
      <content:encoded><![CDATA[<p>Thanks to <a href="https://zenn.dev/m_norii/articles/dbc9f6ce975f57">this link</a> I was able to find this snippet to help quick. I wanted to share this with the world, since it was the only result Google had for this.</p>
<pre class="hljs"><code class="language-yaml" data-lang="yaml"><span class="hljs-attr">log_processing_rules:</span>
   <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">multi_line</span>
     <span class="hljs-attr">name:</span> <span class="hljs-string">new_log_start_with_date</span>
     <span class="hljs-attr">pattern:</span> <span class="hljs-string">\[\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])</span>
</code></pre>
<p>Here is my full YAML file, for example (in a custom config directory. filename: /etc/datadog-agent/conf.d/custom.d/conf.yaml) - based off a Forge created server. I used wildcards to ensure that it was universally available to all hosts and sites.</p>
<pre class="hljs"><code class="language-yaml" data-lang="yaml"><span class="hljs-attr">logs:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">file</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">/home/forge/*/storage/logs/*.log</span>
    <span class="hljs-attr">service:</span> <span class="hljs-string">laravel</span>
    <span class="hljs-attr">source:</span> <span class="hljs-string">laravel</span>
    <span class="hljs-attr">log_processing_rules:</span>
       <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">multi_line</span>
         <span class="hljs-attr">name:</span> <span class="hljs-string">new_log_start_with_date</span>
         <span class="hljs-attr">pattern:</span> <span class="hljs-string">\[\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])</span>
</code></pre>]]></content:encoded>
      <category>datadog</category>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>CrashPlan - what a joke.</title>
      <link>https://www.michaelshadle.com/2017/08/22/crashplan-what-a-joke</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2017/08/22/crashplan-what-a-joke</guid>
      <pubDate>Tue, 22 Aug 2017 18:40:19 GMT</pubDate>
      <description>Why would I be using CrashPlan one might ask? Well, I&apos;ve been waiting years for Backblaze to come up with a consumer/unlimited Linux client for my NAS boxes, and now that B2 is…</description>
      <content:encoded><![CDATA[<p>Why would I be using CrashPlan one might ask? Well, I've been waiting years for Backblaze to come up with a consumer/unlimited Linux client for my NAS boxes, and now that B2 is out, I doubt that's happening. :) CP was the only unlimited + Linux option there is.</p>
<p>I've been getting &quot;convert to CrashPlan Pro&quot; emails for a month or two now. I didn't have any interest. But now it is being forced, as they've announced they are exiting the consumer market. They provide an &quot;easy&quot; way and a discount for 12 months to migrate you over to their &quot;small business platform&quot; - except get this.</p>
<blockquote>
<p>Some cloud backups will be restarted</p>
<p>Some of your devices have more than 5 TB of data backed up to CrashPlan Central. Due to technical platform constraints of the migration process, each device's cloud backup must be less than 5 TB.</p>
<p>If you continue, these cloud backups will be permanently removed after you migrate your account to CrashPlan for Small Business, and these devices will start new cloud backups.</p>
</blockquote>
<p>So two of my NAS units are actually close to 100% backed up (it only took YEARS) - one at 14.7TB, the other at 23TB. Both of those backups, which took forever, are going to be removed. Even though the consumer CrashPlan could support it, and the CrashPlan Pro talks about unlimited backups (&quot;it can be gigabytes or terabytes!&quot;) they give me no way to migrate that. That has to start over from scratch.</p>
<p>Need I remind you that CP's upload performance is abysmal, the client is bloated and &quot;Java-ey&quot; and resource intensive. The whole thing is garbage. Sadly, it is the only Linux capable unlimited client out there though still.</p>
<p>If you don't need Linux, don't touch CP. Go with Backblaze. CP has tons of complaints of lost or broken backups, horrible speeds, then this kind of shit.</p>
<blockquote>
<p>To allow you time to transition to a new backup solution, we've extended your subscription (at no cost to you) by 60 days. Your new subscription expiration date is 09/21/2017.</p>
</blockquote>
<p>How is that 60 days? It's 30 days from today.</p>
<p>I just feel bad for all the people complaining on Twitter about prepaying and CP's policy is no refunds. Their backups will sit on the &quot;Crashplan for Home&quot; system until it expires, I guess - but a backup system with an expiration isn't much of a backup system at all. :)</p>]]></content:encoded>
      <category>consumerism</category>
      <category>software</category>
    </item>
    <item>
      <title>More WordPress woes - degradation over time</title>
      <link>https://www.michaelshadle.com/2017/03/13/more-wordpress-woes-degradation-over-time</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2017/03/13/more-wordpress-woes-degradation-over-time</guid>
      <pubDate>Mon, 13 Mar 2017 22:49:32 GMT</pubDate>
      <description>Another day, another WP headache. One of my clients contacted me saying his site is not performing properly and it has been getting worse. It&apos;s on a server I setup, so the server…</description>
      <content:encoded><![CDATA[<p>Another day, another WP headache.</p>
<p>One of my clients contacted me saying his site is not performing properly and it has been getting worse. It's on a server I setup, so the server shouldn't be the issue, but I wanted to make sure there's not something weird going on with it, and see if I can find some causes.</p>
<p>He's using my CloudFlare full page caching method - so that's good. His frontend performance (for cached pages) is lightning fast. But the backend and uncached pages (and 404s) are abysmal.</p>
<p>I notice the standard stuff - UberMenu, Genesis theme - both very general purpose things, which we all know sacrifices performance for flexibility. UberMenu can be a beast. &quot;I can do everything&quot; themes often are too. Anyway, the site WAS just fine previously with those, so it's something else. In the PHP-FPM slowlog and New Relic I see &quot;maybe_unserialize&quot; keep coming up over and over. That function ideally would never exist if it wasn't for WP storing serialized and unserialized strings in the same places and having to detect if it's working with one or not (such an amazing design...) - but either way, it shouldn't be as slow as it is.</p>
<p>That function is used all over the place - but there are a couple key places to look. Especially when cron is disabled in wp-config.php and I am seeing calls to wp_get_schedule, wp_next_scheduled, and other cron-looking functions, on what seems nearly every page load. I wound up finding the culprit. The client had used a plugin called &quot;Easy Social Metrics&quot; and what it would do is add to the cron queue at least one row per post. So there were hundreds if not thousands of &quot;easy_social_metrics_update_single_post&quot; one-time cron items that were being autoloaded EVERY PAGE LOAD - because the &quot;cron&quot; option is an autoloaded option. So every page load inside of the WP frontend or in the admin area was loading tons of serialized text in this single variable, checking if it was serialized, unserializing it, possibly updating/modifying it, reserializing it, etc.</p>
<p>The sad thing was he didn't like the plugin so he had deleted it. But it left behind all the residue.</p>
<p>I've seen similar issues with other options, the &quot;rewrite_rules&quot; one was abused by some other plugin as well in the past on another site (I don't have the details anymore) but this is the second time I've had to forcefully kill off an option to actually rescue performance. Sadly, this is nothing any normal end user who is using only plugins to interact with their site would ever notice, until they installed some sort of cron manager and saw all these excess items hanging around. Not many people would install a cron manager though, or should need to. So that would just mean they have to hire someone now to diagnose why this magical CMS that can do anything is so abysmally slow.</p>
<p>It does have a nice looking admin interface, low barrier to entry for end users, but the foundation is horrible, the plugin and theme ecosystem seems rich because of the number of options and downloads, but the quality and performance on most are lacking.</p>
<p>Here's a chart of the performance. You'll see the first time I killed the &quot;cron&quot; option around 3:13pm, which was rewritten in full again and caused the second spike, and then when I finally purged it for good around 3:17pm. Site is back with sub-1 second average and remained that way. Which is about as good as you're gonna get with 20+ plugins including UberMenu and a kitchen sink theme. :)</p>
<figure><a href="https://www.michaelshadle.com/media/1789753091880-bbb851d81b-c44005.png"><img src="https://www.michaelshadle.com/media/1789753091880-bbb851d81b-c44005.png" alt=""></a></figure>]]></content:encoded>
      <category>wordpress</category>
    </item>
    <item>
      <title>GoDaddy SSL cert limitations - 10 domains? Not really.</title>
      <link>https://www.michaelshadle.com/2017/02/14/godaddy-ssl-cert-limitations-10-domains-not-really</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2017/02/14/godaddy-ssl-cert-limitations-10-domains-not-really</guid>
      <pubDate>Wed, 15 Feb 2017 01:49:08 GMT</pubDate>
      <description>Just a quick heads up, if planning on buying a UCC cert (totally overpriced!) that claims 10 domains - you actually only get ten FQDNs total - use them wisely. Consider this…</description>
      <content:encoded><![CDATA[<p>Just a quick heads up, if planning on buying a UCC cert (totally overpriced!) that claims 10 domains - you actually only get ten FQDNs total - use them wisely. Consider this example, only covering five domains:</p>
<ol start="2">
<li>
<p><a href="http://a.com">a.com</a></p>
</li>
<li>
<p><a href="http://www.a.com">www.a.com</a></p>
</li>
<li>
<p><a href="http://b.com">b.com</a></p>
</li>
<li>
<p><a href="http://www.b.com">www.b.com</a></p>
</li>
<li>
<p><a href="http://c.com">c.com</a></p>
</li>
<li>
<p><a href="http://www.c.com">www.c.com</a></p>
</li>
<li>
<p><a href="http://d.com">d.com</a></p>
</li>
<li>
<p><a href="http://www.d.com">www.d.com</a></p>
</li>
<li>
<p><a href="http://e.com">e.com</a></p>
</li>
<li>
<p><a href="http://www.e.com">www.e.com</a></p>
</li>
</ol>
<p>This is why we use things like CloudFlare and Let's Encrypt. Depending on your needs. It's 2017, who actually needs to buy SSL certs anymore?</p>
<p>Before my customer purchased the certificate I had to ask, since &quot;domain&quot; means something different to me  (you know, an actual domain) and this is what support told me - I verified this after the fact. Now as she states &quot;the primary covers both [www and non-www]&quot; - you <em>can</em> squeeze in an 11th host, but since I needed the domains fully covered, I could only use it for five domains either way.</p>
<figure><a href="https://www.michaelshadle.com/media/1789753091839-a359cd8db7-cd0e2b.png"><img src="https://www.michaelshadle.com/media/1789753091839-a359cd8db7-cd0e2b.png" alt=""></a></figure>]]></content:encoded>
      <category>consumerism</category>
    </item>
    <item>
      <title>Beware: S3 doesn&apos;t support &quot;+&quot; in filenames (properly)</title>
      <link>https://www.michaelshadle.com/2017/01/12/beware-s3-doesnt-support-plus-in-filenames-properly</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2017/01/12/beware-s3-doesnt-support-plus-in-filenames-properly</guid>
      <pubDate>Fri, 13 Jan 2017 04:50:53 GMT</pubDate>
      <description>Discovered this issue the other day. While you can upload a file with a plus &quot;+&quot; in it, it won&apos;t reject you. However, you cannot directly access it. You can only access it by…</description>
      <content:encoded><![CDATA[<p>Discovered this issue the other day.</p>
<p>While you can upload a file with a plus &quot;+&quot; in it, it won't reject you. However, you cannot directly access it. You can only access it by encoding the &quot;+&quot; to &quot;%2b&quot; - so unless you are doing that in your links, you'll wind up with &quot;access denied&quot; S3 XML error. Because the &quot;+&quot; is interpreted as a space - instead of the actual &quot;+&quot;</p>
<p>While they could fix this, it looks like they won't at this point, as it will change the behavior that everyone is used to. I found some threads from years ago complaining about it, even back then there was little expectation the behavior would be changed.</p>
<p>Total complaints with S3: 3<br>
Total happiness points with S3: 1,292</p>]]></content:encoded>
      <category>aws</category>
    </item>
    <item>
      <title>nginx rate limiting with a combination of IP and user agent</title>
      <link>https://www.michaelshadle.com/2016/09/07/nginx-rate-limiting-with-a-combination-of-ip-and-user-agent</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2016/09/07/nginx-rate-limiting-with-a-combination-of-ip-and-user-agent</guid>
      <pubDate>Wed, 07 Sep 2016 22:13:31 GMT</pubDate>
      <description>Here&apos;s a quick and dirty way to use IP-based rate limiting (very common) but override it for specific user agents (or basically, this is just a method of chaining geo {} and map…</description>
      <content:encoded><![CDATA[<p>Here's a quick and dirty way to use IP-based rate limiting (very common) but override it for specific user agents (or basically, this is just a method of chaining geo {} and map {} and other things together - you have to recycle the variables as each following statement's &quot;default&quot; value.</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-comment"># whitelisted IP ranges - will not have limits applied</span>
geo <span class="hljs-variable">$geo_whitelist</span> {
  <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>;
  <span class="hljs-number">1.2</span>.<span class="hljs-number">3.4</span> <span class="hljs-number">1</span>;
  <span class="hljs-number">2.3</span>.<span class="hljs-number">4.5</span>/<span class="hljs-number">24</span> <span class="hljs-number">1</span>;
}

<span class="hljs-comment"># whitelisted user agents - will not have limits applied</span>
map <span class="hljs-variable">$http_user_agent</span> <span class="hljs-variable">$whitelist</span> {
  <span class="hljs-keyword">default</span> <span class="hljs-variable">$geo_whitelist</span>;
  ~*(google) <span class="hljs-number">1</span>;
}

<span class="hljs-comment"># if whitelist is 0, put the binary IP address in $limit so the rate limiting has something to use</span>
map <span class="hljs-variable">$whitelist</span> <span class="hljs-variable">$limit</span> {
  <span class="hljs-number">0</span> <span class="hljs-variable">$binary_remote_addr</span>;
  <span class="hljs-number">1</span> <span class="hljs-string">&quot;&quot;</span>;
}

limit_req_zone <span class="hljs-variable">$limit</span> zone=perip:<span class="hljs-number">30</span>m rate=<span class="hljs-number">1</span>r/s;
</code></pre>
<p>References:</p>
<ul>
<li><a href="http://serverfault.com/questions/177461/how-to-rate-limit-in-nginx-but-including-excluding-certain-ip-addresses">http://serverfault.com/questions/177461/how-to-rate-limit-in-nginx-but-including-excluding-certain-ip-addresses</a></li>
<li><a href="http://stackoverflow.com/a/30083902">http://stackoverflow.com/a/30083902</a></li>
</ul>]]></content:encoded>
      <category>nginx</category>
    </item>
    <item>
      <title>Automatically installing New Relic on Elastic Beanstalk</title>
      <link>https://www.michaelshadle.com/2016/07/10/automatically-installing-new-relic-on-elastic-beanstalk</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2016/07/10/automatically-installing-new-relic-on-elastic-beanstalk</guid>
      <pubDate>Sun, 10 Jul 2016 21:49:18 GMT</pubDate>
      <description>Nearly 100% automated - it looks like the only way to grab an environment variable right now is through some nasty hacks. Other than the one hard-coded thing at the moment, this…</description>
      <content:encoded><![CDATA[<p>Nearly 100% automated - it looks like the only way to grab an environment variable right now is through some nasty hacks.</p>
<p>Other than the one hard-coded thing at the moment, this seems to work well. Sets up the New Relic configuration as desired, on instance creation. Assuming stock PHP 5.x Amazon Linux AMI.</p>
<p>Just drop this in <code>.ebextensions/newrelic.config</code> or something of the sort, and rebuild your environment. Replace API_KEY with your API key, and change or remove the newrelic.framework line if not using Wordpress (<a href="https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration">this page</a> has a list of supported frameworks)</p>
<pre class="hljs"><code class="language-yaml" data-lang="yaml"><span class="hljs-attr">packages:</span>
  <span class="hljs-attr">yum:</span>
    <span class="hljs-attr">newrelic-sysmond:</span> []
    <span class="hljs-attr">newrelic-php5:</span> []
  <span class="hljs-attr">rpm:</span>
    <span class="hljs-attr">newrelic:</span> <span class="hljs-string">http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm</span>
<span class="hljs-attr">commands:</span>
  <span class="hljs-attr">&quot;01_configure_sysmond&quot;:</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">nrsysmond-config</span> <span class="hljs-string">--set</span> <span class="hljs-string">license_key=API_KEY</span>
  <span class="hljs-attr">&quot;02_start_sysmond&quot;:</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">/etc/init.d/newrelic-sysmond</span> <span class="hljs-string">start</span>
  <span class="hljs-attr">&quot;03_install_php_agent&quot;:</span>
    <span class="hljs-attr">command:</span> <span class="hljs-string">newrelic-install</span> <span class="hljs-string">install</span>
    <span class="hljs-attr">env:</span>
      <span class="hljs-attr">NR_INSTALL_SILENT:</span> <span class="hljs-literal">true</span>
      <span class="hljs-attr">NR_INSTALL_KEY:</span> <span class="hljs-string">API_KEY</span>
<span class="hljs-attr">files:</span>
  <span class="hljs-string">&quot;/etc/php.d/newrelic.ini&quot;</span><span class="hljs-string">:</span>
    <span class="hljs-attr">mode:</span> <span class="hljs-string">&quot;000644&quot;</span>
    <span class="hljs-attr">owner:</span> <span class="hljs-string">root</span>
    <span class="hljs-attr">group:</span> <span class="hljs-string">root</span>
    <span class="hljs-attr">content:</span> <span class="hljs-string">|
      extension=newrelic.so
</span>
      [<span class="hljs-string">newrelic</span>]
      <span class="hljs-string">newrelic.appname</span> <span class="hljs-string">=</span> <span class="hljs-string">&quot;`{ &quot;</span><span class="hljs-string">Ref&quot;</span> <span class="hljs-string">:</span> <span class="hljs-string">&quot;AWSEBEnvironmentName&quot;</span> <span class="hljs-string">}`&quot;</span>
      <span class="hljs-string">newrelic.browser_monitoring.auto_instrument</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.capture_params</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.enabled</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.error_collector.enabled</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.error_collector.record_database_errors</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.high_security</span> <span class="hljs-string">=</span> <span class="hljs-literal">false</span>
      <span class="hljs-string">newrelic.license</span> <span class="hljs-string">=</span> <span class="hljs-string">&quot;API_KEY&quot;</span>
      <span class="hljs-string">newrelic.transaction_tracer.detail</span> <span class="hljs-string">=</span> <span class="hljs-number">1</span>
      <span class="hljs-string">newrelic.transaction_tracer.enabled</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.transaction_tracer.explain_enabled</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.transaction_tracer.explain_threshold</span> <span class="hljs-string">=</span> <span class="hljs-number">2000</span>
      <span class="hljs-string">newrelic.transaction_tracer.record_sql</span> <span class="hljs-string">=</span> <span class="hljs-string">&quot;raw&quot;</span>
      <span class="hljs-string">newrelic.transaction_tracer.slow_sql</span> <span class="hljs-string">=</span> <span class="hljs-literal">true</span>
      <span class="hljs-string">newrelic.framework</span> <span class="hljs-string">=</span> <span class="hljs-string">&quot;wordpress&quot;</span>
</code></pre>]]></content:encoded>
      <category>aws</category>
      <category>php</category>
    </item>
    <item>
      <title>You really can do bash completion with spaces!</title>
      <link>https://www.michaelshadle.com/2016/04/28/you-really-can-do-bash-completion-with-spaces</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2016/04/28/you-really-can-do-bash-completion-with-spaces</guid>
      <pubDate>Fri, 29 Apr 2016 01:49:00 GMT</pubDate>
      <description>A short period ago when I was working on my little ec2ssh project I ran into the issue of tab completion not working for things with spaces in them. This was my first foray into…</description>
      <content:encoded><![CDATA[<p>A short period ago when I was working on my little <a href="https://github.com/mike503/ec2ssh/">ec2ssh</a> project I ran into the issue of tab completion not working for things with spaces in them.</p>
<p>This was my first foray into the world of bash completion, so I incorrectly thought &quot;this can't be that hard - everything has completion now.&quot;</p>
<p>After Googling for hours, trying various things, finding statements saying that it wasn't possible - I stumbled upon the solution. It works properly and was surprisingly easy.</p>
<p>The <code>compgen</code> command typically works with spaces for the word separators. What I had to do was make sure the source data was separated by something else, such as a linebreak (<code>\n</code>) and then tell <code>compgen</code> that was the separator.</p>
<p>So this line before the <code>compgen</code> command was key:</p>
<pre class="hljs"><code>local IFS=$'\n'
</code></pre>
<p>Next, the <code>complete</code> command still won't work without feeding it the <code>-o filenames</code> option. This seems to be critical, telling it to behave like we are dealing with filenames makes it work properly. Note that I couldn't even find the original example that led me to this solution right now. <em>It's that undocumented.</em></p>
<pre class="hljs"><code>complete -o filenames
</code></pre>
<p>If you'd like to see this put altogether, in a very easy to read, semi-documented autocomplete script, check it out here:<br>
<a href="https://github.com/mike503/ec2ssh/blob/master/ec2ssh.bash_completion.sh">https://github.com/mike503/ec2ssh/blob/master/ec2ssh.bash_completion.sh</a></p>]]></content:encoded>
      <category>bash</category>
    </item>
    <item>
      <title>CrashPlan in Docker on Synology</title>
      <link>https://www.michaelshadle.com/2015/12/04/crashplan-in-docker-on-synology</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2015/12/04/crashplan-in-docker-on-synology</guid>
      <pubDate>Sat, 05 Dec 2015 00:06:23 GMT</pubDate>
      <description>TL;DR - fun stuff is at the bottom. It&apos;s time to spend a few minutes to share something that hopefully will solve a headache of mine - and maybe one of yours. I own Synology…</description>
      <content:encoded><![CDATA[<p>TL;DR - fun stuff is at the bottom.</p>
<p>It's time to spend a few minutes to share something that hopefully will solve a headache of mine - and maybe one of yours.</p>
<p>I own Synology DS2411+ units. They're very space efficient, and quiet - the form factor is great, and something I haven't found anywhere else (WHY?!?!) - there is a premium for their specifically designed chassis and software - and in the past I've found it to be worth it. Nowadays with ZFS or Btrfs around, cheaper hardware and such... I'm not as happy, but I'm also not in the market for a new setup. :)</p>
<p>Anyway - one of the main things I want to do is to try to back up everything on my physical units to the cloud. The first barrier to entry is that there is only one truly &quot;set-it-and-forget-it&quot; *unlimited* provider that has a Linux client - and that is CrashPlan. The pricing is great, but the client is bloated, buggy and weird. I've begged Backblaze to create a Linux client for years and there was some chatter about it, but still nothing public. At this point with B2 being launched, I'd be surprised if they do it at all, or just have a B2-based app instead (in which case it will be utility based billing. I want unlimited!)</p>
<p>Back to our only option - CrashPlan.</p>
<p>Due to the terms of distribution with CrashPlan it looks like it cannot be officially packaged by Synology. Which is where the <a href="http://pcloadletter.co.uk/2012/01/30/crashplan-syno-package/">PC Load Letter option</a> came in handy. However it had some issues over time, and the Java distribution would require reinstall periodically. Ultimately, it wasn't the most reliable solution.</p>
<p>So I decided - I'll use the instructions to guide me on a manual install, one that isn't subject to issues with the package manager or Java changes. After <a href="http://forum.synology.com/wiki/index.php/CrashPlan_Headless_Client">using the instructions on the Synology wiki</a> and what I thought was a clean, successful installation that worked for a couple weeks, it too crashed. Somehow during one of CrashPlan's own updates (I believe) it wound up wiping all the .jar files away. Trying to reinstall CrashPlan (the same version) actually failed after that for some unknown reason (how?!?!)</p>
<p>Recently I had some issues when trying to setup a Redmine install for a client. Even following the exact instructions it wouldn't work. No idea why. So I decided to look into a <a href="https://hub.docker.com/r/sameersbn/redmine/">Docker-based setup</a>. Wouldn't you know, I found a package that worked perfectly out of the gate. Docker to the rescue.</p>
<p>I realized not too long ago that Synology added Docker to it's package center. While I dismissed it as being more bloatware and attention being paid to the wrong aspects (just make a rock solid storage platform, I don't need an app store concept on my NAS!) I decided I should take a peek at the possibility of running CrashPlan in a Docker container. That way, it was self-contained in a richer Linux environment, with it's own management of the Java runtime stuff.</p>
<p>As of right now, I will say - &quot;Docker to the rescue&quot; - again. After fixing up the right command line arguments and finding a Docker image that seems to work well, it's been running stable and inherited my old backup perfectly. I use -v to expose the /volume1 off my Synology to the container and it picks up exactly where it left off.</p>
<p>That's quite a lot of explanation for what boils down to the magic of it all. Here is the working image and my command line arguments to it, to expose the ports and volumes and such properly. Enjoy.</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">docker pull jrcs/crashplan
docker run -d -p 4242:4242 -p 4243:4243 -v /volume1:/volume1 jrcs/crashplan:latest
</code></pre>
<p>Add more -v's if needed, and change the ports if you wish. Remember to grab the /var/lib/crashplan/.ui_info file to get the right key so you can connect to it from a CrashPlan Desktop application (once of my other complaints with CP)</p>
<p>UPDATE 2017/01/07 - after running this for months, I'll share my script (I believe it actually requires installing bash from ikpg to really be solid) - I put it on my data volume (volume1) in the crashplan directory and it seems to persist. Any time I want to update the container or something seems to have crashed (since CrashPlan can crash often, thanks mainly to Java and the large amount of files and how it is RAM heavy) I can just run this. It's able to persist the relevant configuration between docker runs, and runs more stable than any other solution I've used or tried. CrashPlan is still much slower than Backblaze but it's still the only service with a Linux compatible client and unlimited data (I don't consider ACD to fit the mold exactly yet)</p>
<pre class="hljs"><code class="language-bash" data-lang="bash"><span class="hljs-built_in">cat</span> /volume1/crashplan/crashplan-docker.sh 
<span class="hljs-comment">#!/opt/bin/bash -v</span>

docker <span class="hljs-built_in">rm</span> -f `docker ps -qa`
<span class="hljs-built_in">rm</span> -f /volume1/crashplan/log/*

docker pull jrcs/crashplan:latest

<span class="hljs-comment"># ref: https://hub.docker.com/r/jrcs/crashplan/</span>
docker run \
-d \
--name=crashplan \
--restart=always \
-h <span class="hljs-variable">$HOSTNAME</span> \
-p 4242:4242 \
-p 4243:4243 \
-v /volume1:/volume1 \
-v /volume1/crashplan:/var/crashplan \
jrcs/crashplan:latest
</code></pre>]]></content:encoded>
      <category>backup</category>
      <category>crashplan</category>
      <category>docker</category>
      <category>software</category>
      <category>synology</category>
    </item>
    <item>
      <title>Speeding up Drupal cache flushing</title>
      <link>https://www.michaelshadle.com/2015/04/21/speeding-up-drupal-cache-flushing</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2015/04/21/speeding-up-drupal-cache-flushing</guid>
      <pubDate>Tue, 21 Apr 2015 23:04:09 GMT</pubDate>
      <description>Are your cache clears slow? Do you use features? It&apos;s great, but can become quite the beast when you run a &quot;drush cc all&quot; or a &quot;drush fra&quot; - and today we figured out why the…</description>
      <content:encoded><![CDATA[<p>Are your cache clears slow?</p>
<p>Do you use features? It's great, but can become quite the beast when you run a &quot;drush cc all&quot; or a &quot;drush fra&quot; - and today we figured out why the &quot;drush cc all&quot; is an issue. Because when hook_flush_caches() runs, if you don't explicitly define this as FALSE, it will run the &quot;fra&quot; for you inside of your cache clear!</p>
<p>Add this to your settings.php:</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-variable">$conf</span>[<span class="hljs-string">&#x27;features_rebuild_on_flush&#x27;</span>] = <span class="hljs-literal">FALSE</span>;
</code></pre>
<p>Since we run our fra separately, we've disabled this, and noticed quite a reduction in time to &quot;flush caches&quot; (which was not only flushing caches but also reverting features, apparently!)</p>
<p>It's that unknown-to-us-before-today variable in the snippet below...</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-comment">/**
 * Implements hook_flush_caches().
 */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">features_flush_caches</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (<span class="hljs-title function_ invoke__">variable_get</span>(<span class="hljs-string">&#x27;features_rebuild_on_flush&#x27;</span>, <span class="hljs-literal">TRUE</span>)) {
    <span class="hljs-title function_ invoke__">features_rebuild</span>();       
    <span class="hljs-comment">// Don&#x27;t flush the modules cache during installation, for performance reasons.</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-title function_ invoke__">variable_get</span>(<span class="hljs-string">&#x27;install_task&#x27;</span>) == <span class="hljs-string">&#x27;done&#x27;</span>) {
      <span class="hljs-title function_ invoke__">features_get_modules</span>(<span class="hljs-literal">NULL</span>, <span class="hljs-literal">TRUE</span>);
    }
  }
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">array</span>();
}
</code></pre>]]></content:encoded>
      <category>drupal</category>
    </item>
    <item>
      <title>Custom XHProf run IDs</title>
      <link>https://www.michaelshadle.com/2014/12/21/custom-xhprof-run-ids</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2014/12/21/custom-xhprof-run-ids</guid>
      <pubDate>Sun, 21 Dec 2014 19:02:20 GMT</pubDate>
      <description>XHProf is an awesome tool, but ships with a very annoying restriction out of the box. It names the run IDs in a cryptic randomized fashion (which makes sense - should be no…</description>
      <content:encoded><![CDATA[<p>XHProf is an awesome tool, but ships with a very annoying restriction out of the box. It names the run IDs in a cryptic randomized fashion (which makes sense - should be no collisions, and there's no &quot;good&quot; default way to name them otherwise.)</p>
<p>The good news however is that it does support custom run IDs to be named in the save_run() method. Awesome! Except for an odd &quot;bug&quot; or &quot;feature&quot; - a custom run ID won't display in the runs UI if it has non-hex characters in it (see the end of this post for information about that.)</p>
<p>This makes profiling specific requests a lot easier - you can put in a unique query string parameter and see it come up in the run ID, if the URL isn't already obvious. You could also simply define a standard query string parameter for your users/developers to use instead of the entire [scrubbed] URL as a run ID. Since I run a multi-tenant development server with a bunch of developers each having the ability to have a bunch of unique hostnames, it makes the most sense to use every piece of the URL for the run ID.</p>
<p>To start using custom XHProf run IDs, enable XHProf the standard way, at the earliest point in your application (at the top of the front-controller index.php, for example):</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">&#x27;xhprof&#x27;</span>]) &amp;&amp; !<span class="hljs-keyword">empty</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;XHPROF_ROOT&#x27;</span>]) ) {
  <span class="hljs-keyword">include_once</span> <span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;XHPROF_ROOT&#x27;</span>] . <span class="hljs-string">&#x27;/xhprof_lib/utils/xhprof_lib.php&#x27;</span>;
  <span class="hljs-keyword">include_once</span> <span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;XHPROF_ROOT&#x27;</span>]. <span class="hljs-string">&#x27;/xhprof_lib/utils/xhprof_runs.php&#x27;</span>;
  <span class="hljs-title function_ invoke__">xhprof_enable</span>(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);
}
</code></pre>
<p>The key to the custom naming is is when it saves the run output. In this example, I made a simple function to take the URL, remove all special characters and change them into dashes and remove any repetitive &quot;dashing&quot;, and assign that as the third parameter to the save_runs() method, which is the &quot;run ID&quot; name.</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">&#x27;xhprof&#x27;</span>]) &amp;&amp; !<span class="hljs-keyword">empty</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;XHPROF_ROOT&#x27;</span>])) {
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_make_xhprof_run_id</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;HTTPS&#x27;</span>])) {
      <span class="hljs-variable">$run_id</span> = <span class="hljs-string">&#x27;https-&#x27;</span>;
    }
    <span class="hljs-keyword">else</span> {
      <span class="hljs-variable">$run_id</span> = <span class="hljs-string">&#x27;http-&#x27;</span>;
    }
    <span class="hljs-variable">$run_id</span> .= <span class="hljs-title function_ invoke__">urldecode</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;HTTP_HOST&#x27;</span>] . <span class="hljs-string">&#x27;/&#x27;</span> . <span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;REQUEST_URI&#x27;</span>]) . <span class="hljs-string">&#x27;-&#x27;</span> . <span class="hljs-title function_ invoke__">microtime</span>(<span class="hljs-literal">TRUE</span>);
    <span class="hljs-variable">$run_id</span> = <span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-title function_ invoke__">preg_replace</span>(<span class="hljs-string">&#x27;|([^A-Za-z0-9])|&#x27;</span>, <span class="hljs-string">&#x27;-&#x27;</span>, <span class="hljs-variable">$run_id</span>), <span class="hljs-string">&#x27;-&#x27;</span>);
    <span class="hljs-keyword">while</span> (<span class="hljs-title function_ invoke__">strstr</span>(<span class="hljs-variable">$run_id</span>, <span class="hljs-string">&#x27;--&#x27;</span>)) {
      <span class="hljs-variable">$run_id</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-string">&#x27;--&#x27;</span> , <span class="hljs-string">&#x27;-&#x27;</span>, <span class="hljs-variable">$run_id</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-variable">$run_id</span>;
  }
  <span class="hljs-variable">$xhprof_data</span> = <span class="hljs-title function_ invoke__">xhprof_disable</span>();
  <span class="hljs-variable">$xhprof_runs</span> = <span class="hljs-keyword">new</span> <span class="hljs-title class_">XHProfRuns_Default</span>();
  <span class="hljs-variable">$run_id</span> = <span class="hljs-variable">$xhprof_runs</span>-&gt;<span class="hljs-title function_ invoke__">save_run</span>(<span class="hljs-variable">$xhprof_data</span>, <span class="hljs-string">&#x27;xhprof_testing&#x27;</span>, <span class="hljs-title function_ invoke__">_make_xhprof_run_id</span>()); 
}
</code></pre>
<p>If you wanted to use a simple query string parameter, I would still use the same type of safeguards so that the filename comes out in a sane way (no high ASCII or other characters which the filesystem wouldn't handle well) - for example, using the &quot;run_id&quot; parameter (I haven't tested this code, but it *should* work :))</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">&#x27;xhprof&#x27;</span>]) &amp;&amp; !<span class="hljs-keyword">empty</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;XHPROF_ROOT&#x27;</span>])) {
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_make_xhprof_run_id</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// return null and it will handle it like usual</span>
    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">isset</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">&#x27;run_id&#x27;</span>])) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    }
    <span class="hljs-variable">$run_id</span> = <span class="hljs-title function_ invoke__">trim</span>(<span class="hljs-title function_ invoke__">preg_replace</span>(<span class="hljs-string">&#x27;|([^A-Za-z0-9])|&#x27;</span>, <span class="hljs-string">&#x27;-&#x27;</span>, <span class="hljs-title function_ invoke__">urldecode</span>(<span class="hljs-variable">$_GET</span>[<span class="hljs-string">&#x27;run_id&#x27;</span>]) . <span class="hljs-string">&#x27;-&#x27;</span> . <span class="hljs-title function_ invoke__">microtime</span>(<span class="hljs-literal">TRUE</span>)), <span class="hljs-string">&#x27;-&#x27;</span>);
    <span class="hljs-keyword">while</span> (<span class="hljs-title function_ invoke__">strstr</span>(<span class="hljs-variable">$run_id</span>, <span class="hljs-string">&#x27;--&#x27;</span>)) {
      <span class="hljs-variable">$run_id</span> = <span class="hljs-title function_ invoke__">str_replace</span>(<span class="hljs-string">&#x27;--&#x27;</span> , <span class="hljs-string">&#x27;-&#x27;</span>, <span class="hljs-variable">$run_id</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-variable">$run_id</span>;
  }
  <span class="hljs-variable">$xhprof_data</span> = <span class="hljs-title function_ invoke__">xhprof_disable</span>();
  <span class="hljs-variable">$xhprof_runs</span> = <span class="hljs-keyword">new</span> <span class="hljs-title class_">XHProfRuns_Default</span>();
  <span class="hljs-variable">$run_id</span> = <span class="hljs-variable">$xhprof_runs</span>-&gt;<span class="hljs-title function_ invoke__">save_run</span>(<span class="hljs-variable">$xhprof_data</span>, <span class="hljs-string">&#x27;xhprof_testing&#x27;</span>, <span class="hljs-title function_ invoke__">_make_xhprof_run_id</span>()); 
}
</code></pre>
<p>NOTE: Both of these methods require one thing to be fixed on the display side. Currently, the XHProf display UI that comes with the stock package *will* list all the XHProf runs, but won't load them if there's non-hex characters in the run ID. I don't know why this naming limitation is being forced. I've filed a bug[1] for now to ask why, or to propose removing the restriction (ideally) - however, for now I've commented out those three lines and everything seems to work fine so far.</p>
<p>[1] <a href="https://github.com/phacility/xhprof/issues/58">https://github.com/phacility/xhprof/issues/58</a></p>]]></content:encoded>
      <category>php</category>
      <category>profiling</category>
      <category>xhprof</category>
    </item>
    <item>
      <title>Facebook Messenger and the illusion of privacy</title>
      <link>https://www.michaelshadle.com/2014/08/27/facebook-messenger-and-the-illusion-of-privacy</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2014/08/27/facebook-messenger-and-the-illusion-of-privacy</guid>
      <pubDate>Wed, 27 Aug 2014 22:55:51 GMT</pubDate>
      <description>There are a lot of people who continue to spread the FUD around Messenger, and it is making me crazy. Anyone who thinks they have privacy on a third party service needs a reality…</description>
      <content:encoded><![CDATA[<p>There are a lot of people who continue to <a href="http://www.9news.com.au/technology/2014/08/09/07/47/facebook-messenger-app-has-permission-spy-on-your-phone">spread the FUD</a> around Messenger, and it is making me crazy.</p>
<p>Anyone who thinks they have privacy on a third party service needs a reality check.</p>
<p>As <a href="http://www.wired.com/politics/law/news/1999/01/17538">Scott McNealy said in 1999</a>, &quot;You have zero privacy anyway. Get over it.&quot; Anyone who still believes using a service someone else owns (especially for free) entitles them to privacy is sadly mistaken. Most services will <em>try</em> to do the right thing, but there will always be a chance of an accidental data breach or hack, even from the most trustworthy services. You can only hope that the company wants to do good by the consumer.</p>
<p><strong>Simply put, if you don't control it, you can't expect it to be controlled for you.</strong></p>
<p>There are two primary complaints I've heard during this whole Messenger debacle.</p>
<p>The first is that Messenger terms now allow them to spy on you and you can incriminate yourself by using it. First, companies are <strong>required</strong> to comply with law enforcement if they want to do business in this country. Second, if you are doing anything illegal, you shouldn't be discussing it on something someone else owns anyway. This has always been the case with your telephone, text messaging, etc... that's just common sense.</p>
<p>The other complaint is about unrestricted access to your camera and photos and contacts. Once again, that's nothing new - you authorize your apps all the time for access. Let's take some popular apps for example: Snapchat? You probably authorized it for camera, photo album and contact access. Apps need photo album access to be able to get past photos. They need camera access to take pictures/videos inside of the app. Instagram? You most likely authorized those for camera and/or the photo album too. You probably authorized LinkedIn to your contacts. You most likely authorized the <em>original</em> Facebook app to your camera and photo album (otherwise you can't post any images from inside the application!) - you probably even authorized it to access your contacts.</p>
<p>I feel bad for Facebook having to deal with such unoriginal claims. Yes, it sucks to have to install yet another app, but they have reasons for it and it works well in conjunction with the original Facebook app. It's free, and it isn't a space hog, so there's no real &quot;cost&quot; associated. Battery drainage is the only complaint I consider to be reasonable.</p>
<p>Just remember - <em>nothing</em> is truly private. Even your encrypted end-to-end messaging - someone can take a screenshot or save it and share it. It comes back to what Jon Voight said in <em>Enemy of the State</em>, &quot;The only privacy that's left is the inside of your head.&quot;</p>]]></content:encoded>
      <category>consumerism</category>
    </item>
    <item>
      <title>How to compile eggdrop on Ubuntu 14.04.1 LTS &quot;trusty&quot;</title>
      <link>https://www.michaelshadle.com/2014/08/08/how-to-compile-eggdrop-on-ubuntu-14-04-1-lts-trusty</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2014/08/08/how-to-compile-eggdrop-on-ubuntu-14-04-1-lts-trusty</guid>
      <pubDate>Sat, 09 Aug 2014 04:41:20 GMT</pubDate>
      <description>It&apos;s been a while. Updates? I&apos;m going to try to post more, and I also put the entire site on SSL. I&apos;ve switched hosts to Linode as well. Isn&apos;t that amazing? Back to compiling…</description>
      <content:encoded><![CDATA[<p>It's been a while. Updates? I'm going to try to post more, and I also put the entire site on SSL. I've switched hosts to Linode as well. Isn't that amazing?</p>
<p>Back to compiling eggdrop. When it gives that annoying paragraph:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">configure: error:

Tcl cannot be found on this system.

Eggdrop requires Tcl and the Tcl development files to compile. If you already have Tcl installed on this system, make sure you also have the development files (common package names include <span class="hljs-string">&#x27;tcl-dev&#x27;</span> and <span class="hljs-string">&#x27;tcl-devel&#x27;</span>). If I just wasn<span class="hljs-string">&#x27;t looking in the right place for it, re-run ./configure using the --with-tcllib=&#x27;</span>/path/to/libtcl.so<span class="hljs-string">&#x27; and --with-tclinc=&#x27;</span>/path/to/tcl.h<span class="hljs-string">&#x27; options.

See doc/COMPILE-GUIDE&#x27;</span>s <span class="hljs-string">&#x27;Tcl Detection and Installation&#x27;</span> section <span class="hljs-keyword">for</span> more information.
</code></pre>
<p>Install these 2 packages (and let the dependencies also install), and then this configure string works. For some reason, we no longer have a plain old <a href="http://libtcl.so">libtcl.so</a>, and eggdrop requires BOTH of these options to be provided or neither one works...</p>
<pre class="hljs"><code class="language-bash" data-lang="bash"><span class="hljs-built_in">sudo</span> apt-get install -y libtcl8.5 tcl8.5-dev
./configure --with-tcllib=/usr/lib/x86_64-linux-gnu/libtcl8.5.so --with-tclinc=/usr/include/tcl8.5/tcl.h
</code></pre>
<p>Oh yeah, this does assume you're running x86_64. Because there's really no reason you wouldn't be anymore.</p>]]></content:encoded>
      <category>tech-tips</category>
    </item>
    <item>
      <title>Docker HTTP proxy settings in Upstart</title>
      <link>https://www.michaelshadle.com/2013/10/10/docker-http-proxy-settings-in-upstart</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2013/10/10/docker-http-proxy-settings-in-upstart</guid>
      <pubDate>Fri, 11 Oct 2013 00:02:59 GMT</pubDate>
      <description>This was driving me crazy. There&apos;s some bug reports about it, but nobody has a plain and simple example. So here&apos;s mine. Enjoy. Old: New:</description>
      <content:encoded><![CDATA[<p>This was driving me crazy. There's some bug reports about it, but nobody has a plain and simple example. So here's mine. Enjoy.</p>
<p>Old:</p>
<pre class="hljs"><code class="language-python" data-lang="python">description <span class="hljs-string">&quot;Run docker&quot;</span>

start on filesystem <span class="hljs-keyword">or</span> runlevel [<span class="hljs-number">2345</span>]
stop on runlevel [!<span class="hljs-number">2345</span>]

respawn

script
  /usr/<span class="hljs-built_in">bin</span>/docker -d
end script
</code></pre>
<p>New:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">description <span class="hljs-string">&quot;Run docker&quot;</span>

start on filesystem or runlevel [2345]
stop on runlevel [!2345]

respawn

<span class="hljs-built_in">env</span> HTTP_PROXY=<span class="hljs-string">&quot;http://your.address:port&quot;</span>
<span class="hljs-built_in">env</span> HTTPS_PROXY=<span class="hljs-string">&quot;http://your.address:port&quot;</span>

script
  /usr/bin/docker -d
end script
</code></pre>]]></content:encoded>
      <category>docker</category>
      <category>software</category>
      <category>ubuntu</category>
      <category>upstart</category>
    </item>
    <item>
      <title>My first Scout plugin!</title>
      <link>https://www.michaelshadle.com/2013/09/08/my-first-scout-plugin</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2013/09/08/my-first-scout-plugin</guid>
      <pubDate>Mon, 09 Sep 2013 05:21:24 GMT</pubDate>
      <description>I&apos;m digging Scout so far, and it has almost all the plugins I would want already in their plugin directory. However, I did want to add in a Solr &quot;healthcheck&quot;, since we&apos;ve noticed…</description>
      <content:encoded><![CDATA[<p>I'm digging <a href="http://www.scoutapp.com">Scout</a> so far, and it has almost all the plugins I would want already in their plugin directory. However, I did want to add in a Solr &quot;healthcheck&quot;, since we've noticed some oddities with our search index.</p>
<p>Here is a quick-and-dirty way to get the number of results based on an empty search (i.e. the entire index) for a single Solr core on localhost. Maybe this will help somebody else out there. I suppose it could be paramterized with hostnames, search strings, etc... and it wouldn't be that hard either from what it looks like.</p>
<p>Enjoy.</p>
<p>Filename: solr.rb</p>
<pre class="hljs"><code class="language-ruby" data-lang="ruby"><span class="hljs-keyword">class</span> <span class="hljs-title class_">SolrResultCount</span> &lt; <span class="hljs-title class_ inherited__">Scout::Plugin</span>

  needs <span class="hljs-string">&quot;rubygems&quot;</span>
  needs <span class="hljs-string">&quot;json&quot;</span>
  needs <span class="hljs-string">&quot;net/http&quot;</span>

  <span class="hljs-keyword">def</span> <span class="hljs-title function_">build_report</span>
    url = <span class="hljs-string">&quot;http://localhost:8983/solr/select?q=&amp;rows=3&amp;fl=bundle&amp;wt=json&quot;</span>
    r = <span class="hljs-title class_">Net</span>::<span class="hljs-variable constant_">HTTP</span>.get_response(<span class="hljs-variable constant_">URI</span>.parse(url))
    parsed = <span class="hljs-variable constant_">JSON</span>.parse(r.body)
    report(<span class="hljs-symbol">:results=&gt;parsed</span>[<span class="hljs-string">&quot;response&quot;</span>][<span class="hljs-string">&quot;numFound&quot;</span>])
  <span class="hljs-keyword">end</span>

<span class="hljs-keyword">end</span>
</code></pre>]]></content:encoded>
      <category>development</category>
    </item>
    <item>
      <title>Setting up chrooted SFTP-only access on a Synology DiskStation</title>
      <link>https://www.michaelshadle.com/2013/08/28/setting-up-chrooted-sftp-only-access-on-a-synology-diskstation</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2013/08/28/setting-up-chrooted-sftp-only-access-on-a-synology-diskstation</guid>
      <pubDate>Wed, 28 Aug 2013 10:22:11 GMT</pubDate>
      <description>This has been on my list to try to figure out for a long time. I wanted SFTP only access to specific accounts, and to be able to chroot them. It took me a while and various…</description>
      <content:encoded><![CDATA[<p>This has been on my list to try to figure out for a long time. I wanted SFTP only access to specific accounts, and to be able to chroot them. It took me a while and various attempts, only to get wind up landing on the most basic solution, of course.</p>
<p>I originally tried scponly and scponlyc (which I've used in the past) and rssh, however none of them worked properly for me.</p>
<p>Sure enough, the openssh package from optware worked right out of the box.*</p>
<pre class="hljs"><code>wget http://wizjos.endofinternet.net/synology/archief/syno-mvkw-bootstrap_1.2-7_arm-ds111.xsh
ipkg install openssh openssh-sftp-server
</code></pre>
<p>Then edit /opt/etc/openssh/sshd_config, and put in:</p>
<pre class="hljs"><code class="language-sql" data-lang="sql"><span class="hljs-keyword">Match</span> <span class="hljs-keyword">User</span> username
        ChrootDirectory <span class="hljs-operator">/</span><span class="hljs-keyword">some</span><span class="hljs-operator">/</span>directory
        ForceCommand internal<span class="hljs-operator">-</span>sftp
</code></pre>
<p>Also edit the user account in /etc/passwd, change the home dir to the /some/directory, and give it &quot;/bin/sh&quot; for a shell.</p>
<p>Viola... when sshd is restarted next time it will just work.</p>
<p>The guys at optware made a neat startup script that will start their sshd on boot. So nothing to do there.</p>
<p>Make sure to disable synology's built-in ssh (Control Panel &gt; Terminal) or you'll probably be hitting the wrong one!</p>
<p>If you are concerned about privileges, the way that Synology runs its units isn't very UNIX permission friendly (most files are world writable on the filesystem, and the expectation is the daemons will properly control the access.) I wound up creating a little cron job that chmods and chowns files to keep the secondary account I've created to be a &quot;read only&quot; account to that directory.</p>
<p><em>* As always with my tips, YMMV - this worked fine on my Atom-based DS2411+ unit. but when I tried the same setup on a DS213, it didn't seem to work. No idea why, there aren't much diagnostics or logs provided to use. Sorry.</em></p>
<p><strong>UPDATE:</strong> After running this on the &quot;working&quot; NAS unit for a bit, it stopped working. The culprit was the ChrootDirectory became owned by the user, not by root:root. Changing it back (chown root:root /some/directory) fixes that. So it looks like OpenSSH wants that in place for the chroot stuff to work. That could have been the issue mentioned in the previous paragraph (couldn't test it anymore)</p>]]></content:encoded>
      <category>software</category>
      <category>synology</category>
    </item>
    <item>
      <title>Tackling the &quot;to-do&quot; list problem</title>
      <link>https://www.michaelshadle.com/2013/08/08/tackling-the-to-do-list-problem</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2013/08/08/tackling-the-to-do-list-problem</guid>
      <pubDate>Thu, 08 Aug 2013 07:57:54 GMT</pubDate>
      <description>I have a to-do list (surprise!) - actually I have a couple. Possibly even a few... I&apos;ve even got an item on one of them to consolidate the lists together. It is so easy to keep…</description>
      <content:encoded><![CDATA[<p>I have a to-do list (surprise!) - actually I have a couple. Possibly even a few... I've even got an item on one of them to consolidate the lists together.</p>
<p>It is so easy to keep adding new items, and it isn't as easy to mark them off. Tasks change status or become mini &quot;projects&quot; with multiple steps (get car oil changed = schedule oil change appointment, which leads to an appointment being booked, which will be the item until it can be marked complete.) At some point I really want to visit the whole &quot;to-do item status&quot; concept as well.</p>
<p>Anyway, this is how the inner workings of my engineer brain function. Some tasks are insanely simple, but mixed in with more complex ones that require perquisite tasks, specific times of the day (business hours for example), specific people, or specific locations that may or may not be possible to get to easily.</p>
<p>I've struggled with trying to tame the never-ending lists. Last week I had a night open and plans to be really productive and knock some things off my list - which wound up not happening, but other &quot;productive&quot; tasks did get taken care of. Those were not planned, but still helpful. Someone said &quot;what a productive day&quot; and I felt like it wasn't the &quot;productive&quot; I actually wanted.</p>
<p>Working in the world of software/web development, this kind of stuff has parallels in the engineering world. I guess you can call that &quot;technical debt&quot; - new stuff is coming up and old stuff isn't being taken care of.</p>
<p>That won't work for me. I need to be making progress, I've got a lot of tasks that need to be finished. That's why they made the list to begin with.</p>
<p>While I've always had the desire to finish these things, I haven't had the proper personal accountability for actually checking things off the list(s) - I love marking things done, but I don't make it a regular habit of checking them enough.</p>
<p>Enter <a href="http://www.beeminder.com">Beeminder</a> - a personal accountability system for reaching goals. A co-worker introduced me to the site. I started thinking about the usual suspects - like losing weight and thought about some of the things he had put in - like making sure he spends X hours a day being productive on personal projects. What I liked most is the work spent on the system to make it statistically sound, measurable (a goal needs to be measurable), capable of automating, and with appropriate notifications to remind me to log whatever data isn't being supplied automatically via other devices or services (your scale can talk to it, for example.)</p>
<p>I started thinking about other ideas to put down as goals. One of them was being &quot;productive&quot; by marking one thing off my to-do list per day. However, that can vary. Some items are easier than others, and what if I have a day where other &quot;productive&quot; tasks come up that take away from that list (as a lot of days do...) - so I began thinking more about it.</p>
<p>I came up with the idea that each task should have some sort of amount of effort associated to it. The effort is derived from the amount of work the task requires and/or the amount of coordination due to location, time constraints, people constraints, etc. For example, getting my passport - that has been on my list for over a year. I paid for it, filed the paperwork, just need the photo and actual submission done. I tried a few times last year but never had all my ducks in a row, and then it fell by the wayside (I had no real need for it and got busy with other things.)</p>
<p>Being a obsessed with completing things like I am, it's still on my list, and I want to get it done. I won't be surprised if my payment is now forfeited due to government accounting needing to close the books each year or something like that. Nevertheless, it's something I should have anyway, it's staying on the list. That would get a value of 1.0 - the highest a task can have, in my world. It requires finding a place that is open, a place that does photos, possibly trying to haggle with them to honor my payment made last year, etc. - a lot of possible effort there, along with time constraints (business hours, sort of) and location (specific locations handle specific things.)</p>
<p>Once I thought about it in that way, I could put in a Beeminder task of &quot;finish at least 1.0 units of effort per day&quot; or something. I started thinking of other tasks on my list, and it looked like that would be an easy way to try to knock things out. It almost becomes a game.</p>
<p>Then I started expanding the idea further. Those random unplanned tasks that come up, such as helping my Parents move? That took a lot of physical work and time. I can't really be taking care of other items if I am busy helping them out. I don't want to be penalized for it. So we can introduce the concept of &quot;bonus units&quot; - I could say &quot;I didn't do anything on the list, but that was definitely worth 1.0&quot; - and feel like the day is fulfilled still.</p>
<p>I believe every day people should do something to advance their life (or someone elses), and this way of tracking makes it easier to be accountable.</p>
<p>Extending it even more, random daily tasks that may or may not be done, based on laziness, distractions, whatever - those can have some value too. Maybe you don't go to the store that often - so going to the store is 0.2, or getting a haircut is 0.2. What about laundry? Those things do count. They are productive. Most of us probably wouldn't think of giving ourselves some credit for them when introducing something as detailed as this.</p>
<p>Those people who prefer the stick vs. the carrot could even put in negative units. Maybe you want to stop watching so much TV, so you deduct 0.1 units per hour. Combine that with earning 0.2 units per hour of gym time, and you are doing the equivalent of calorie counting but with productivity.</p>
<p>The gamification makes it kinda fun, and it might make it easier to adopt as part of a daily routine. Tying it to a system such as Beeminder could be useful too, if you like their method of being punished for non-compliance. Some of us need that, and I may wind up using their site for tracking each day's units.</p>
<p>I tried to come up with a name for a unit, the best I could come up with was &quot;Personal Productivity Unit&quot; (or PPU, since it needs an acronym) - but it was an idea that has been brewing for a while, and I think I have come up with enough structure now to give it a shot in real life and see how it fares.</p>
<p>Finally, I am sure I am not the first one to think of something like this, there are probably books written on this, but I haven't seen anything myself and it makes my engineering brain happy to be able to weigh tasks and set a goal based on that. If anyone else has any more ideas on the subject, I'm all ears!</p>]]></content:encoded>
      <category>lifestyle</category>
    </item>
    <item>
      <title>Upstart script for Apache Solr</title>
      <link>https://www.michaelshadle.com/2013/07/11/upstart-script-for-apache-solr</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2013/07/11/upstart-script-for-apache-solr</guid>
      <pubDate>Fri, 12 Jul 2013 05:20:12 GMT</pubDate>
      <description>(Apologies for not sharing my technical thoughts for six months now!) I was trying to figure out the best way to launch Apache Solr on Ubuntu - and was having issues finding a…</description>
      <content:encoded><![CDATA[<p>(Apologies for not sharing my technical thoughts for six months now!)</p>
<p>I was trying to figure out the best way to launch Apache Solr on Ubuntu - and was having issues finding a nice clean way to do it. I decided after some misc init scripts, that I should look at Upstart. Thankfully someone (mentioned below) already had a working script available to start from.</p>
<p>Assumes:</p>
<ul>
<li>
<p>Solr will be running as user &quot;solr&quot; group &quot;solr&quot;</p>
</li>
<li>
<p>Solr's root where start.jar is located is /home/solr</p>
</li>
<li>
<p>This works well using Solr 4.3.1, Ubuntu 12.04.2 LTS (precise)</p>
</li>
</ul>
<p>Put this in /etc/init/solr.conf:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">start on runlevel [2345]
stop on runlevel [!2345]

<span class="hljs-built_in">kill</span> <span class="hljs-built_in">timeout</span> 30
respawn

setuid solr
setgid solr

script
   <span class="hljs-built_in">chdir</span> /home/solr
   <span class="hljs-built_in">exec</span> /usr/bin/java -jar start.jar
end script
</code></pre>
<p>Big thanks to <a href="http://ericwilson.erics.ws/snippets/2013/4/6/upstart-script-for-solr">Eric Wilson's blog</a> for the initial script. I tweaked it for my specific user/group/location desires.</p>]]></content:encoded>
      <category>software</category>
    </item>
    <item>
      <title>Remapping remote keys for OpenELEC/XBMC</title>
      <link>https://www.michaelshadle.com/2013/01/10/remapping-remote-keys-for-openelecxbmc</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2013/01/10/remapping-remote-keys-for-openelecxbmc</guid>
      <pubDate>Fri, 11 Jan 2013 02:55:23 GMT</pubDate>
      <description>This past week, I set my Parents up with a Raspberry Pi-based OpenELEC unit, which I built for them to replace an extremely dated Buffalo product. (So far I have been pretty…</description>
      <content:encoded><![CDATA[<p>This past week, I set my Parents up with a Raspberry Pi-based OpenELEC unit, which I built for them to replace an extremely dated Buffalo product. (So far I have been pretty surprised as to what this little RPi can do!)</p>
<p>After getting a stable setup going, the last piece of it was getting a remote that they could manage. I was nervous at first because of compatibility concerns and &quot;bleeding edge&quot; software. However, I picked up an &quot;Adesso ARC-1100 Media Center Remote&quot; - which I had seen as being compatible on the XBMC forums, and out of the box, it works great. Truly plug and play.</p>
<p>I wanted to pick up something reasonably priced and <a href="http://www.iguanamicro.com/adarmecere.html">locally</a> (just in case I had to return it, I didn't want to hassle with RMA processes.)</p>
<p>The main issue with the remote is that some buttons are a bit confusing - which is tolerable, but the main offender is the power button. It works out of the box, as one would expect, except that once you power down the OpenELEC/RPi combination, you can't power it back up again (at least not with a USB-powered IR receiver...)</p>
<p>To solve that issue I looked into figuring out how to do some key remapping, to make the power button do something different, or nothing at all. The <a href="http://wiki.openelec.tv/index.php?title=Guide_To_Test_a_Remote_and_Remap_Keys">documentation</a> seems straightforward but made me dizzy for a moment (and is slightly incorrect where remote.xml is), but on the first try I had success. After that, I decided to mess around and see what other buttons I could &quot;disable&quot; essentially (and I decided to see if &lt;null&gt; could be used to map the key to nothing - it seems to work)</p>
<p>Here is the output of that work, it looks simple enough. Put this under /storage/.xbmc/userdata/Lircmap.xml (or via the userdata SMB share)</p>
<pre class="hljs"><code class="language-xml" data-lang="xml">
  
    KEY_POWER 
    KEY_DELETE 
    KEY_SUBTITLE 
    KEY_VOLUMEDOWN 
    KEY_VOLUMEUP 
  

</code></pre>
<p>Sure enough, it all works - now I have a remote solution for them that won't let them get into trouble, and confidence now on how to map keys in the future.</p>
<p>After playing with XBMC on a Pivos AIOS DS, Intel NUC, and OpenELEC on an RPi, I have to say I am happy to see the extensive community involvement in the XBMC project and its derivatives.</p>
<p>Now, I just wish skinning it was as easy...</p>]]></content:encoded>
      <category>openelec</category>
      <category>raspberry-pi</category>
      <category>remotes</category>
      <category>rpi</category>
      <category>toys</category>
      <category>xbmc</category>
    </item>
    <item>
      <title>Shout out to CrashPlan!</title>
      <link>https://www.michaelshadle.com/2012/08/24/shout-out-to-crashplan</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2012/08/24/shout-out-to-crashplan</guid>
      <pubDate>Fri, 24 Aug 2012 09:40:58 GMT</pubDate>
      <description>While I am typically a BackBlaze fan boy (&quot;we&apos;ll always be unlimited&quot; and so cost-effective) I somehow stumbled upon CrashPlan. Which when looking at it and seeing it&apos;s a…</description>
      <content:encoded><![CDATA[<p>While I am typically a BackBlaze fan boy (&quot;we'll always be unlimited&quot; and so cost-effective) I somehow stumbled upon CrashPlan. Which when looking at it and seeing it's a Java-based client initially scared me, but the support for Linux and other OSes got me interested. Not only can I stick it on servers and home Linux boxes (and I have now...) but they even give you tips on how to use an SSH tunnel to connect to their local service. So I can launch a desktop application on my Windows machine and connect to my CrashPlan backup daemon on my server at SoftLayer. Neat.</p>
<p>It is supposed to be totally unlimited as well, and they only charge $12.99 or something for 2-10 computers, vs. a per-computer model from BackBlaze. Also, they don't list support for file shares, but it had no problem backing up one of my samba mounts. (Please don't fix that if it's a bug!)</p>
<p>So while I still consider BackBlaze to be more efficient and easier to use (just &quot;set it and forget it&quot; I will say that CrashPlan has a lot more options, is an opt-in policy (akin to Mozy, etc.) instead of an opt-out by default policy (BackBlaze) and it makes it really easy to list the entire filesystem, and select/deselect at any level of it.</p>
<p>The other interesting/neat thing is you can set it up to backup to friends machines, local storage, attached drives or their CrashPlan Central cloud (which is what they charge the monthly for.)</p>
<p>Since BackBlaze isn't playing in the Linux space yet, and has special ways to check if a filesystem is &quot;local&quot; and such, it looks like I will be using the best of both systems for now. The Java UI does feel a bit &quot;Java-ey&quot; but the price, features and performance of the actual network backups seem well worth it.</p>
<p>So +1 to CrashPlan!</p>]]></content:encoded>
      <category>software</category>
    </item>
    <item>
      <title>One of my favorite parts about conferences is the schwag.</title>
      <link>https://www.michaelshadle.com/2012/08/20/one-of-my-favorite-parts-about-conferences-is-the-schwag</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2012/08/20/one-of-my-favorite-parts-about-conferences-is-the-schwag</guid>
      <pubDate>Mon, 20 Aug 2012 08:10:56 GMT</pubDate>
      <description>I&apos;m a sucker for a free t-shirt. This year was a record - 11 shirts from OSCON 2012, and I missed going to the OpenStack anniversary event where I could have picked up another…</description>
      <content:encoded><![CDATA[<p>I'm a sucker for a free t-shirt. This year was a record - 11 shirts from OSCON 2012, and I missed going to the OpenStack anniversary event where I could have picked up another one. The one disappointment about all of this though is probably half of these shirts are unusable - they're either so thin they couldn't even make &quot;undershirt&quot; status, or such an odd fit (too skinny and long, or too wide and too short.)</p>
<p>So I plead with you, companies, please invest just that little bit more to get higher quality stock. It can't be that much more, and you'll have a greater chance that people will wear those shirts sporting your logo, and not because they picked it up at the local Goodwill. :)</p>
<p>On another note, I apologize for not posting anything in almost seven months. I've been busy and haven't felt like wordsmithing anything I've been up to, or otherwise haven't had anything useful to share.</p>]]></content:encoded>
      <category>uncategorized</category>
    </item>
    <item>
      <title>PHP 5.4 stuff I&apos;m jazzed about...</title>
      <link>https://www.michaelshadle.com/2012/01/28/php54-stuff-im-jazzed-about</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2012/01/28/php54-stuff-im-jazzed-about</guid>
      <pubDate>Sat, 28 Jan 2012 09:10:17 GMT</pubDate>
      <description>I&apos;m always excited to read updates to the NEWS file for each PHP version (yes, I am that big of a PHP fan boy) - and PHP 5.4 has quite a handful of noteworthy changes. I started…</description>
      <content:encoded><![CDATA[<p>I'm always excited to read updates to the NEWS file for each PHP version (yes, I am that big of a PHP fan boy) - and PHP 5.4 has quite a handful of noteworthy changes. I started cutting them out and decided to publish my &quot;this is interesting&quot; or &quot;this is awesome&quot; list...</p>
<p>This is as of PHP 5.4.0 RC6. Note that I didn't put in anything related to OO, as I despise the obsession with OO now in PHP and do my best to live without it.</p>
<p>Misc. notable changes:</p>
<ul>
<li>Added built-in web server that is intended for testing purpose. (Moriyoshi)</li>
<li>Changed default value of &quot;default_charset&quot; php.ini option from ISO-8859-1 to UTF-8. (Rasmus)</li>
<li>Added array dereferencing support. (Felipe)</li>
<li>Added header_register_callback() which is invoked immediately prior to the sending of headers and after default headers have been added. (Scott)</li>
<li>Changed http_response_code() to be able to set a response code. (Kalle)</li>
<li>Added new json_encode() option JSON_PRETTY_PRINT. FR #44331. (Adam)</li>
<li>Changed silent conversion of array to string to produce a notice. (Patrick)</li>
<li>Removed support for putenv(&quot;TZ=..&quot;) for setting the timezone. (Derick)</li>
<li>Removed the timezone guessing algorithm in case the timezone isn't set with date.timezone or date_default_timezone_set(). Instead of a guessed timezone, &quot;UTC&quot; is now used instead. (Derick)</li>
<li>ext/mysql, mysqli and pdo_mysql now use mysqlnd by default. (Johannes) )I think this is in 5.3 though too?)</li>
<li>Expose session status via new function, session_status (FR #52982) (Arpad)</li>
<li>Added support for storing upload progress feedback in session data. (Arnaud)</li>
</ul>
<p>PHP-FPM related:</p>
<ul>
<li>Remove EXPERIMENTAL flag. (fat)</li>
<li>Added partial syslog support (on error_log only). FR #52052. (fat)</li>
<li>Lowered default value for Process Manager. FR #54098. (fat)</li>
<li>Enhance security by limiting access to user defined extensions. FR #55181. (fat)</li>
<li>Added process.max to control the number of process FPM can fork. FR #55166. (fat)</li>
<li>Dropped restriction of not setting the same value multiple times, the last one holds. (giovanni at giacobbi dot net, fat)</li>
</ul>
<p>Removed legacy features:</p>
<ul>
<li>Safe mode and all related ini options. (Kalle)</li>
<li>register_globals and register_long_arrays ini options. (Kalle)</li>
<li>import_request_variables(). (Kalle)</li>
<li>allow_call_time_pass_reference. (Pierrick)</li>
<li>Session bug compatibility mode (session.bug_compat_42 and session.bug_compat_warn ini options). (Kalle)</li>
<li>session_is_registered(), session_register() and session_unregister() functions. (Kalle)</li>
<li>y2k_compliance ini option. (Kalle)</li>
<li>Removed magic_quotes_gpc, magic_quotes_runtime and magic_quotes_sybase ini options. get_magic_quotes_gpc, get_magic_quotes_runtime are kept but always return false, set_magic_quotes_runtime raises an E_CORE_ERROR. (Pierrick, Pierre)</li>
</ul>]]></content:encoded>
      <category>php</category>
      <category>php-fpm</category>
    </item>
    <item>
      <title>PHP.reboot - are you kidding me?</title>
      <link>https://www.michaelshadle.com/2011/10/09/php-reboot-are-you-kidding-me</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/10/09/php-reboot-are-you-kidding-me</guid>
      <pubDate>Sun, 09 Oct 2011 21:22:17 GMT</pubDate>
      <description>Something just cropped up today on HN about a &quot;reboot of PHP&quot; - being a PHP fanboy, I decided to go look. I&apos;ve had my own ideas on what I&apos;d change (or rather, just clean up…</description>
      <content:encoded><![CDATA[<p>Something just cropped up today on HN about a &quot;reboot of PHP&quot; - being a PHP fanboy, I decided to go look. I've had my own ideas on what I'd change (or rather, just clean up, optimize, and purge) from PHP.</p>
<p>The project is here: <a href="https://code.google.com/p/phpreboot/">https://code.google.com/p/phpreboot/</a></p>
<p>Why is this an issue? Well, for one, it's NOT A REBOOT OF PHP. It's a frickin' Java-based re-implementation of some PHP ideas and function names with a completely different syntax, and at the end of the day, it has 99.9% nothing in common with PHP.</p>
<p>Why do people develop in PHP? Because it is PHP. Stop trying to make PHP more like Java, more JSON-y, etc. Why did it become the world's most popular language? Besides for being easy to pick up (too easy, sometimes, which leads to a bunch of garbage and unsecure code), it got there because of what it is.</p>
<p>This &quot;php.reboot&quot; project is just trying to use PHP's popularity and function names to get people to check it out. PHP doesn't have XML/JSON/SQL style constructs (although the new array syntax sure does look like an attempt to emulate JSON, cough), it has structure - that's what &quot;$&quot; and &quot;;&quot; are for - denoting specific constructs in the language. If people don't want to develop using &quot;$&quot; or &quot;;&quot; go switch to another language that doesn't, that is already established.</p>
<p>I am tired of seeing blog posts and other items pop up every so often &quot;why PHP wants to be more like Java&quot; or &quot;10 things PHP can learn from Ruby&quot; - if you're trying to adapt PHP to another language, just use the other language. Period.</p>
<p>Some of the ideas in this project might be neat, or good; but in the end, it's not a &quot;reboot of PHP&quot; and stop labeling it as one.</p>]]></content:encoded>
      <category>php</category>
    </item>
    <item>
      <title>nginx goes &quot;Prime time&quot;</title>
      <link>https://www.michaelshadle.com/2011/07/18/nginx-goes-prime-time</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/07/18/nginx-goes-prime-time</guid>
      <pubDate>Mon, 18 Jul 2011 17:05:47 GMT</pubDate>
      <description>Today, Igor announced that he is establishing a company behind nginx, citing that he and some others are going to be focusing more seriously on development, support, etc. This is…</description>
      <content:encoded><![CDATA[<p>Today, Igor announced that he is establishing a company behind nginx, citing that he and some others are going to be focusing more seriously on development, support, etc. This is exciting, as it proves how serious the project has become. For a long time, nginx has been regularly updated, and support has been typically very reliable, but at the end of the day, the internals of nginx development and features and such have largely been a mystery. It sounds like now we'll all benefit from increased transparency and much more focus on the end-users and support for developers in a more structured and formal way.</p>
<p>I, for one, am excited to see things like a roadmap and making it easier for contributors to help out.</p>
<p>Read Igor's post <a href="http://nginx.org/pipermail/nginx/2011-July/028021.html">here</a>.</p>]]></content:encoded>
      <category>nginx</category>
    </item>
    <item>
      <title>nginx hits 1.0(.0)</title>
      <link>https://www.michaelshadle.com/2011/04/12/nginx-hits-1-0-0</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/04/12/nginx-hits-1-0-0</guid>
      <pubDate>Tue, 12 Apr 2011 10:16:31 GMT</pubDate>
      <description>nginx, my webserver du joir, announced its 1.0.0 launch today. Along with the announcement, Igor has also posted a public SVN repository to grab the code from (which seems to…</description>
      <content:encoded><![CDATA[<p><a href="http://nginx.org/">nginx</a>, my webserver du joir, announced its 1.0.0 launch today. Along with the announcement, Igor has also posted a public SVN repository to grab the code from (which seems to include a lot of historical versions, if not the whole thing!)</p>
<p>He hasn't setup a web-based SVN option yet (cough, cough, I bet it would be if nginx supported SVN's DAV needs :)) - but you can hit it up using a native SVN client: svn://svn.nginx.org - note, I would only grab &quot;/nginx/trunk&quot; as otherwise you'll get a few years worth of code, if not the entire nine years.</p>
<p>At first I thought this was a joke, seeing the announcement for 1.0.0 - sounds like it just started. But one must remember, he's always used pre-1.0 for past versions.</p>
<p><strong>Update:</strong></p>
<p>MTecknology maintains a <a href="http://ppa.launchpad.net/nginx/stable/ubuntu">PPA</a> and has already built a package for 1.0.0. The quick and dirty method to update:</p>
<pre class="hljs"><code class="language-sql" data-lang="sql">apt<span class="hljs-operator">-</span><span class="hljs-keyword">get</span> install python<span class="hljs-operator">-</span>software<span class="hljs-operator">-</span>properties
<span class="hljs-keyword">add</span><span class="hljs-operator">-</span>apt<span class="hljs-operator">-</span>repository ppa:nginx<span class="hljs-operator">/</span>stable
apt<span class="hljs-operator">-</span><span class="hljs-keyword">get</span> <span class="hljs-keyword">update</span>
</code></pre>
<p>This will provide you a handful of new packages, by default the &quot;nginx&quot; package is a dummy package that will provide &quot;nginx-full&quot; and should be the only one you really need to care about.</p>
<pre class="hljs"><code class="language-sql" data-lang="sql">nginx<span class="hljs-operator">-</span>dbg <span class="hljs-operator">-</span> Debugging symbols <span class="hljs-keyword">for</span> nginx
nginx <span class="hljs-operator">-</span> small, but very powerful <span class="hljs-keyword">and</span> efficient web server <span class="hljs-keyword">and</span> mail proxy
nginx<span class="hljs-operator">-</span>common <span class="hljs-operator">-</span> small, but very powerful <span class="hljs-keyword">and</span> efficient web server (common files)
nginx<span class="hljs-operator">-</span>doc <span class="hljs-operator">-</span> small, but very powerful <span class="hljs-keyword">and</span> efficient web server (documentation)
nginx<span class="hljs-operator">-</span>extras <span class="hljs-operator">-</span> nginx web server <span class="hljs-keyword">with</span> <span class="hljs-keyword">full</span> <span class="hljs-keyword">set</span> <span class="hljs-keyword">of</span> core modules <span class="hljs-keyword">and</span> extras
nginx<span class="hljs-operator">-</span>extras<span class="hljs-operator">-</span>dbg <span class="hljs-operator">-</span> Debugging symbols <span class="hljs-keyword">for</span> nginx (extras)
nginx<span class="hljs-operator">-</span><span class="hljs-keyword">full</span> <span class="hljs-operator">-</span> nginx web server <span class="hljs-keyword">with</span> <span class="hljs-keyword">full</span> <span class="hljs-keyword">set</span> <span class="hljs-keyword">of</span> core modules
nginx<span class="hljs-operator">-</span><span class="hljs-keyword">full</span><span class="hljs-operator">-</span>dbg <span class="hljs-operator">-</span> Debugging symbols <span class="hljs-keyword">for</span> nginx (<span class="hljs-keyword">full</span>)
nginx<span class="hljs-operator">-</span>light <span class="hljs-operator">-</span> nginx web server <span class="hljs-keyword">with</span> minimal <span class="hljs-keyword">set</span> <span class="hljs-keyword">of</span> core modules
nginx<span class="hljs-operator">-</span>light<span class="hljs-operator">-</span>dbg <span class="hljs-operator">-</span> Debugging symbols <span class="hljs-keyword">for</span> nginx (light)
</code></pre>]]></content:encoded>
      <category>nginx</category>
    </item>
    <item>
      <title>Poor man&apos;s Global Redirect for Drupal 6.x</title>
      <link>https://www.michaelshadle.com/2011/03/22/poor-mans-global-redirect-for-drupal-6x</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/03/22/poor-mans-global-redirect-for-drupal-6x</guid>
      <pubDate>Wed, 23 Mar 2011 05:31:23 GMT</pubDate>
      <description>I was moving a customer&apos;s site from an old HTML and individual PHP page site to a friendly URL site managed by Drupal, and I only cared about intercepting URLs with those file…</description>
      <content:encoded><![CDATA[<p>I was moving a customer's site from an old HTML and individual PHP page site to a friendly URL site managed by Drupal, and I only cared about intercepting URLs with those file extensions. I installed <a href="http://drupal.org/project/globalredirect">Global Redirect</a> on a Drupal 6.x site, and the entire site started going into an infinite redirect, before I even had time to configure it. I had to use Drush to disable the module, and immediately uninstalled Global Redirect since I didn't have time to debug what was going on, and hacked this up.</p>
<p>I didn't really need this to do much. The code is simple and there is no UI to manage it, but it works, and even gives you cute little X-Redirect headers to let you know if it was executed and if it found a match. It would be easy enough to take that if() out and have it check any URL (just be sure to remove the fallback :))</p>
<pre class="hljs"><code class="language-php" data-lang="php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo_init</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">if</span>(<span class="hljs-title function_ invoke__">stristr</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;REQUEST_URI&#x27;</span>], <span class="hljs-string">&#x27;.php&#x27;</span>) || <span class="hljs-title function_ invoke__">stristr</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;REQUEST_URI&#x27;</span>], <span class="hljs-string">&#x27;.htm&#x27;</span>)) {
        <span class="hljs-variable">$old</span> = <span class="hljs-title function_ invoke__">parse_url</span>(<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;REQUEST_URI&#x27;</span>], PHP_URL_PATH);
        <span class="hljs-variable">$new</span> = <span class="hljs-title function_ invoke__">db_result</span>(<span class="hljs-title function_ invoke__">db_query</span>(<span class="hljs-string">&quot;SELECT new_url FROM custom_redirect WHERE old_url = &#x27;%s&#x27;&quot;</span>, <span class="hljs-variable">$old</span>));
        <span class="hljs-keyword">if</span>(<span class="hljs-variable">$new</span>) {
            <span class="hljs-title function_ invoke__">watchdog</span>(<span class="hljs-string">&#x27;foo&#x27;</span>, <span class="hljs-variable">$old</span>.<span class="hljs-string">&#x27; found in the custom_redirect table&#x27;</span>, <span class="hljs-literal">NULL</span>, WATCHDOG_INFO);
            <span class="hljs-title function_ invoke__">header</span>(<span class="hljs-string">&#x27;X-Redirect: Found&#x27;</span>);
            <span class="hljs-title function_ invoke__">drupal_goto</span>(<span class="hljs-string">&#x27;http://&#x27;</span>.<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;HTTP_HOST&#x27;</span>].<span class="hljs-variable">$new</span>, <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-number">301</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-title function_ invoke__">watchdog</span>(<span class="hljs-string">&#x27;foo&#x27;</span>, <span class="hljs-variable">$old</span>.<span class="hljs-string">&#x27; NOT found in the custom_redirect table&#x27;</span>, <span class="hljs-literal">NULL</span>, WATCHDOG_ERROR);
            <span class="hljs-title function_ invoke__">header</span>(<span class="hljs-string">&#x27;X-Redirect: Not Found&#x27;</span>);
            <span class="hljs-title function_ invoke__">drupal_goto</span>(<span class="hljs-string">&#x27;http://&#x27;</span>.<span class="hljs-variable">$_SERVER</span>[<span class="hljs-string">&#x27;HTTP_HOST&#x27;</span>].<span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-string">&#x27;&#x27;</span>, <span class="hljs-number">302</span>);
        }
    }
}
</code></pre>
<p>The table?</p>
<pre class="hljs"><code class="language-sql" data-lang="sql"><span class="hljs-keyword">CREATE TABLE</span> custom_redirect (
  old_url <span class="hljs-type">varchar</span>(<span class="hljs-number">150</span>) <span class="hljs-keyword">NOT NULL</span>,
  new_url <span class="hljs-type">varchar</span>(<span class="hljs-number">150</span>) <span class="hljs-keyword">NOT NULL</span>,
  <span class="hljs-keyword">PRIMARY KEY</span> (old_url)
) ENGINE<span class="hljs-operator">=</span>MyISAM <span class="hljs-keyword">DEFAULT</span> CHARSET<span class="hljs-operator">=</span>utf8;
</code></pre>
<p>Enjoy. Totally could have Drupal'ed that up and made a hook_install() for the schema too, right? :p</p>]]></content:encoded>
      <category>drupal</category>
      <category>php</category>
    </item>
    <item>
      <title>How I sped up my MySQL restores</title>
      <link>https://www.michaelshadle.com/2011/02/25/how-i-sped-up-my-mysql-restores</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/02/25/how-i-sped-up-my-mysql-restores</guid>
      <pubDate>Fri, 25 Feb 2011 12:12:02 GMT</pubDate>
      <description>I want to share this with the world, as it may have been helpful up front for me. I had to move a database that is 13gb on the filesystem (not including the shared ibdata file) -…</description>
      <content:encoded><![CDATA[<p>I want to share this with the world, as it may have been helpful up front for me. I had to move a database that is 13gb on the filesystem (not including the shared ibdata file) - the database is a mixture of MyISAM and InnoDB tables. That's not an extremely large or complex database, however, when I ran the export script, it only took a couple minutes. Great, I figured import would take longer, but not as long as it actually was originally.</p>
<p>I didn't do the math, but it would have probably taken over 10-15 hours to restore the database from the mysqldump. There's a couple easy tweaks I did not use. For one, I used --skip-opt and made my mysqldump files full INSERT statements (for verbosity and the ability to &quot;diff&quot; them if I ever needed to) - this was stolen from a backup script I wrote.</p>
<p>If you read the documentation/blogs, it says to use --opt when running mysqldump for faster imports. Well, duh! While I was at it, I also tweaked a couple other things. Right now it is moving MUCH faster. What did I do?</p>
<ul>
<li>
<p>On the source, I used mysqldump --opt (it seemed to dump the database faster too)</p>
</li>
<li>
<p>On the destination, I set innodb_flush_log_at_trx_commit to &quot;0&quot; in my.cnf for the time being. This server isn't used yet, so that's safe.</p>
</li>
<li>
<p>I also put &quot;SET AUTOCOMMIT=0;&quot; at the top of the script, and &quot;COMMIT;&quot; at the bottom of the script. I don't need any commits until the end, this is a fresh import.</p>
</li>
</ul>
<p>The results are not very scientific, but here's how it breaks down so far (still in the middle of the process)</p>
<ul>
<li>
<p>Without these tweaks, at 107 minutes it was only at 2.2gb out of 13gb.</p>
</li>
<li>
<p>Without these tweaks, at 12 minutes it was at 4.5gb out of 13gb.</p>
</li>
</ul>
<p>I think this will save my bacon, I wish I had done this sooner and not wasted that two hours originally. Someone in #mysql recommended I look at <a href="http://www.percona.com/software/percona-xtrabackup/">XtraBackup</a>, but it seemed like too much to learn and attempt my first run at it while I was having to do a  production migration.</p>]]></content:encoded>
      <category>software</category>
    </item>
    <item>
      <title>Setting PHP INI parameters from nginx</title>
      <link>https://www.michaelshadle.com/2011/02/11/setting-php-ini-parameters-from-nginx</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/02/11/setting-php-ini-parameters-from-nginx</guid>
      <pubDate>Fri, 11 Feb 2011 11:29:28 GMT</pubDate>
      <description>A little known feature in PHP-FPM 5.3.3+ (since it was integrated into PHP core) is that you can actually define PHP INI parameters inside of your nginx configuration. This…</description>
      <content:encoded><![CDATA[<p>A little known feature in PHP-FPM 5.3.3+ (since it was integrated into PHP core) is that you can actually define PHP INI parameters inside of your nginx configuration. This bridges some of the desire to have &quot;php_value&quot; and &quot;php_admin_value&quot; from Apache available. It's not user-override-able, but things like htscanner or newer PHP 5.3 features could address some of that.</p>
<p>This is cool, and I wasn't sure it actually got in a build or not, I remember it was mentioned or discussed, but sure enough, Jérôme coded it and got it in to FPM in core. So it is available to all, and he welcomes the feedback - see <a href="http://forum.nginx.org/read.php?2,172118">this thread</a> on the nginx mailing list.</p>
<p>Due to limitations in the FastCGI protocol, you have to pass all the parameters you want as a single string, separated by &quot;\n&quot; - it's not the cleanest looking configuration, but that's how it is for now. I spitballed a different approach to it, but at the moment I believe it will be unlikely to get adopted.</p>
<p>If you're like me, you're probably looking for the code samples almost immediately. Here's your examples. Note that PHP_VALUE and PHP_ADMIN_VALUE are both legitimate keys, the difference being that PHP_ADMIN_VALUE does not allow the user to override the value using ini_set() - see <a href="http://php.net/manual/en/configuration.changes.php">the manual</a> for more infomation.</p>
<p>Single value:</p>
<pre class="hljs"><code>fastcgi_param PHP_VALUE sendmail_from=direct@prout.com;
</code></pre>
<p>Multiple values, manually line-broken:</p>
<pre class="hljs"><code>fastcgi_param PHP_VALUE &quot;sendmail_from=chroot@prout.com
precision=42&quot;;
</code></pre>
<p>Multiple values, with the \n in there to clearly call it out:</p>
<pre class="hljs"><code>fastcgi_param PHP_VALUE &quot;sendmail_from=chroot@prout.com \n precision=42&quot;;
</code></pre>
<p>More information is available in the <a href="http://bugs.php.net/bug.php?id=51595">feature request</a> on the PHP bug tracker.</p>]]></content:encoded>
      <category>nginx</category>
      <category>php</category>
      <category>php-fpm</category>
    </item>
    <item>
      <title>Verizon and Frontier have your password - just FYI</title>
      <link>https://www.michaelshadle.com/2011/02/05/verizon-and-frontier-have-your-password-just-fyi</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/02/05/verizon-and-frontier-have-your-password-just-fyi</guid>
      <pubDate>Sat, 05 Feb 2011 21:22:38 GMT</pubDate>
      <description>It was weird to see a company nowadays still have your password stored somewhere plaintext.</description>
      <content:encoded><![CDATA[<p>It was weird to see a company nowadays still have your password stored somewhere plaintext.</p>
<figure><a href="https://www.michaelshadle.com/media/1789753091810-cb9491e5e4-e29fc2.png"><img src="https://www.michaelshadle.com/media/1789753091810-cb9491e5e4-e29fc2.png" alt="" title="frontier-password-plaintext"></a></figure>]]></content:encoded>
      <category>consumerism</category>
    </item>
    <item>
      <title>Mozy stops &quot;unlimited&quot; plan... and I mosey on</title>
      <link>https://www.michaelshadle.com/2011/02/01/mozy-stops-unlimited-plan-and-i-mosey-on</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/02/01/mozy-stops-unlimited-plan-and-i-mosey-on</guid>
      <pubDate>Tue, 01 Feb 2011 23:57:40 GMT</pubDate>
      <description>I&apos;ve been a fan of Backblaze for a long time, and prefer it and recommend it over Mozy time and time again. Mozy was the golden child for a bit, but now the prize goes to…</description>
      <content:encoded><![CDATA[<p>I've been a fan of Backblaze for a long time, and prefer it and recommend it over Mozy time and time again. Mozy was the golden child for a bit, but now the prize goes to Backblaze, with its more efficient backup client, faster network speeds and same price. I've been using Backblaze for over a year by itself on many machines and have been quite happy. For the sake of redundancy though, a couple months ago I decided to subscribe to Mozy as well, just out of paranoia.</p>
<p>Due to the fact that their service always uses over 100 megs of RAM, and seems to continuously get stuck on certain files, I was planning on getting rid of it soon. Today's announcement made this decision even easier though, as now they've decided to go the way of other companies with tiered pricing models. With how cheap technology continuously gets, any company marking prices up really pisses me off.</p>
<p>So, I give a profane salute to you, Mozy, as you have now joined the ranks of companies I feel personally displeased with, and definitely will not recommend (not that I really did anyway.)</p>
<p>Even AT&amp;T (one of the main companies I despise) let people grandfather in their unlimited plans, and cell networks take a lot more beating than a backup service with hard drive prices going down every day. Adding more servers to a rack is a lot harder than adding cell tower capacity. That type of &quot;next month you'll be forced to change&quot; does not sit well with me.</p>
<blockquote>
<p>Dear Michael,</p>
<p>Thanks for being a valued Mozy subscriber. For the first time since 2006, we're adjusting the price of our MozyHome service and wanted to give you a heads up. As part of this change, we're replacing our MozyHome Unlimited backup plan and introducing the following tiered storage plans:</p>
<p>50 GB for $5.99 per month (includes backup for 1 computer)<br>
125 GB for $9.99 per month (includes backup for up to 3 computers)</p>
<p>You may add additional computers (up to 5 in total) or 20 GB increments of storage to either of the plans, each for a monthly cost of $2.00.</p>
<p>While this policy takes effect for new MozyHome customers starting today, your MozyHome Unlimited subscription is still valid for the duration of your current monthly term. In order to ensure uninterrupted service, you'll need to select a new renewal plan.</p>
</blockquote>]]></content:encoded>
      <category>consumerism</category>
      <category>software</category>
    </item>
    <item>
      <title>United States of Google</title>
      <link>https://www.michaelshadle.com/2011/01/23/united-states-of-google</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/01/23/united-states-of-google</guid>
      <pubDate>Sun, 23 Jan 2011 08:17:45 GMT</pubDate>
      <description>Just saw this code on a site, I forgot this good stuff existed. I&apos;ve seen it before in a post about Google&apos;s web fonts and using their jsapi to load the webfont.js file, and I…</description>
      <content:encoded><![CDATA[<p>Just saw this code on a site, I forgot this good stuff existed. I've seen it before in a post about Google's web fonts and using their jsapi to load the webfont.js file, and I just rediscovered it again. I love Google. Using their clout to better the web (IMHO.) You can call me a fanboy - I don't care.</p>
<pre class="hljs"><code class="language-javascript" data-lang="javascript">&lt;script type=<span class="hljs-string">&quot;text/javascript&quot;</span> src=<span class="hljs-string">&quot;http://www.google.com/jsapi&quot;</span>&gt;&lt;/script&gt;
<span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript">google.<span class="hljs-title function_">load</span>(<span class="hljs-string">&quot;jquery&quot;</span>, <span class="hljs-string">&quot;1.4&quot;</span>);</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
<span class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript">google.<span class="hljs-title function_">load</span>(<span class="hljs-string">&quot;jqueryui&quot;</span>, <span class="hljs-string">&quot;1.7.2&quot;</span>);</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>]]></content:encoded>
      <category>development</category>
    </item>
    <item>
      <title>True &quot;Incognito&quot; mode for Google chrome</title>
      <link>https://www.michaelshadle.com/2011/01/08/true-incognito-mode-for-google-chrome</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2011/01/08/true-incognito-mode-for-google-chrome</guid>
      <pubDate>Sat, 08 Jan 2011 08:48:01 GMT</pubDate>
      <description>I hate Windows. I do. This is a very hacky, no-garbage-collection, but still &quot;working good enough&quot; script. At the advice of #chromium on freenode, when asked about cookie sharing…</description>
      <content:encoded><![CDATA[<p>I hate Windows. I do.</p>
<p>This is a very hacky, no-garbage-collection, but still &quot;working good enough&quot; script. At the advice of #chromium on freenode, when asked about cookie sharing between Incognito windows, I was told it's been discussed before, and I got the information on how to make sure that your Incognito windows don't share information or cookies by forcing separate user data directories.</p>
<p>I'm not really worried about privacy, I'm more annoyed that I launch separate Incognito windows and it shares cookies between them, which is sort of against the point. I have to login to the same sites over and over under different accounts for different clients, and it's a PITA.</p>
<p>Major things to note:</p>
<ul>
<li>
<p>This assumes you'll run some sort of &quot;temp directory cleanup&quot; tool on your own for Windows. This doesn't have any concept of &quot;oh yeah, I have to cleanup that temp directory I made&quot;</p>
</li>
<li>
<p>None of your extensions, bookmarks, settings, etc. will be remembered in this session. It's completely barren.</p>
</li>
<li>
<p>You will never (assuming the GUID is unique) get the same session more than once.</p>
</li>
</ul>
<p>As I said, it's hacky, and you'll need to change a couple of the paths. I couldn't figure it out elegantly, and I was getting tired of trying to find script examples on the net (why is it so hard to find code that works together for Microsoft languages?)</p>
<p>Perhaps someday soon Chrome or someone will develop something more robust for this. For now, if you want - this does seem to work, at least on my XP SP3 system.</p>
<p>Note: This is vbscript. Make a file called &quot;incognito.vbs&quot; or something and it should work.</p>
<pre class="hljs"><code class="language-vbnet" data-lang="vbnet"><span class="hljs-comment">&#x27; keep us honest</span>
<span class="hljs-keyword">Option</span> <span class="hljs-keyword">Explicit</span>

<span class="hljs-comment">&#x27; because we have to</span>
<span class="hljs-keyword">Dim</span> strDirectory
<span class="hljs-keyword">Dim</span> strTempDirectory
<span class="hljs-keyword">Dim</span> TypeLib
<span class="hljs-keyword">Dim</span> objFSO
<span class="hljs-keyword">Dim</span> objShell
<span class="hljs-keyword">Dim</span> strChromePath

<span class="hljs-comment">&#x27; change this if you want - anything with spaces has to have be wrapped in triple quotes</span>
strChromePath = <span class="hljs-string">&quot;&quot;&quot;C</span>:\Documents <span class="hljs-built_in">and</span> Settings\mike\Local Settings\Application Data\Google\Chrome\Application\chrome.exe<span class="hljs-string">&quot;&quot;&quot;
strTempDirectory = &quot;</span>C:\Windows\Temp<span class="hljs-string">&quot;

&#x27; make a clean guid
Set TypeLib = CreateObject(&quot;</span>Scriptlet.TypeLib<span class="hljs-string">&quot;)
strDirectory = TypeLib.Guid
strDirectory = Replace(strDirectory, &quot;</span>{<span class="hljs-string">&quot;, &quot;&quot;)
strDirectory = Replace(strDirectory, &quot;</span>}<span class="hljs-string">&quot;, &quot;&quot;)
strDirectory = strTempDirectory &amp; &quot;</span>\<span class="hljs-string">&quot; &amp; strDirectory

&#x27; create the directory
Set objFSO = CreateObject(&quot;</span>Scripting.FileSystemObject<span class="hljs-string">&quot;)
objFSO.CreateFolder(strDirectory)

&#x27; launch it, or fail
If err.number = vbEmpty then
   Set objShell = CreateObject(&quot;</span>WScript.Shell<span class="hljs-string">&quot;)
   objShell.run (strChromePath &amp; &quot;</span> --incognito --no-first-run --user-data-dir=<span class="hljs-string">&quot; &amp; strDirectory)
Else
   WScript.echo &quot;</span>VBScript <span class="hljs-keyword">Error</span>: <span class="hljs-string">&quot; &amp; err.number
End If

&#x27; cleanup
Set TypeLib = nothing
set objFSO = nothing
Set objShell = nothing

&#x27; quit
WScript.Quit()
</span></code></pre>]]></content:encoded>
      <category>development</category>
      <category>software</category>
    </item>
    <item>
      <title>PHP 5.2.15 released, patch updated</title>
      <link>https://www.michaelshadle.com/2010/12/09/php-5-2-15-released-patch-updated</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/12/09/php-5-2-15-released-patch-updated</guid>
      <pubDate>Fri, 10 Dec 2010 03:01:09 GMT</pubDate>
      <description>PHP 5.2.15 was released today, and I&apos;ve made a copy of the previous patch. It still applies without any issues (a &quot;make test&quot; looks good) - this is supposed to be the latest…</description>
      <content:encoded><![CDATA[<p>PHP 5.2.15 was released today, and I've made a copy of the previous patch. It still applies without any issues (a &quot;make test&quot; looks good) - this is supposed to be the latest version of PHP 5.2.x.</p>
<p>Download it <a href="http://php-fpm.org/downloads/php-5.2.15-fpm-0.5.14.diff.gz">here</a>.</p>
<p>I highly recommend upgrading to PHP 5.3.3+ with the more updated/better FPM version (among a million other enhancements) that is bundled in core now. Coincidentally, PHP 5.3.4 came out today as well, with a handful of FPM bug fixes/features (see my other blog post or the NEWS file.)</p>
<p>Enjoy!</p>]]></content:encoded>
      <category>php</category>
      <category>php-fpm</category>
    </item>
    <item>
      <title>Netflix jumps on the fleecing bandwagon</title>
      <link>https://www.michaelshadle.com/2010/11/22/netflix-jumps-on-the-fleecing-bandwagon</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/11/22/netflix-jumps-on-the-fleecing-bandwagon</guid>
      <pubDate>Mon, 22 Nov 2010 23:39:46 GMT</pubDate>
      <description>If you&apos;ve read some older posts, I have praised Netflix for multiple reasons: Great service Easy-to-use, feature-rich but not overbearing website Fast delivery times Actually…</description>
      <content:encoded><![CDATA[<p>If you've read some older posts, I have praised Netflix for multiple reasons:</p>
<ul>
<li>
<p>Great service</p>
</li>
<li>
<p>Easy-to-use, feature-rich but not overbearing website</p>
</li>
<li>
<p>Fast delivery times</p>
</li>
<li>
<p>Actually reduced the price of my plan voluntarily</p>
</li>
</ul>
<p>Today I've got some bad news though. I just received an email notifying me that my plan will increase $3/month. Normally I wouldn't be as vocal, but this is on top of the deals they've made with studios to delay releases ~30 days. Netflix <a href="http://techcrunch.com/2009/11/10/we-know-hollywood-is-this-dumb-et-tu-netflix/">claims it will receive huge discounts</a> and the <a href="http://www.prnewswire.com/news-releases/twentieth-century-fox-and-netflix-announce-comprehensive-strategic-agreement-that-includes-physical-and-digital-distribution-90333649.html">press release for Fox</a> says it will more of their library to be streamed. It's obvious the studios are supposedly hoping this ~30 day window will encourage consumers to rent/buy DVDs normally. Most sites I've read think it will just cause piracy to rise. I'm inclined to agree.</p>
<p>While the movie delay originally annoyed me, it wasn't enough for me to get too angry over. I'm so busy most of the time that 30 days passes me by in the blink of an eye. I don't believe Redbox has that restriction in place, so one could go rent a movie immediately from them still if they wanted.</p>
<p>However, now they are increasing costs on me while delivering less service. That I can't keep quiet about.</p>
<p>So with a heavy heart right now, I have to -2 Netflix. I kept the original movie delay -1 to myself. But now they get both negative marks at once for this new move. I really need to start a point system.</p>]]></content:encoded>
      <category>consumerism</category>
    </item>
    <item>
      <title>I was wrong.</title>
      <link>https://www.michaelshadle.com/2010/11/18/i-was-wrong</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/11/18/i-was-wrong</guid>
      <pubDate>Fri, 19 Nov 2010 05:51:50 GMT</pubDate>
      <description>I was wrong, and I&apos;m happy to admit it. I was worried that if FPM was to ever make it in to PHP core, it would stagnate and become part of such a big machine that it would take…</description>
      <content:encoded><![CDATA[<p>I was wrong, and I'm happy to admit it.</p>
<p>I was worried that if FPM was to ever make it in to PHP core, it would stagnate and become part of such a big machine that it would take forever to receive updates. However, since its adoption into PHP 5.3.3, Jérôme has been hacking away on it and I was happy to see that in 5.3.4RC1, a handful of changes are being included:</p>
<ul>
<li>
<p>Added '-p/--prefix' to php-fpm to use a custom prefix and run multiple instances. (fat)</p>
</li>
<li>
<p>Added custom process title for FPM. (fat)</p>
</li>
<li>
<p>Added '-t/--test' to php-fpm to check and validate FPM conf file. (fat)</p>
</li>
<li>
<p>Added statistics about listening socket queue length for FPM. (andrei dot nigmatulin at gmail dot com, fat)</p>
</li>
<li>
<p>Fixed inconsistent backlog default value (-1) in FPM on many systems. (fat)</p>
</li>
<li>
<p>Fixed bug #52674 (FPM Status page returns inconsistent Content-Type headers). (fat)</p>
</li>
<li>
<p>Fixed bug #52498 (libevent was not only linked to php-fpm). (fat)</p>
</li>
</ul>
<p>Thanks guys, I am counting the days until I can finally use PHP 5.3. I also discovered the new magic variable <strong>DIR</strong> exists a couple weeks ago - between everything, I am jonesing to move badly!</p>
<p><em>(For those wondering, &quot;fat&quot; is Jérôme's pseudonym.)</em></p>]]></content:encoded>
      <category>php</category>
      <category>php-fpm</category>
    </item>
    <item>
      <title>Pidoco - rapid prototyping/wireframing - why didn&apos;t I find this before?</title>
      <link>https://www.michaelshadle.com/2010/11/11/pidoco-rapid-prototypingwireframing-why-didnt-i-find-this-before</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/11/11/pidoco-rapid-prototypingwireframing-why-didnt-i-find-this-before</guid>
      <pubDate>Thu, 11 Nov 2010 20:40:35 GMT</pubDate>
      <description>A while ago, I was looking for tools to do prototyping/wireframing so I could explain my ideas a bit better than some crappy sketched out &quot;wireframes&quot; on paper. For some reason…</description>
      <content:encoded><![CDATA[<p>A while ago, I was looking for tools to do prototyping/wireframing so I could explain my ideas a bit better than some crappy sketched out &quot;wireframes&quot; on paper. For some reason, this one did not come up, so I want to help them gain exposure for being so awesome.</p>
<p>I just discovered this tool in the last hour. It not only  allows you to make wireframes, but actually usable prototypes - with links to external sites and other pages inside of the prototype, pull in external images and content, has layers like photoshop ... the list goes on and on. Best part is the learning curve was quite simple. I found another tool which was an Adobe AIR-based app, if I recall, but it was a bit cryptic and hard to use. This thing allows you to even invite people to do usability testing on your prototype, record their movements, leave comments, etc. Best of all, the cost is extremely reasonable!</p>
<p>There's simply too much to name off and now all I want to do for the next month is prototype out all my ideas!</p>
<p><a href="https://pidoco.com/">https://pidoco.com/</a></p>]]></content:encoded>
      <category>development</category>
      <category>software</category>
    </item>
    <item>
      <title>Drupal is NOT a CMS.</title>
      <link>https://www.michaelshadle.com/2010/10/09/drupal-is-not-a-cms</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/10/09/drupal-is-not-a-cms</guid>
      <pubDate>Sat, 09 Oct 2010 22:19:03 GMT</pubDate>
      <description>Contrary to what you may call it, and even what they say it is - a &quot;Content Management Platform&quot; - I consider it to be an extensible core framework that &quot;happens to ship with many…</description>
      <content:encoded><![CDATA[<p>Contrary to what you may call it, and even what they say it is - a &quot;Content Management Platform&quot; - I consider it to be an extensible core framework that &quot;happens to ship with many content related features by default.&quot;</p>
<p>Stripping it down to bare bones would reveal a flexible and fairly well designed framework that can be used for anything really.</p>
<p>That's my major beef with Drupal - that it ships with so much content-specific functionality in place. For instance a node is something everyone universally agrees is a &quot;great concept&quot; - a basic item that is extended by custom options (CCK is the model of how easy this is) - but nodes still have a &quot;Title&quot; and a &quot;Body&quot; and publishing options and other fields that shouldn't be there in a truly generic system. The idea of one central basic element though is spot-on in my mind. With all that in mind, I begin my thoughts...</p>
<p><strong>When it comes down to it, almost everything can be considered some form of a &quot;content&quot; item.</strong> For example, I designed something to track transactions. At first I cheated and used CCK and just made some custom fields. I also made a version using Drupal's schema API that just made a normal database table, to skip any CCK overhead and node &quot;addons&quot; Drupal glues on by default. However, the overhead aside, I was able to use this system and with not a lot of code, make a fully functional transaction tracking system based off of node concepts. I used CCK as a &quot;schema designing&quot; frontend, and could use Views to get the information back out in a variety of ways.</p>
<p>Is a transaction &quot;content&quot; in the common sense of the word? Not at all. It's a reference to someone purchasing something, in this case a user purchased another type of node - so really it was just a user reference and a node reference. I didn't care about the &quot;Publishing options&quot; or any of the other Drupal-related built-in node specifics, and anything else that may attach itself to nodes - Pathauto, Fivestar, etc.</p>
<p>I [ab]used the node-based system and CCK's UI to make myself a flexible schema to track transactions. I was also able to use pure API to create a database table and manually track the information, and skip any of the hooks related to node processing (Pathauto, Fivestar, publishing options, etc.) - which one was better? Well, I'm still deciding that. By using the node method I can easily expose it in a view. I am not sure I can using custom schema (I think someone told me I could but I haven't tried yet) - I'd really like to use Views for it, and be lazy on the delivery side of it. By going custom, I track only what I want in the database and save probably many levels of pre- and post-processing on the result set.</p>
<p>Getting back to my original statement - Drupal's foundation is pretty solid. It enables anything to be accomplished, it's just that damn middle layer that I wish would be more decoupled and moved into modules that can be enabled or disabled. For the most part, people who use Drupal seem to use it mainly for it's CMS/&quot;Content Management Platform&quot; capabilities just fine. Some of my sites require custom work though, and that is where I enjoy the framework/platform's underlying capabilities.</p>
<p>Typically when developing a site, there are common elements such as user login/registration/roles and management, form processing, XSS/CSRF/other attack vector protection, output encoding, data and request normalization, etc. I've built my own little library of functions and even a bit of a stub framework to use them which do a lot of this. Drupal however has already generalized most of this and provides it to you for no cost.</p>
<p>Frameworks in the typical definitinion such as RoR, Symfony, and half a million others give you the basics, but don't give you that much. It's still up to you to create everything else. While I may whine about Drupal's content-heavy core packaging, it does provide some built-ins that I do find useful to be included. So I guess that can be chalked up to some personal opinion - I would rather the it push the content stuff out to modules (and strip nodes down to even simpler basic structure) yet keep the user registration, login, role and capabilities and form processing available.</p>
<p>All in all, I am having fun looking through the directories of modules out there, and trying to approach things with a more Drupal-eqsue model in mind, understanding that I will sacrifice some performance and add some overhead, but also save myself the headache of all those tedious user submission and form processing screens and such. That's usually where typical self-coded projects seem to start trailing off for me, is winding up getting into the user interaction piece of it. Database design, delivery - that's easy. Form processing and user experience? Annoying as hell :)</p>]]></content:encoded>
      <category>drupal</category>
    </item>
    <item>
      <title>How to render Safari cookieless</title>
      <link>https://www.michaelshadle.com/2010/10/05/how-to-render-safari-cookieless</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/10/05/how-to-render-safari-cookieless</guid>
      <pubDate>Wed, 06 Oct 2010 06:53:28 GMT</pubDate>
      <description>Today we had an issue at work, an odd issue. OS X users using Safari wound up with a proxy issue after clicking on a button on our site, and reloading the page. The suspect seemed…</description>
      <content:encoded><![CDATA[<p>Today we had an issue at work, an odd issue.</p>
<p>OS X users using Safari wound up with a proxy issue after clicking on a button on our site, and reloading the page.</p>
<p>The suspect seemed simple to me - the button has to do something persistent that makes the browser behave differently the next page load - so a cookie or a session-based thing on the server side which scrambles the request. Session stuff seemed incorrect as it should show a PHP error or something, not actually make the proxy reject the request. So I came to the easy conclusion of going down the cookie route.</p>
<p>Sure enough, it was an onclick function which set a cookie - one that worked in every browser including Safari on Windows*, but broke on Safari on OS X. So we looked to see what the cookie was. Turns out, Safari on OS X at the moment does not like when a cookie's value ends with a comma &quot;,&quot; - it  literally breaks cookie handling altogether. It sends some request that our proxy considers invalid and rejects, and checking without the proxy involved showed us that some cookies (if not all of them) were not being sent to the server (or at least not properly) - which included our authentication cookies. The minute we nuked this &quot;bad&quot; cookie, our other cookies got read properly, the proxy allowed the request, etc.</p>
<p>So, for those people who like to see things more direct and don't like to read a lot of fluff (me included!) here's a simple breakdown:</p>
<pre class="hljs"><code>BREAKS: CookieName=Foo,Bar,Baz,
WORKS: CookieName=Foo,Bar,Baz
</code></pre>
<p>Pretty simple. Odd that it appears to be inconsistent across platforms. Anyway, have fun with that little nugget of information. If I wasn't lazy I would look into exactly where to submit a bug, somewhere in the WebKit community I assume.</p>
<p><em>* I cannot confirm that Windows did not suffer from this, a coworker provided that information.</em></p>]]></content:encoded>
      <category>software</category>
    </item>
    <item>
      <title>How would I change PHP?</title>
      <link>https://www.michaelshadle.com/2010/09/22/how-would-i-change-php</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/09/22/how-would-i-change-php</guid>
      <pubDate>Wed, 22 Sep 2010 11:09:56 GMT</pubDate>
      <description>Anyone who knows me knows I am a PHP fanboy. I use PHP for everything - web applications, web scraping, batch scripting, if there is an itch that software can fix, I try to…</description>
      <content:encoded><![CDATA[<p>Anyone who knows me knows I am a PHP fanboy. I use PHP for everything - web applications, web scraping, batch scripting, if there is an itch that software can fix, I try to scratch it with PHP. I dreamed of a PHP scripting plugin for Eggdrop IRC bots, so I didn't have to fuss with TCL. Anywhere PHP could be adopted, I've hoped someone was working on a way it could be.</p>
<p>However, if you talk to people who know the internals of PHP they'll tell you there's a lot of ugly stuff in there. That it's a language based on macros, etc. I don't necessarily care about that. My experience is from a user perspective, not an internals one. That being said, just from my higher level interaction with the language, these are some of the things I'd love to change.</p>
<ul>
<li>
<p><strong>Make function name conventions consistent.</strong> Some functions have underscores, some don't. strpos vs. str_replace, html_entity_decode vs. htmlentities, etc.</p>
</li>
<li>
<p><strong>Make argument order consistent for similar types of functions.</strong> Depending on what you're doing, it's one or the other. in_array($needle, $haystack) vs. strstr($haystack, $needle), etc.</p>
</li>
<li>
<p><strong>Optimize the core.</strong> Strip the core down more, and push more things into modules. Enable some of them by default, fine. But when it comes down to it, I don't need easily 30-40% of the functions that PHP has built in.</p>
</li>
<li>
<p><strong>Combine similar functions and use arguments to define the behavior.</strong> For example addslashes() and addcslashes(). Make it one function with a constant to define its behavior.</p>
</li>
<li>
<p><strong>Disable magic quotes (preferred) or enable it and don't give any option to change it.</strong> As far as I'm concerned as long as you pick one route, you can guarantee universal compatibility, whether that means using magic quotes, or not using them and expecting developers to understand input sanitization, sanity checking/type checking/all that jazz. Which I don't think is a bad thing.</p>
</li>
<li>
<p><strong>Implement a &quot;strict&quot; mode.</strong> &quot;PHP is lazy&quot; as Rasmus says which is fine and all, but I don't like the PHP name shamed with terms like &quot;insecure&quot; - any code can be insecure in any language, however, PHP is so easy to pick up and get things going that it makes it <em>too</em> easy to write crappy and insecure code. Specifics on a &quot;strict mode&quot;? I've got none. It's late and I can't think of how I would enforce better coding practices in core...</p>
</li>
<li>
<p><strong>Get rid of $_REQUEST.</strong> I've advocated this for years and even unset($_REQUEST) in my code. To me it's a lazy person's workaround for coding and introduces some of the same vectors that were closed when disabling register_globals. If you -really- want to have a $_REQUEST type mechanism in your code, just array_merge($_GET, $_POST, $_COOKIE, etc) in whatever oder you want. I dislike using software that uses $_REQUEST by default but doesn't actually <em>need</em> the flexibility of POST vs. GET vs. COOKIE and such. Know which input stream your data is coming from, if nothing else, it will at least make replay attacks and such much harder for people to craft.</p>
</li>
<li>
<p><strong>Get rid of objects and OO stuff.</strong> Yeah, I said it. Everyone loves OOP. Why? While I see the power of being able to extend classes, I also see it seeming to be the most troublesome when it comes to compatibility checks, all the APC crashing or odd bugs I've suffered from were due to it. If you look at something like Drupal, they've figured out how to extend or override using procedural code quite well. Sadly, even they're converting more things to OO as well.  IMO, OOP is more suited for longer-running applications, perhaps something event driven where a new object to represent a connection is created (however, C's been doing this without dealing with objects forever, it doesn't HAVE to be OO...) Those are the two main examples I see for using OO. Disclaimer: I wasn't raised in an OO environment, this is all based on personal experience and preference. :)</p>
</li>
</ul>
<p>I've memorized the function list for what I use pretty well (like I said, I probably only use a subset of the functions in PHP) however the most annoying thing is when it comes to the needle vs. haystack argument positioning. I usually have to reference <a href="http://php.net">php.net</a> for it. Sometimes I can trial and error though. In an ideal world, I wouldn't have to.</p>
<p>It would be great if something like PHP 6.0 would adopt some of these practices, since it is a major version change. Perl, Ruby and Python I believe have all done similar things where a major change really was a dramatic change and required conversion of code to meet its new requirements.</p>
<p>I'm sure this list could grow, and I may add to it. Who knows.</p>]]></content:encoded>
      <category>development</category>
      <category>php</category>
    </item>
    <item>
      <title>Our credit system is broken</title>
      <link>https://www.michaelshadle.com/2010/09/11/our-credit-system-is-broken</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/09/11/our-credit-system-is-broken</guid>
      <pubDate>Sat, 11 Sep 2010 13:01:41 GMT</pubDate>
      <description>I got some results back on my credit report. Choice items such as: Length of account history is too short. Too long since most recent account established. What the hell? Don&apos;t…</description>
      <content:encoded><![CDATA[<p>I got some results back on my credit report.</p>
<p>Choice items such as:</p>
<ul>
<li>
<p>Length of account history is too short.</p>
</li>
<li>
<p>Too long since most recent account established.</p>
</li>
</ul>
<p>What the hell? Don't those basically contradict each other?</p>
<p>But wait, there's more:</p>
<ul>
<li>
<p>Too many recent inquiries.</p>
</li>
<li>
<p>Length of account history is too short.</p>
</li>
<li>
<p>Too many accounts with balances.</p>
</li>
</ul>
<p>Sounds like I am being encouraged to open a fresh account, because my &quot;most recent account&quot; was created too long ago. But too many new accounts dings me, on the flip side. I have too many accounts at the same time though. It's a catch 22.</p>
<p>However, the major complaint I have is that applying for loans/doing any sort of shopping that requires someone to pull your credit winds up <em>hurting your credit score</em>. This isn't anything new, but I simply do not get it. Shopping around and applying to things should have <em>absolutely nothing</em> to do with your score. That is like being charged 25 cents for looking at a carton of milk at the store but not buying it. Or having to pay to window shop - before you know whether or not you can even afford what you're looking at. Your <em>credit</em> score should only be altered when your <em>credit</em> situation changes. Not for simply checking to see if you can save money by refinancing or shopping for auto loans.</p>
<p>Unless you are extended a new credit line or something else, there should be no change in score. Especially nowadays with so many companies offering specials that require you to apply, shopping for a refinance (which can be turned down easily) costs you points on your credit score. Shopping does not mean you're actually receiving anything.</p>
<p>Also, I am told that &quot;inquiries within the same industry within the same 45 day period only counts as one pull&quot;. I call bullshit. I am sure they're still counting each one somewhat.</p>
<p>While I do believe a credit rating system is valuable in some form, ours definitely needs to be overhauled. With the economy moving so slowly, people are looking for various ways to get more money out of their home or car, applying for more credit cards, etc. Regardless of the approval, it is messing with your credit just for shopping.</p>
<p><strong>Suggestions</strong></p>
<ul>
<li>
<p>Having your credit pulled should have no adverse affect on your score. Period.</p>
</li>
<li>
<p>The time ranges need to be adjusted. &quot;Too long since your latest account was opened&quot; - that's a new one for me. Really contracts the hell out of the &quot;Length of account history is too short&quot; notice.</p>
</li>
<li>
<p>Consistency across different bureaus - some tell me I don't have enough accounts. Some tell me I have too many. It is like trying to please a committee - you can't please everyone all at once.</p>
</li>
</ul>
<p>I've had credit being built for 10 years, a couple different credit cards, bank accounts and loans. By now I should be receiving no negative marks for anything I've done relating to too many accounts, not enough accounts, too much time, not enough time, etc. However, it seems like raising the number takes an infinite amount of time, but lowering it happens almost immediately when your credit is pulled.</p>
<p>Once again, a sincere disappointment with how a system is run. I also do not see the reasoning behind some of the rules, either.</p>]]></content:encoded>
      <category>consumerism</category>
    </item>
    <item>
      <title>Cleanest configuration for the new PHP-FPM?</title>
      <link>https://www.michaelshadle.com/2010/08/26/cleanest-configuration-for-the-new-php-fpm</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/08/26/cleanest-configuration-for-the-new-php-fpm</guid>
      <pubDate>Thu, 26 Aug 2010 10:49:12 GMT</pubDate>
      <description>When examining the PHP-FPM configuration, I realized that I only tweak a few key pieces per pool, so I decided to share my approach to minimize redundancy and keep things simple…</description>
      <content:encoded><![CDATA[<p>When examining the PHP-FPM configuration, I realized that I only tweak a few key pieces per pool, so I decided to share my approach to minimize redundancy and keep things simple (more files, but simpler to manage)</p>
<p>Because I still have to maintain PHP 5.2.x for clients, I have decided to try building everything in self-contained in an /opt/php53 directory. So consider that my $prefix, and change appropriately.</p>
<p>I have the following setup, and it seems to work great so far.</p>
<p>/opt/php53/etc/php-fpm.conf:</p>
<pre class="hljs"><code class="language-ini" data-lang="ini"><span class="hljs-section">[global]</span>
<span class="hljs-attr">log_level</span> = notice
<span class="hljs-attr">error_log</span> = /opt/php53/var/log/php-fpm.log
<span class="hljs-attr">pid</span> = /opt/php53/var/run/php-fpm.pid
<span class="hljs-attr">emergency_restart_threshold</span> = <span class="hljs-number">10</span>
<span class="hljs-attr">emergency_restart_interval</span> = <span class="hljs-number">1</span>m
<span class="hljs-attr">process_control_timeout</span> = <span class="hljs-number">5</span>s
<span class="hljs-attr">daemonize</span> = <span class="hljs-literal">yes</span>

<span class="hljs-comment">; pools</span>
<span class="hljs-attr">include</span> = /opt/php53/etc/fpm.d/pools/*.conf
</code></pre>
<p>One file per pool, for example, a pool named &quot;mike&quot; -</p>
<p>/opt/php53/etc/fpm.d/pools/mike.conf:</p>
<pre class="hljs"><code class="language-ini" data-lang="ini"><span class="hljs-section">[mike]</span>
<span class="hljs-attr">listen</span> = <span class="hljs-number">127.0</span>.<span class="hljs-number">0.1</span>:<span class="hljs-number">11000</span>
<span class="hljs-attr">user</span> = mike
<span class="hljs-attr">group</span> = mike
<span class="hljs-attr">request_slowlog_timeout</span> = <span class="hljs-number">5</span>s
<span class="hljs-attr">slowlog</span> = /opt/php53/var/log/slowlog-mike.log
<span class="hljs-attr">pm.max_children</span> = <span class="hljs-number">5</span>
<span class="hljs-attr">pm.start_servers</span> = <span class="hljs-number">3</span>
<span class="hljs-attr">pm.min_spare_servers</span> = <span class="hljs-number">2</span>
<span class="hljs-attr">pm.max_spare_servers</span> = <span class="hljs-number">4</span>
<span class="hljs-attr">pm.max_requests</span> = <span class="hljs-number">500</span>
<span class="hljs-attr">include</span> = /opt/php53/etc/fpm.d/common.conf
</code></pre>
<p>Common elements for each pool (if these could be inherited globally, which they MIGHT be, I could just toss them in the main php-fpm.conf. Perhaps a feature request. Will post on the mailing list...)</p>
<p>Remember that <code>rlimit_files</code> needs to be something set in your sysctl.conf or on the system level or you'll get that RLIMIT_NOFILE warning. Also, depending on how you want to limit resources per pool/client, you may want to tweak things, such as <code>request_terminate_timeout</code>.</p>
<p>/opt/php53/etc/fpm.d/common.conf:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">listen.backlog = -1
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.status_path = /status
ping.path = /ping
ping.response = pong
request_terminate_timeout = 120s
rlimit_files = 131072
rlimit_core = unlimited
catch_workers_output = <span class="hljs-built_in">yes</span>
<span class="hljs-built_in">env</span>[HOSTNAME] = <span class="hljs-variable">$HOSTNAME</span>
<span class="hljs-built_in">env</span>[PATH] = /bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin:/opt/php53/bin:/opt/php53/sbin
<span class="hljs-built_in">env</span>[TMP] = /tmp
<span class="hljs-built_in">env</span>[TMPDIR] = /tmp
<span class="hljs-built_in">env</span>[TEMP] = /tmp
</code></pre>
<p>As always, YMMV.</p>]]></content:encoded>
      <category>php</category>
      <category>php-fpm</category>
    </item>
    <item>
      <title>The HDMI cable scam</title>
      <link>https://www.michaelshadle.com/2010/08/22/the-hdmi-cable-scam</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/08/22/the-hdmi-cable-scam</guid>
      <pubDate>Sun, 22 Aug 2010 21:14:56 GMT</pubDate>
      <description>Someone finally published an article that caught my eye about this, so I thought I&apos;d add my two cents. Summary in my own words: Never pay more than $5/foot for an HDMI cable at…</description>
      <content:encoded><![CDATA[<p>Someone <a href="http://www.msnbc.msn.com/id/38731070/ns/technology_and_science-tech_and_gadgets/">finally published an article</a> that caught my eye about this, so I thought I'd add my two cents.</p>
<p>Summary in my own words:</p>
<p>Never pay more than $5/foot for an HDMI cable at big box places like Best Buy, etc.</p>
<p>The best places to go are small shops around town - those are roughly $1/foot. There's a handful of places around me that offer plenty of options - length, color, etc. Obviously the length-to-cost ratio is different based on the length (I see some that are less than $1/foot, and some that are more than $1/foot, but all pretty close.)</p>
<p>When looking at an HDMI cable all you need to see is &quot;High Speed&quot; or 10.2Gbps on the packaging. Don't look for &quot;Hz&quot;, &quot;4K&quot; or anything else. Look for either &quot;10.2 Gbps&quot; or &quot;High Speed&quot; and then find the cheapest cable for the length you need.</p>
<p><em>As it says, quality of manufacture can be an issue - but like any product, that is always a possibility. However, most cables should have absolutely no issue.</em></p>
<p>This goes for Ethernet cables too - you shouldn't have to pay more than $1/foot anymore. Even for cat6. I'm looking at a local place with 50 foot cat6 for $15. 75 foot cat5e for $11. Don't get ripped off!</p>]]></content:encoded>
      <category>toys</category>
    </item>
    <item>
      <title>Front Controller Patterns and nginx</title>
      <link>https://www.michaelshadle.com/2010/08/20/front-controller-patterns-and-nginx</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/08/20/front-controller-patterns-and-nginx</guid>
      <pubDate>Fri, 20 Aug 2010 23:31:28 GMT</pubDate>
      <description>It&apos;s no secret I&apos;m a fan of nginx. Probably no secret that I&apos;m a fan of front controller pattern design as well. Why? I find it to be the most universal and easy to support. I…</description>
      <content:encoded><![CDATA[<p>It's no secret I'm a fan of <a href="http://nginx.org/">nginx</a>. Probably no secret that I'm a fan of <a href="http://en.wikipedia.org/wiki/Front_Controller_pattern">front controller pattern</a> design as well.</p>
<p>Why? I find it to be the most universal and easy to support. I create things from scratch using it, and the most popular software out there uses it - <a href="http://drupal.org/">Drupal</a>, <a href="http://www.joomla.org/">Joomla</a>, <a href="http://wordpress.org/">WordPress</a> - and frameworks including the <a href="http://framework.zend.com/">Zend Framework</a>.</p>
<p>A lot of people cook up crazy nginx configurations for this stuff, when all it really takes for at least a standard setup is a single line of configuration code. However, I just found out something that was sitting in front of me this entire time.</p>
<p>BAD: I used to advise people to use this:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">try_files <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php?page=$uri$is_args<span class="hljs-variable">$args</span>;
</code></pre>
<p>BETTER: When actually, even simpler, you can use this:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">try_files <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php?page=<span class="hljs-variable">$request_uri</span>;
</code></pre>
<p>So my whole blog post <a href="http://michaelshadle.com/2009/05/15/dont-forget-the-args">here</a> is slightly wrong. If you use $request_uri, you don't have to remember the $args. It's already there. :)</p>
<p>Note: different packages have different parameters. <a href="http://www.cmsmadesimple.org/">CMS Made Simple</a> uses &quot;page&quot;, Drupal uses &quot;q&quot;, WordPress uses &quot;q&quot; - some software, like WordPress, doesn't technically need anything, they can fall back by reading PATH_INFO or REQUEST_URI, and not a parameter.</p>
<p>In which case, all you need is:</p>
<pre class="hljs"><code class="language-bash" data-lang="bash">try_files <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php;
</code></pre>
<p>Don't care about directories? Drop the &quot;$uri/&quot; too. Save some stat calls - if you don't need em :)</p>]]></content:encoded>
      <category>nginx</category>
    </item>
    <item>
      <title>The magic that is... nginx</title>
      <link>https://www.michaelshadle.com/2010/08/18/the-magic-that-is-nginx</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/08/18/the-magic-that-is-nginx</guid>
      <pubDate>Wed, 18 Aug 2010 09:38:50 GMT</pubDate>
      <description>I&apos;ve told this story countless times, but I&apos;ve never publicly documented it. This happened over a year ago, but I feel obligated to share it. nginx is the main reason for the…</description>
      <content:encoded><![CDATA[<p>I've told this story countless times, but I've never publicly documented it. This happened over a year ago, but I feel obligated to share it. nginx is the main reason for the success and deserves bragging rights.</p>
<p>We had an upcoming product release, and another team was handling all the communication, content, etc. I was simply just the &quot;managed server&quot; administrator type person. Helped setup nginx, PHP-FPM, configure packages on the server, stuff like that.</p>
<p>The other team managed the web applications and such. I had no clue what we would be in for that day.</p>
<p>There is a phrase, &quot;too many eggs in one basket&quot; - well, this was our first system and we were using it for many things, it hadn't gotten to the point where we needed to split it up or worry about scaling. Until this day, of course.</p>
<p>To me, the planning could have been a bit better, with the ISO image we were providing from the origin being staged on other mirrors, using torrents to offload traffic to P2P, etc. However, that wasn't done proactively, only reactively.</p>
<h3 id="the-story" tabindex="-1"> The story</h3>
<p>Launch day occurs. I get an email about someone unable to SSH to a specific IP. I check it out - the IP is unreachable, but the server is up. I submit a ticket to the provider, and they let me know why - apparently the server had triggered their DDoS mitigation system once it hit something like ~500mbit; it was automatically flagged as probably being under attack, and the IP was blackholed.</p>
<p>Once we informed them this was all legit, they instantly worked to put us onto a switch that was not DDoS protected, and we resumed taking traffic. This was all done within 15 or 20 minutes, if I recall. I've never seen anything so smoothly handled - no IP changes, completely transparent to us.</p>
<p>I believe the pocket of no traffic (seen in the graph below) was when we were moved off their normal network monitoring and into a Cisco Guard setup. We were definately caught off guard; like I said, I knew we'd get some traffic, but not filling the entire gigabit port. Not a lot of providers would be so flexible about this and handle it with such grace. There are some reports of it being slow, and that is literally because the server itself has too much going on. PHP is trying to handle all the Drupal traffic, and during the night, the disk I/O was at 100% for a long period of time. Oh yeah - since this was the origin, the servers mirroring us had to start pulling stuff from us too :)</p>
<p>Luckily we're billed by the gigabyte there, not by 95th like most places, or this would be one heck of a hosting bill. We wound up able to reroute the bandwidth fast enough to not even be charged ANY overage for it!</p>
<p>All in all, without nginx in the mix, I doubt this server would have been able to take the pounding. There was no reverse proxy cache, no Varnish, no Squid, nothing of that nature. I am not sure Drupal was even setup to use any memory caching, and I don't believe memcached was available. There were a LOT of options to reduce load - the main one was just cutting down the bandwidth usage to open up space in the pipe, which was eventually done by removing the ISO file off the origin server, and pushing it to a couple mirror sites. Things calmed down then.</p>
<p>However, it attests to how amazinly efficient nginx is - the entire experience wound up taking only 60 something megabytes of RAM for nginx.</p>
<p>Want the details? See below.</p>
<p><strong>The hardware</strong></p>
<ul>
<li>
<p>Intel Xeon 3220 (single CPU, quad-core)</p>
</li>
<li>
<p>4GB RAM</p>
</li>
<li>
<p>single 7200RPM 250GB SATA disk, no RAID, no LVM, nothing</p>
</li>
<li>
<p>Gigabit networking to the rack, with a 10GbE uplink</p>
</li>
</ul>
<p><strong>The software - to the best of my memory (remember, all on a single box!)</strong></p>
<ul>
<li>
<p><a href="http://nginx.org/">nginx</a> (probably 0.7.x at that point)</p>
<ul>
<li>
<p>proxying PHP requests to <a href="http://php-fpm.org">PHP-FPM</a> with PHP 5.2.x (using the patch)</p>
<ul>
<li><a href="http://drupal.org">Drupal</a> 6.x - as far as I know, no advanced caching, no memcached, *possibly* APC</li>
</ul>
</li>
<li>
<p>proxying certain hosts for CGI requests to <a href="http://httpd.apache.org/">Apache</a> 2.x (not sure if it was 2.2.x or 2.0.x)</p>
<ul>
<li>
<p><a href="http://www.gnu.org/software/mailman/">mailman</a> - this was a public mail list server</p>
</li>
<li>
<p><a href="http://www.bugzilla.org/">Bugzilla</a></p>
</li>
</ul>
</li>
<li>
<p>This server was also a yum repo for the project, serving through nginx</p>
</li>
</ul>
</li>
<li>
<p><a href="http://php-fpm.org">PHP-FPM</a> - for Drupal, possibly a couple other apps</p>
</li>
<li>
<p><a href="http://www.postfix.org/">Postfix</a> - the best MTA out there :)</p>
<ul>
<li>
<p>I believe amavisd/clamav/etc. was involved for mail scanning</p>
</li>
<li>
<p>Integration with mailman, of course</p>
</li>
</ul>
</li>
<li>
<p><a href="http://www.mysql.com/">MySQL</a> - 5.0.x, using MyISAM tables by default, I don't believe things were converted to InnoDB</p>
</li>
<li>
<p><a href="http://rsync.samba.org/">rsync</a> - mirrors were pulling using the rsync protocol</p>
</li>
</ul>
<p><strong>The provider</strong></p>
<ul>
<li><a href="http://www.softlayer.com">SoftLayer</a> - they just rock. Not a paid placement. :)</li>
</ul>
<h3 id="the-stats" tabindex="-1"> The stats</h3>
<p><strong>nginx memory usage</strong><br>
During some of that time... only needed 60 megs of physical RAM. 240 megs including virtual. At 2200+ concurrent connections... eat that, Apache.</p>
<pre class="hljs"><code class="language-yaml" data-lang="yaml"><span class="hljs-string">root</span>     <span class="hljs-number">13023</span>  <span class="hljs-number">0.0</span>  <span class="hljs-number">0.0</span>  <span class="hljs-number">39684</span>  <span class="hljs-number">2144</span> <span class="hljs-string">?</span>        <span class="hljs-attr">Ss   03:56   0:00 nginx:</span> <span class="hljs-string">master</span> <span class="hljs-string">process</span> <span class="hljs-string">/usr/sbin/nginx</span>
<span class="hljs-string">www-data</span> <span class="hljs-number">13024</span>  <span class="hljs-number">2.0</span>  <span class="hljs-number">0.3</span>  <span class="hljs-number">50148</span> <span class="hljs-number">14464</span> <span class="hljs-string">?</span>        <span class="hljs-attr">D    03:56   9:30 nginx:</span> <span class="hljs-string">worker</span> <span class="hljs-string">process</span>
<span class="hljs-string">www-data</span> <span class="hljs-number">13025</span>  <span class="hljs-number">1.1</span>  <span class="hljs-number">0.3</span>  <span class="hljs-number">51052</span> <span class="hljs-number">15256</span> <span class="hljs-string">?</span>        <span class="hljs-attr">D    03:56   5:38 nginx:</span> <span class="hljs-string">worker</span> <span class="hljs-string">process</span>
<span class="hljs-string">www-data</span> <span class="hljs-number">13026</span>  <span class="hljs-number">1.3</span>  <span class="hljs-number">0.3</span>  <span class="hljs-number">50760</span> <span class="hljs-number">15076</span> <span class="hljs-string">?</span>        <span class="hljs-attr">D    03:56   6:13 nginx:</span> <span class="hljs-string">worker</span> <span class="hljs-string">process</span>
<span class="hljs-string">www-data</span> <span class="hljs-number">13027</span>  <span class="hljs-number">1.3</span>  <span class="hljs-number">0.3</span>  <span class="hljs-number">50584</span> <span class="hljs-number">14900</span> <span class="hljs-string">?</span>        <span class="hljs-attr">D    03:56   6:22 nginx:</span> <span class="hljs-string">worker</span> <span class="hljs-string">process</span>
</code></pre>
<p><strong>nginx status (taken at some random point)</strong></p>
<pre class="hljs"><code class="language-yaml" data-lang="yaml"><span class="hljs-attr">Active connections:</span> <span class="hljs-number">2258</span>
<span class="hljs-string">server</span> <span class="hljs-string">accepts</span> <span class="hljs-string">handled</span> <span class="hljs-string">requests</span>
<span class="hljs-number">711389</span> <span class="hljs-number">711389</span> <span class="hljs-number">1483197</span>
<span class="hljs-attr">Reading: 2 Writing: 2040 Waiting:</span> <span class="hljs-number">216</span>
</code></pre>
<p><strong>Bandwidth (taken from the provider's switch)</strong></p>
<pre class="hljs"><code class="language-sql" data-lang="sql">Exceeded Bits <span class="hljs-keyword">Out</span>: <span class="hljs-number">1001.9</span> M (Threshold: <span class="hljs-number">500</span> M)
Auto Manage <span class="hljs-keyword">Method</span>: FCR_BLOCK
Auto Manage <span class="hljs-keyword">Result</span>: SUCCESSFUL

Exceeded Bits <span class="hljs-keyword">Out</span>: <span class="hljs-number">868.1</span> M (Threshold: <span class="hljs-number">500</span> M)
Auto Manage <span class="hljs-keyword">Method</span>: FCR_BLOCK
Auto Manage <span class="hljs-keyword">Result</span>: SUCCESSFUL
</code></pre>
<p>To give you an idea of the magnitude of growth, this is the amount of gigabytes the server pushes on a normal day:</p>
<ul>
<li>
<p>2009-05-18 155.01 GB</p>
</li>
<li>
<p>2009-05-17 127.48 GB</p>
</li>
<li>
<p>2009-05-16 104.21 GB</p>
</li>
<li>
<p>2009-05-15 152.42 GB</p>
</li>
<li>
<p>2009-05-14 160.12 GB</p>
</li>
<li>
<p>2009-05-13 148.6 GB</p>
</li>
</ul>
<p>On launch day and the spillover into the next day:</p>
<ul>
<li>
<p>2009-05-19 2036.37 GB</p>
</li>
<li>
<p>2009-05-20 2481.87 GB</p>
</li>
</ul>
<h3 id="the-pretty-pictures" tabindex="-1"> The pretty pictures</h3>
<p>Click for larger versions!</p>
<p><strong>Hourly traffic graph</strong><br>
<a href="https://www.michaelshadle.com/media/1789753091690-798ba3ab38-24daee.jpg"><img src="https://www.michaelshadle.com/media/1789753091690-798ba3ab38-24daee.jpg" alt="nginx rocks!" title="nginx spike image #2"></a><br>
<em>(Note: I said 600M, apparently their threshhold from their router says 500M)</em></p>
<p><strong>Weekly traffic graph</strong><br>
<a href="https://www.michaelshadle.com/media/1789753091670-90be0ec4a1-94aa18.jpg"><img src="https://www.michaelshadle.com/media/1789753091670-90be0ec4a1-94aa18.jpg" alt="nginx rocks!" title="nginx spike image #2"></a></p>
<h3 id="the-takeaway" tabindex="-1"> The takeaway</h3>
<p>Normally I would never think a server could get slammed with so much while it is having to service so much. Perhaps if it was JUST a PHP/MySQL server, or JUST a static file server, but no - we had two webservers, a mailing list manager, Drupal (which is not the most optimized PHP software), etc. The server remained responsive enough to service requests, on purely commodity hardware.</p>]]></content:encoded>
      <category>nginx</category>
      <category>php</category>
      <category>php-fpm</category>
    </item>
    <item>
      <title>Microsize me</title>
      <link>https://www.michaelshadle.com/2010/07/30/microsize-me</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/07/30/microsize-me</guid>
      <pubDate>Sat, 31 Jul 2010 04:30:31 GMT</pubDate>
      <description>The world is getting smaller. AT&amp;T&apos;s got a Femtocell called a &quot;MicroCell&quot; PayPal is an example of a &quot;micropayment&quot; service Microformats are becoming increasingly popular to add…</description>
      <content:encoded><![CDATA[<p>The world is getting smaller.</p>
<ul>
<li>
<p>AT&amp;T's got a <a href="http://en.wikipedia.org/wiki/Femtocell">Femtocell</a> called a &quot;MicroCell&quot;</p>
</li>
<li>
<p>PayPal is an example of a &quot;<a href="http://en.wikipedia.org/wiki/Micropayment">micropayment</a>&quot; service</p>
</li>
<li>
<p><a href="http://en.wikipedia.org/wiki/Microformat">Microformats</a> are becoming increasingly popular to add more metadata into websites, mainly for richer machine processing</p>
</li>
<li>
<p><a href="http://en.wikipedia.org/wiki/MicroATX">MicroATX</a> is one of many small form factors. However, not as small as Nano-ITX, Mini-ITX</p>
</li>
<li>
<p><a href="http://twitter.com">Twitter</a> is the world's most popular &quot;<a href="http://en.wikipedia.org/wiki/Microblogging">Microblogging</a>&quot; service</p>
</li>
<li>
<p>Need to clean something fragile? <a href="http://en.wikipedia.org/wiki/Microfiber">Microfiber</a> cloths are typically used to clean luxury cars, computer parts, screens, etc.</p>
</li>
<li>
<p>Those small tweaks to squeeze out a little bit more performance? <a href="http://michaelshadle.com/php-optimization">Micro-optimizations</a> can be useful or can be a pain. It's up to you to decide what is worth it or not.</p>
</li>
</ul>
<p>In this world of larger cars, larger boats, larger cruise ships, larger meals, just remember this - a lot of things are getting smaller. Typically technology... but I threw in another couple terms I seem to say often.</p>
<p>Update:</p>
<p>I forgot, <a href="http://en.wikipedia.org/wiki/Microexpression">microexpressions</a>, now being made a household name thanks to the TV show &quot;Lie to Me&quot; (highly recommended show, btw.)</p>]]></content:encoded>
      <category>uncategorized</category>
    </item>
    <item>
      <title>Little-known URI shorthand - the &quot;network-path&quot; reference</title>
      <link>https://www.michaelshadle.com/2010/07/21/little-known-uri-shorthand-the-network-path-reference</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/07/21/little-known-uri-shorthand-the-network-path-reference</guid>
      <pubDate>Thu, 22 Jul 2010 05:38:12 GMT</pubDate>
      <description>I&apos;ve seen this before, and it was mentioned earlier today at OSCON, but I never knew if it was a browser behavior or a standard. Looks like I got it with some help from IRC. Say…</description>
      <content:encoded><![CDATA[<p>I've seen this before, and it was mentioned earlier today at OSCON, but I never knew if it was a browser behavior or a standard. Looks like I got it with some help from IRC.</p>
<p>Say you have a foreign host and you don't want to have to figure out if you're on http:// or https:// and call their assets appropriately so you don't get a mixed-mode warning. You can actually use a syntax that is defined in <a href="http://tools.ietf.org/html/rfc3986#section-4.2">RFC 3986</a>, specifically section 4.2:</p>
<blockquote>
<p>A relative reference that begins with two slash characters is termed a network-path reference; such references are rarely used. A relative reference that begins with a single slash character is termed an absolute-path reference. A relative reference that does not begin with a slash character is termed a relative-path reference.</p>
</blockquote>
<p>Which means you can do this:</p>
<pre class="hljs"><code class="language-html" data-lang="html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;//foo.com/bar.jpg&quot;</span> /&gt;</span>
</code></pre>
<p>and your browser will request <a href="http://foo.com/bar.jpg">http://foo.com/bar.jpg</a> or <a href="https://foo.com/bar.jpg">https://foo.com/bar.jpg</a>, depending on what scheme your browser is currently on.</p>
<p>I was hesitant at first to consider it &quot;okay&quot; but as it is published in the RFC and Chromium's <a href="http://code.google.com/p/chromium/issues/detail?id=27524">fixed bugs relating to it</a>, it does appear to be a properly supported method that could save you a few keystrokes. Let me know if it doesn't work for you! Be sure to give browser/OS information and conditions to reproduce.</p>
<p><em>Oh yeah, and the other host needs to be on https as well, of course. I shouldn't really have to say that, though :)</em></p>]]></content:encoded>
      <category>development</category>
    </item>
    <item>
      <title>nginx and Go Daddy SSL certificates</title>
      <link>https://www.michaelshadle.com/2010/07/15/nginx-and-godaddy-ssl-certificates</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/07/15/nginx-and-godaddy-ssl-certificates</guid>
      <pubDate>Thu, 15 Jul 2010 21:30:23 GMT</pubDate>
      <description>Generate the CSR: Enter in whatever you want - you NEED the &quot;Common Name&quot; everything else is not really required for it to work. Paste the CSR into Go Daddy, get back the .crt…</description>
      <content:encoded><![CDATA[<ol>
<li>
<p>Generate the CSR:</p>
<pre class="hljs"><code>openssl genrsa 2048 &gt; yourhost.com.key
openssl req -new -key yourhost.com.key &gt; yourhost.com.csr
</code></pre>
</li>
<li>
<p>Enter in whatever you want - you NEED the &quot;Common Name&quot; everything else is not really required for it to work.</p>
<pre class="hljs"><code class="language-java" data-lang="java"><span class="hljs-type">Country</span> <span class="hljs-title function_">Name</span> <span class="hljs-params">(<span class="hljs-number">2</span> letter code)</span> [AU]:US
State or <span class="hljs-type">Province</span> <span class="hljs-title function_">Name</span> <span class="hljs-params">(full name)</span> [Some-State]:.
<span class="hljs-type">Locality</span> <span class="hljs-title function_">Name</span> <span class="hljs-params">(eg, city)</span> []:.
<span class="hljs-type">Organization</span> <span class="hljs-title function_">Name</span> <span class="hljs-params">(eg, company)</span> [Internet Widgits Pty Ltd]:Something Here
Organizational <span class="hljs-type">Unit</span> <span class="hljs-title function_">Name</span> <span class="hljs-params">(eg, section)</span> []:.
<span class="hljs-type">Common</span> <span class="hljs-title function_">Name</span> <span class="hljs-params">(eg, YOUR name)</span> []:yourhost.com
Email Address []:.

Please enter the following <span class="hljs-string">&#x27;extra&#x27;</span> attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
</code></pre>
</li>
<li>
<p>Paste the CSR into Go Daddy, get back the .crt file</p>
</li>
<li>
<p>Combine the cert + Go Daddy chain:</p>
<pre class="hljs"><code>cat yourhost.com.crt gd_bundle.crt &gt; yourhost.com.pem
</code></pre>
</li>
<li>
<p>Lastly, in nginx.conf:</p>
<pre class="hljs"><code>ssl_certificate /etc/nginx/certs/yourhost.com.pem;
ssl_certificate_key /etc/nginx/certs/yourhost.com.key;
</code></pre>
</li>
</ol>
<p>Additionally I have these SSL tweaks which seems to maintain a better SSL experience, passes McAfee Secure's SSL checks, etc.:</p>
<pre class="hljs"><code class="language-ruby" data-lang="ruby">ssl on;
ssl_protocols <span class="hljs-title class_">SSLv3</span> <span class="hljs-title class_">TLSv1</span>;
ssl_ciphers <span class="hljs-variable constant_">ALL</span><span class="hljs-symbol">:-ADH</span><span class="hljs-symbol">:+HIGH</span><span class="hljs-symbol">:+MEDIUM</span><span class="hljs-symbol">:-LOW</span><span class="hljs-symbol">:-SSLv2</span><span class="hljs-symbol">:-EXP</span>;
ssl_session_cache <span class="hljs-symbol">shared:</span><span class="hljs-variable constant_">SSL</span><span class="hljs-symbol">:</span>10m;
</code></pre>]]></content:encoded>
      <category>nginx</category>
    </item>
    <item>
      <title>A simple Upstart recipe for KVM</title>
      <link>https://www.michaelshadle.com/2010/07/01/a-simple-upstart-recipe-for-kvm</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/07/01/a-simple-upstart-recipe-for-kvm</guid>
      <pubDate>Thu, 01 Jul 2010 19:04:20 GMT</pubDate>
      <description>Might not be the most advanced, but hey, it works. You just need to alter the mac address and the display for each machine. I&apos;m running this on Ubuntu 10.04 (Lucid) and it seems…</description>
      <content:encoded><![CDATA[<p>Might not be the most advanced, but hey, it works. You just need to alter the mac address and the display for each machine. I'm running this on Ubuntu 10.04 (Lucid) and it seems to work great.</p>
<p>/etc/init/my-kvm.conf:</p>
<pre class="hljs"><code class="language-python" data-lang="python">description     <span class="hljs-string">&quot;my-kvm&quot;</span>

start on (net-device-up
   <span class="hljs-keyword">and</span> local-filesystems)
stop on runlevel [016]

respawn
<span class="hljs-built_in">exec</span> /usr/<span class="hljs-built_in">bin</span>/kvm -hda /root/virtual-machines/my-kvm.<span class="hljs-built_in">bin</span> -no-acpi -m <span class="hljs-number">128</span> -net nic,macaddr=DE:AD:BE:EF:<span class="hljs-number">18</span>:<span class="hljs-number">12</span> -net tap -vnc :<span class="hljs-number">0</span>
</code></pre>
<p>Enjoy.</p>]]></content:encoded>
      <category>software</category>
    </item>
    <item>
      <title>Happy day! PHP-FPM included with PHP 5.3.3RC1, and WordPress 3.0</title>
      <link>https://www.michaelshadle.com/2010/06/17/happy-day-php-fpm-included-with-php-5-3-3rc1-and-wordpress-30</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/06/17/happy-day-php-fpm-included-with-php-5-3-3rc1-and-wordpress-30</guid>
      <pubDate>Fri, 18 Jun 2010 00:19:52 GMT</pubDate>
      <description>Officially in the 5.3.3RC1 distribution. Sweet! From the NEWS file: 17 Jun 2010, PHP 5.3.3 RC1 ... \- Added FastCGI Process Manager (FPM) SAPI. (Tony) ... and on an unrelated…</description>
      <content:encoded><![CDATA[<p>Officially in the <a href="http://downloads.php.net/johannes/php-5.3.3RC1.tar.bz2">5.3.3RC1</a> distribution. Sweet! From the NEWS file:</p>
<blockquote>
<p>17 Jun 2010, PHP 5.3.3 RC1<br>
...<br>
- Added FastCGI Process Manager (FPM) SAPI. (Tony)<br>
...</p>
</blockquote>
<p>and on an unrelated note:</p>
<blockquote>
<p>- Added support for JSON_NUMERIC_CHECK option in json_encode() that converts numeric strings to integers. (Ilia)</p>
</blockquote>
<p>Shouldn't this be called JSON_NUMERIC_CONVERT? or JSON_FORCE_INTEGER? It's not just a &quot;check&quot; - guess it's too late now? :)</p>
<p><strong>WordPress 3.0...</strong><br>
<a href="http://wordpress.org/news/2010/06/thelonious/">WordPress 3.0 came out today</a>. Tonight I'll probably upgrade this site and see how well it works. I'm going to check it in to Subversion first so I can roll back if needed.</p>
<p>Some key changes I wanted to talk about...</p>
<ul>
<li>
<p>One thing that was highlighted is the option to use custom header images - which can easily be done right now. I did it well over a year ago in a theme. With post meta you can always load metadata about a post and use it in the theme, so this update seems a bit specific to me, since themes were already customizable. Why build a feature that is so specific? Same with background images/colors...</p>
</li>
<li>
<p>Custom menus/menu editor - this could get cool, the menu editor is the more exciting piece as it will allow a visual way to manage the taxonomy. Not sure how it will mix in with tags and categories though, guess that's &quot;I'll see it when I upgrade.&quot;</p>
</li>
<li>
<p>MU merge - finally, I can run multiple installs off the same WP install, hopefully, without wp-config.php hacks. How exactly it works I will have to find out.</p>
</li>
<li>
<p>Custom post types - now all of a sudden you can make any sort of object with custom attributes, which opens the door to things such as the item below.</p>
</li>
<li>
<p>WP e-Commerce says they're going to change from using all their extra tables to using core WP schema. That's awesome.</p>
</li>
</ul>
<p>A couple bones to pick...</p>
<ul>
<li>
<p>It's not a rewrite. It's still a <em>blogging</em> tool that is being extended further to be a full-featured that can handle &quot;anything&quot; - however the tables are still named &quot;posts&quot; even though now you can create an arbitrary type of item. I'd like to see it renamed and normalized.</p>
</li>
<li>
<p>All the plugins and themes and such are procedural code, but some inner workings such as the DB layer are OO. That seems amateur to me, and unnecessary.</p>
</li>
</ul>
<p>I'd love to see WP get rewritten. It has a LOT of overhead and includes built in that need calling and a lot of other cruft that I stumble across. Go back to the drawing board with building a list of every feature it has, and look at it from a longer term perspective. It's great to see something keep growing, but when it comes down to it, it is still a fork of b2, which was made for <em>blogging</em>, not for <em>anything and everything</em>.</p>
<p>It's got the right idea with extensibility and such, but to me the core has a lot of code - and lots of code means more complicated execution paths, more &quot;I'll just add this in instead of refactor this old code,&quot; more cruft. I'm quite sure I could get as much extensibility out of a fresh rewrite with less than half the code under the hood. Things like text styling for example should be moved to a plugin (I disable all the wptexturize filters for example... throw those in an include and make it enabled by default instead!)</p>
<p>Of course, WordPress does have millions of users so it has a proven track record. I can't complain that much, I do use it myself. For blogging, it's the best tool out there. For other things, it typically leverages plugins which may or may not have decent UIs or APIs to interact with. That's where it shows signs of weakness. It also isn't as strict as Drupal when it comes to code conventions either, which would greatly increase the usability of a lot of plugins.</p>]]></content:encoded>
      <category>php</category>
      <category>php-fpm</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>The Trifecta with AT&amp;T</title>
      <link>https://www.michaelshadle.com/2010/06/02/the-trifecta-with-att</link>
      <guid isPermaLink="true">https://www.michaelshadle.com/2010/06/02/the-trifecta-with-att</guid>
      <pubDate>Thu, 03 Jun 2010 06:01:43 GMT</pubDate>
      <description>Today AT&amp;T reported a bunch of data plan changes, perfectly aligned with screwing over people when iPhone OS 4 comes out. OS 4 will give us tethering ability with AT&amp;T. Of course…</description>
      <content:encoded><![CDATA[<p>Today <a href="http://www.engadget.com/2010/06/02/atandt-makes-sweeping-changes-to-data-plans-iphone-tethering-comi/">AT&amp;T reported</a> a bunch of data plan changes, perfectly aligned with screwing over people when iPhone OS 4 comes out.</p>
<p>OS 4 will give us tethering ability with AT&amp;T. Of course, that comes with an additional cost now. If you want to &quot;officially&quot; tether with AT&amp;T, you'll have to switch to one of their two data plans, and THEN buy tethering on top of that. Instead of your $30 for unlimited, you'll be paying $45 for only two gigs of bandwidth, vs. $30 currently for unlimited. Or $35 for a measily 250 megs.</p>
<p>They claim that 98% of its users fall within those tiers. Sounds like they're giving 98% of us a way to save a few bucks, right? Wrong. What people are overlooking is the fact that those statistics don't include the fact that you will be TETHERING. As in, your computer will be transferring data, and you're already accustomed to a much heavier data consumption through that medium. Think of how those little widgets on your laptop grab information off the net every so often, or a single Youtube video could easily be 20+ megs. It does add up, and ultimately anyone who wants to tether with AT&amp;T should use it sparsely - otherwise, they'll be paying $10/gig for your overages.</p>
<p>I'll give AT&amp;T some credit - their marketing geniuses and social engineers are gaming this system well - using the upcoming iPhone and OS for service type changes, some of which require contracts, some don't - helping them limit the impact on their network in creative ways while making you think you're getting a better deal. I especially like the fact once you drop out of an unlimited contract you can't go back, and they're trying to sway you out of it by not changing your expiration date if you drop down, and &quot;allowing&quot; you to switch back and forth between the two plans. Oh, and new iPad users? If you don't have a plan by the time OS 4 launches, you'll be subject to these new limits.</p>
<p>Let's face it - AT&amp;T's network can't handle the iPhone. It's a blame game that ultimately both could be doing better at. I'm sure the iPhone could change it's tower-hogging style behavior, and I'm sure AT&amp;T could be deploying all these upgrades they keep telling us about faster.</p>
<p>For me, if I do decide to go with the next iPhone, I won't be buying it with a contract. I'm going to stay a free agent, and not get locked in to a new agreement, and not buy their joke for insurance (monthly fee and still the cost of buying a refurbished unit for the deductable?!) - and I am getting closer every day to switching over to maybe the Evo 4G on Sprint - a hybrid solution with a limited 4g network around the area. Sprint and Verizon seem to have a much more reliable network, and since this device is still primarily a <em>phone</em>, voice calls do count for <em>something</em>. Sprint's at least would afford me faster WiMAX when I could get it, and openly promote the device's ability to share the connection with up to 8? devices.</p>
<p>I haven't investigated the fees, but when I can't go a single day without a dropped call, and I try to find landlines to fall back on where I can instead of my phone, something has got to change.</p>]]></content:encoded>
      <category>consumerism</category>
    </item>
  </channel>
</rss>
