<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>tghw</title>
        <description>Hi! I&#39;m Tyler.&lt;br /&gt;I&#39;m a founder of &lt;a href=&#34;https://www.snaposit.com/&#34;&gt;Snaposit&lt;/a&gt;. I used to work at the one and only Fog Creek Software.</description>
        <link>http://tghw.com</link>
        
        
        <item>
            <title>Tyler&#39;s Green Chile Stew Recipe</title>
            <description>&lt;p&gt;It&#39;s soup season, and people always ask me for this recipe.&lt;/p&gt;
&lt;p&gt;So here it is:&lt;/p&gt;
&lt;h2&gt;Ingredients&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;8 cups vegetable stock*&lt;/li&gt;
&lt;li&gt;4 large potatoes, diced&lt;/li&gt;
&lt;li&gt;3 cans of pinto beans&lt;/li&gt;
&lt;li&gt;1 can of corn kernels&lt;/li&gt;
&lt;li&gt;Hatch green chile, chopped **&lt;/li&gt;
&lt;li&gt;Half an onion&lt;/li&gt;
&lt;li&gt;1 tbsp of garlic&lt;/li&gt;
&lt;li&gt;Olive oil&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Directions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Chop the onions and garlic and saute them in olive oil at the bottom of a large stock pot.&lt;/li&gt;
&lt;li&gt;When the onions have turned translucent, pour the stock into the pot.&lt;/li&gt;
&lt;li&gt;Add the potatoes, beans, and corn and bring the pot to a boil.&lt;/li&gt;
&lt;li&gt;Once the pot is boiling, reduce the heat to low.&lt;/li&gt;
&lt;li&gt;Add the green chile.&lt;/li&gt;
&lt;li&gt;Let the pot simmer until the potatoes are soft and the stew has thickened, usually 30-60 minutes, stirring every few minutes. ***&lt;/li&gt;
&lt;li&gt;Serve in a bowl with cheese on top and a warm tortilla on the side for dipping.&lt;/li&gt;
&lt;li&gt;Enjoy!&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;p&gt;* I prefer bullion cubes to premade stock because they&#39;re cheaper and
 easier to store. Most bullion cubes make 2 cups of stock.&lt;/p&gt;
&lt;p&gt;** The amount of green chile is left as an exercise to the reader. I suggest starting small and adding more until you have enough heat.&lt;/p&gt;
&lt;p&gt;*** It&#39;s easy to burn the bottom of the pot if left unattended for too long. Make sure you stir!&lt;/p&gt;</description>
            <pubDate>Oct 19, 2017</pubDate>
            <link>http://tghw.com/blog/tyler-s-green-chile-stew-recipe</link>
            <guid>http://tghw.com/blog/tyler-s-green-chile-stew-recipe</guid>
        </item>
        
        
        <item>
            <title>Copilot: Coming Full Circle</title>
            <description>&lt;p&gt;Exactly 10 years ago, Copilot was &lt;a href=&#34;http://projectaardvark.com/archive/july.html#full-disclosure&#34;&gt;officially announced to the public&lt;/a&gt;. A little over a year ago, I acquired it from Fog Creek as a part of their corporate restructuring, driven mostly by the need to &lt;a href=&#34;http://www.joelonsoftware.com/items/2014/07/24.html&#34;&gt;spin Trello out into its own company&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;ve kept it pretty quiet so far, mostly because I was spending a lot of my time doing all of the things necessary to push Copilot out of the nest, something that I didn&#39;t want users to be adversely affected by. This included migrating it to new servers, splitting the Copilot credit cards into their own vault, separating the billing systems, and carving Copilot data out of the databases.&lt;/p&gt;
&lt;p&gt;The other reason I&#39;ve kept it quiet is that I was a little embarrassed about the state of Copilot. It had been quite a while since any major updates were done to it, and its age was starting to show. The next task was to rewrite the client applications to be faster, more stable, and easier to use.&lt;/p&gt;
&lt;p&gt;It&#39;s been a long road, but with the new client applications feeling pretty solid, today &lt;a href=&#34;https://www.copilot.com/News/TwoBigAnnouncements.aspx&#34;&gt;I announce the soft-launch of the new client applications&lt;/a&gt;, along with a public acknowledgement of the new ownership of Copilot.&lt;/p&gt;
&lt;p&gt;I wasn&#39;t actually aiming to hit the decade mark since Copilot&#39;s first official announcement. That was more of a happy coincidence than anything. But realizing it&#39;s been 10 years since &lt;a href=&#34;https://www.youtube.com/watch?v=J3dTxIjEeRw&#34;&gt;that summer&lt;/a&gt; has made me reflect on the path I&#39;ve taken to get here.&lt;/p&gt;
&lt;p&gt;It&#39;s certainly been a windy road, but I&#39;m happy to be back working on the project that set my career on this trajectory.&lt;/p&gt;</description>
            <pubDate>Jul 01, 2015</pubDate>
            <link>http://tghw.com/blog/copilot-coming-full-circle</link>
            <guid>http://tghw.com/blog/copilot-coming-full-circle</guid>
        </item>
        
        
        <item>
            <title>Magic: How to launch a product so no one will ever use it again.</title>
            <description>&lt;p&gt;Yesterday, I came across a new text-based meta-service called &lt;a href=&#34;http://getmagicnow.com/&#34;&gt;Magic&lt;/a&gt;. Magic is supposed to be the ultimate on-demand service. According to its homepage, you can ask Magic for anything you can order online, and they&#39;ll take care of it for you.&lt;/p&gt;
&lt;p&gt;It&#39;s actually a pretty simple idea. They hired some people to respond to the text messages that come in, decide which service is most appropriate for the request, and place the order. In terms of technology, it&#39;s also very simple, likely being a Twilio number with an admin panel on the backend, linked to Stripe&#39;s payment gateway.&lt;/p&gt;
&lt;p&gt;Last night I was over at &lt;a href=&#34;http://www.keacher.com/&#34;&gt;Jeff&#39;s&lt;/a&gt; place watching the eventual Best Picture winner, Birdman. We decided to order dinner, and since I had signed up for Magic, I thought it&#39;d be fun to try it, even if it was a little pricier.&lt;/p&gt;
&lt;p&gt;At 6:00pm I sent Magic a message asking for a burrito and a burrito bowl from Chipotle. Then we waited.&lt;/p&gt;
&lt;p&gt;19 minutes later, I got a reply with a link to put in my credit card information. At 6:21pm I replied that I was done putting in my credit card and at 6:23pm I sent them the address to send the order to. Then we waited.&lt;/p&gt;
&lt;p&gt;31 minutes later, at 6:54pm, Magic replied, asking for my name. I replied within a minute. Then we waited.&lt;/p&gt;
&lt;p&gt;27 minutes later, at 7:21pm, Magic finally replied with a price. For one veggie burrito and one veggie burrito bowl to be delivered they wanted $35.&lt;/p&gt;
&lt;p&gt;Just in case you think that might be a typo, I&#39;ll spell it out. Thirty five dollars.&lt;/p&gt;
&lt;p&gt;An hour and twenty one minutes after first contact, we were offered delivery of our $13 meal for $35. Given most delivery times, we wouldn&#39;t have seen our food until 8:00pm. Had I gone through &lt;a href=&#34;https://postmates.com&#34;&gt;Postmates&lt;/a&gt; (which Magic likely used for this order) directly, I would have had my order for only $26 (still pricey for delivery) in only the time required for someone to pick it up and deliver it.&lt;/p&gt;
&lt;p&gt;Magic? Not really. Surprisingly Slow And Doubly Expensive Delivery Service. That&#39;s more like it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Like what you see here? Go check out my new project &lt;a href=&#34;http://www.gameplan30.com&#34;&gt;GamePlan30&lt;/a&gt;!&lt;/p&gt;</description>
            <pubDate>Feb 23, 2015</pubDate>
            <link>http://tghw.com/blog/magic-how-to-launch-a-product-so-no-one-will-ever-use-it-again</link>
            <guid>http://tghw.com/blog/magic-how-to-launch-a-product-so-no-one-will-ever-use-it-again</guid>
        </item>
        
        
        <item>
            <title>32 Is The New 20</title>
            <description>&lt;p&gt;Recently, a dear friend turned 30. Being my longest tenured friend, I gave her a call to wish her well on the dawn of her fourth decade. &lt;/p&gt;
&lt;p&gt;Like many, she was somewhat distressed by the prospect of turning 30. (In retrospect, opening the conversation with &#34;Hey old lady!&#34; was probably not the best choice.)  Being that I had passed that same milestone only a few months before, she asked me how I got through it.&lt;/p&gt;
&lt;p&gt;&#34;I realized that 30 is a totally arbitrary number and that it is just another birthday.&#34;&lt;/p&gt;
&lt;p&gt;I could tell she recognized the logic of the statement, but the sentiment rang hollow. Sure, it&#39;s an arbitrary number, but it&#39;s an arbitrary number that ends in zero. I decided to try another tack.&lt;/p&gt;
&lt;p&gt;&#34;That&#39;s just because we use base-10 for our numbers. If we used base-16, you would still have two years until you turn 20!&#34;&lt;/p&gt;
&lt;p&gt;She was intrigued by this prospect. But being one of the 99% of people who do not regularly think in other bases, she needed a quick refresher. &#34;What&#39;s base-16?&#34;&lt;/p&gt;
&lt;p&gt;&#34;It&#39;s when you don&#39;t go into double digits until 16, so in base-16, one-zero equals 16.&#34;&lt;/p&gt;
&lt;p&gt;&#34;Oh, right. But what do you do when you get above 9?&#34;&lt;/p&gt;
&lt;p&gt;&#34;Well, most commonly you use letters. In base-16, which is also called hexadecimal, you use letters. So it goes 8, 9, A, B, C, D, E, F, 10.&#34;&lt;/p&gt;
&lt;p&gt;&#34;So I just turned 1E?&#34;&lt;/p&gt;
&lt;p&gt;&#34;Yeah, exactly!&#34;&lt;/p&gt;
&lt;p&gt;&#34;I like that! I&#39;m going to tell everyone that I&#39;m not turning 30, I&#39;m just turning 1E!&#34;&lt;/p&gt;
&lt;p&gt;I&#39;m not sure the deviation into base-16 helped assuage her fears about the interminable march of time, but for a moment a little math distracted her from her worries.&lt;/p&gt;</description>
            <pubDate>Dec 09, 2013</pubDate>
            <link>http://tghw.com/blog/32-is-the-new-20</link>
            <guid>http://tghw.com/blog/32-is-the-new-20</guid>
        </item>
        
        
        <item>
            <title>Microcaching for a Faster Site</title>
            <description>&lt;p&gt;My website, this site, is not fast. But, because of this little trick I&#39;m about to show you, you probably think it is.&lt;/p&gt;
&lt;p&gt;It&#39;s not particularly slow, either, at least not when there&#39;s not too much load on it. &lt;code&gt;ab&lt;/code&gt; reports that the median request time for the homepage is about 60ms when there&#39;s only one request per second coming in. But if traffic starts picking up, it starts slowing down. With 2 req/sec, the median jumps to 90ms per request, a 50% increase. At 5 req/sec, it slows to 225ms per request. Do some quick math and you&#39;ll see we&#39;ll soon have a problem.&lt;/p&gt;
&lt;p&gt;Let&#39;s take a quick look under the hood. The website is a heavily modified version of an early iteration of &lt;a href=&#34;https://github.com/orf/simple&#34;&gt;Simple&lt;/a&gt;. It is written in Python using Flask and SqlAlchemy, talking to a PostgreSQL database. This is all being run by &lt;a href=&#34;http://tghw.com/blog/multiple-django-and-flask-sites-with-nginx-and-uwsgi-emperor&#34;&gt;uWSGI in Emperor mode&lt;/a&gt; and served by Nginx.&lt;/p&gt;
&lt;p&gt;Each of these levels could be a source of slowness. We could profile the Python code to figure out where we&#39;re spending our time. Is Jinja2 being slow about autoescaping the html? Maybe. Perhaps it&#39;s in the database layer. SqlAlchemy might be creating some bad queries, so we should log those. And, of course, we need to make sure that PostgreSQL is tuned properly so we&#39;re getting the most out of its caching. Then there&#39;s uWSGI; should we allocate 2, 4, or 8 processes to the site?&lt;/p&gt;
&lt;p&gt;But you know what? That&#39;s a difficult, tedious process, and it&#39;s easy to make things worse in the process.&lt;/p&gt;
&lt;div class=&#34;text-center&#34;&gt;&lt;img src=&#34;https://pymgur.s3.amazonaws.com/HTTciCDp_thumbnail.jpg&#34;&gt;&lt;br&gt;&lt;b&gt;Optimization is hard! Let&#39;s go shopping.&lt;/b&gt;&lt;/div&gt;

&lt;p&gt;What if we could just speed the whole thing up all at once?&lt;/p&gt;
&lt;p&gt;It turns out that, for this type of site, where the users only see one version of the content (as opposed to a web app, where each user has their own version of the site) microcaching is an ideal solution.&lt;/p&gt;
&lt;p&gt;Microcaching is the practice of caching the entire contents of a web page for a very short amount of time. In our case, this will be just one second.&lt;/p&gt;
&lt;p&gt;By doing this, we ensure that when the site is under any sort of load, the vast majority of visitors are getting a copy of the site served as static content from the cache, which Nginx is very good at. In fact, because of the way the caching is set up, the only time a user would wait for the &#34;slow&#34; site would be if they were the first person to hit the site in over a second. But, we know that the &#34;slow&#34; site is pretty fast when it&#39;s under such light load.&lt;/p&gt;
&lt;p&gt;The following is a slightly modified version of my Nginx config file for tghw.com, which shows how to do this:&lt;/p&gt;
&lt;?prettify?&gt;

&lt;pre&gt;&lt;code&gt;# Set cache dir
proxy_cache_path /var/cache/nginx levels=1:2 
                 keys_zone=microcache:5m max_size=1000m;

# Actual server
server {
    listen 80;
    server_name a.tghw.com;
    # ...the rest of your normal server config...
}

# Virtualhost/server configuration
server {
    listen   80;
    server_name  tghw.com;

    # Define cached location (may not be whole site)
    location / {
        # Setup var defaults
        set $no_cache &#34;&#34;;
        # If non GET/HEAD, don&#39;t cache &amp;amp; mark user as uncacheable for 1 second via cookie
        if ($request_method !~ ^(GET|HEAD)$) {
            set $no_cache &#34;1&#34;;
        }
        # Drop no cache cookie if need be
        # (for some reason, add_header fails if included in prior if-block)
        if ($no_cache = &#34;1&#34;) {
            add_header Set-Cookie &#34;_mcnc=1; Max-Age=2; Path=/&#34;;            
            add_header X-Microcachable &#34;0&#34;;
        }
        # Bypass cache if no-cache cookie is set
        if ($http_cookie ~* &#34;_mcnc&#34;) {
            set $no_cache &#34;1&#34;;
        }
        # Bypass cache if flag is set
        proxy_no_cache $no_cache;
        proxy_cache_bypass $no_cache;
        # Point nginx to the real app/web server
        proxy_pass http://a.tghw.com/;
        # Set cache zone
        proxy_cache microcache;
        # Set cache key to include identifying components
        proxy_cache_key $scheme$host$request_method$request_uri;
        # Only cache valid HTTP 200 responses for 1 second
        proxy_cache_valid 200 1s;
        # Serve from cache if currently refreshing
        proxy_cache_use_stale updating;
        # Send appropriate headers through
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # Set files larger than 1M to stream rather than cache
        proxy_max_temp_file_size 1M;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Most of this code was originally derived from &lt;a href=&#34;http://fennb.com/&#34;&gt;Fenn Bailey&lt;/a&gt;. Unfortunately, it seems his site has gone down with the Posterous shutdown.)&lt;/p&gt;
&lt;p&gt;So what&#39;s going on here? Let&#39;s start with the top. I&#39;ve set up the Flask site to respond to a.tghw.com. That&#39;s the actual site that we&#39;ll be caching. Note that the subdomain is not required. You could just as easily use another port, like 8080.&lt;/p&gt;
&lt;p&gt;Next, for tghw.com, we first check to see if there&#39;s any reason we shouldn&#39;t use the cache. This includes doing a request other than HEAD or GET or having a certain cookie (which the admin page sets for me). If that&#39;s the case, we set a cookie for the next 2 seconds that says not to use the cache and we skip the cache for this request. (You want this to be longer than the caching time so your next GET request will grab a fresh copy.)&lt;/p&gt;
&lt;p&gt;If we are using the cache for this request, then we defer to Nginx&#39;s usual &lt;code&gt;proxy_pass&lt;/code&gt;. We tell it that all successful requests (HTTP 200) should be cached for 1 second. The choice of 1 second is pretty arbitrary, it could be longer, but since I know the app itself performs well with 1 request per second, there wouldn&#39;t be a lot of benefit to making it longer. We also set &lt;code&gt;proxy_cache_use_stale&lt;/code&gt; to serve from the cache if Nginx is still busy updating the cache, meaning that users won&#39;t actually see a slower response while we go to the actual site.&lt;/p&gt;
&lt;p&gt;So how does this do compared to the stock site? Well...it blows it out of the water.&lt;/p&gt;
&lt;p&gt;Command used: &lt;code&gt;ab -k -n 50000 -c [1|5|10|25|50|100] -t 10 http://[a.]tghw.com/&lt;/code&gt;&lt;/p&gt;
&lt;style&gt;
.table tr th, .table tr td { text-align: center; }
&lt;/style&gt;
&lt;table class=&#34;table table-bordered&#34;&gt;
    &lt;thead&gt;
        &lt;tr class=&#34;text-center&#34;&gt;
            &lt;th&gt;&lt;/th&gt; &lt;th colspan=&#34;2&#34;&gt;a.tghw.com&lt;/th&gt; &lt;th colspan=&#34;2&#34;&gt;tghw.com&lt;/th&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;-c&lt;/th&gt; &lt;th&gt;req/sec&lt;/th&gt; &lt;th&gt;med resp (ms)&lt;/th&gt; &lt;th&gt;req/sec&lt;/th&gt; &lt;th&gt;med resp (ms)&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;f

            &lt;th&gt;1&lt;/th&gt; &lt;td&gt;15&lt;/td&gt; &lt;td&gt;64&lt;/td&gt; &lt;td&gt;5,952&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;5&lt;/th&gt; &lt;td&gt;32&lt;/td&gt; &lt;td&gt;151&lt;/td&gt; &lt;td&gt;17,283&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;10&lt;/th&gt; &lt;td&gt;31&lt;/td&gt; &lt;td&gt;312&lt;/td&gt; &lt;td&gt;19,991&lt;/td&gt; &lt;td&gt;0&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;25&lt;/th&gt; &lt;td&gt;33&lt;/td&gt; &lt;td&gt;751&lt;/td&gt; &lt;td&gt;19,916&lt;/td&gt; &lt;td&gt;1&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;50&lt;/th&gt; &lt;td&gt;30&lt;/td&gt; &lt;td&gt;1,589&lt;/td&gt; &lt;td&gt;17,397&lt;/td&gt; &lt;td&gt;3&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;100&lt;/th&gt; &lt;td&gt;32&lt;/td&gt; &lt;td&gt;2,984&lt;/td&gt; &lt;td&gt;16,717&lt;/td&gt; &lt;td&gt;5&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;While the Flask site can reliably serve up to about 30 requests per second, it starts slowing down pretty significantly. The microcached site, on the other hand, serves almost 20,000 requests per second at its peak. More importantly, the response times stay in the single digit milliseconds, making the site feel nice and fast, regardless of load.&lt;/p&gt;
&lt;p&gt;So there&#39;s an easy way to speed up your blog without having to make any changes to the application code.&lt;/p&gt;</description>
            <pubDate>May 21, 2013</pubDate>
            <link>http://tghw.com/blog/microcaching-for-a-faster-site</link>
            <guid>http://tghw.com/blog/microcaching-for-a-faster-site</guid>
        </item>
        
        
        <item>
            <title>When the Intern Writes the Billing System</title>
            <description>&lt;p&gt;In the autumn of 2005 I was finishing an internship at &lt;a href=&#34;http://fogcreek.com/&#34;&gt;Fog Creek Software&lt;/a&gt;. My colleagues and I on &lt;a href=&#34;http://www.youtube.com/watch?v=J3dTxIjEeRw&#34;&gt;Project Aardvark&lt;/a&gt; had successfully developed and released &lt;a href=&#34;https://www.copilot.com&#34;&gt;Copilot&lt;/a&gt;. After the launch, we cleaned up the few remaining bugs and added a few small, requested features. Then people started leaving. First &lt;a href=&#34;http://bitquabit.com/&#34;&gt;Ben&lt;/a&gt;, then Yaron, and finally Michael. By the end of August, I was the only intern left.&lt;/p&gt;
&lt;p&gt;It would stay that way for the next three months. Unlike the other interns, I didn&#39;t have to return to school immediately. I had graduated from &lt;a href=&#34;http://www.rose-hulman.edu/&#34;&gt;Rose-Hulman&lt;/a&gt; already and was able to defer my admission to Stanford for the first quarter of classes. This gave me another three months at Fog Creek to tie up any loose ends with Copilot and start adding the next big feature. My assignment, as the last remaining intern? A subscription billing for Copilot.&lt;/p&gt;
&lt;p&gt;(Yes, they had an intern writing the new billing system. No, I&#39;m not making this up.)&lt;/p&gt;
&lt;p style=&#34;text-align:center&#34;&gt;&lt;img src=&#34;/static/img/copilot/window.jpg&#34;&gt;&lt;/p&gt;

&lt;p&gt;When we first launched Copilot, there was only one option for payments: a $5 pass that was good for 24 hours of use. This was great for occasional users, since the cost was more than worth the time saved by not having to do remote support blind. But for more frequent users, it was a hassle. They&#39;d have to enter their credit card information every time they needed to help someone. This was especially bad for companies that used it for customer support, since it forced their support people to request access to the company card on a daily basis.&lt;/p&gt;
&lt;p&gt;Our plan was to implement a subscription billing system, similar to cell phone plans, based on minutes used per month, except with transparent, benevolent pricing. It would have several plans with a different number of included minutes and a per-minute charge for any overages. To make sure users weren&#39;t locked into something too expensive, we also said the system needed to let users change plans at any time.&lt;/p&gt;
&lt;p&gt;My first task was to research options for storing and charging credit cards. I read dozens of marketing pages, sent emails to companies asking for info, and made phone calls to sales people. But every option had the same basic flaw: they could only do rigid, set-price subscriptions. This wouldn&#39;t work for us, since users could easily be charged a different amount each month, depending on how much they utilized the service.&lt;/p&gt;
&lt;p&gt;Instead, we decided that we would write the whole subscription system from scratch ourselves. We already had a similar system in place for one-off purchases, so we thought we might be able to reuse some of the old code. I started writing the recurring billing code while one of our co-founders started on the credit card vault, which we called Roach Motel. (Get it? Cards check in, but they don&#39;t check out...)&lt;/p&gt;
&lt;p&gt;We did everything possible to isolate credit cards from the rest of our infrastructure, keeping it all on a separate server stored in our secure cage in the office, instead of the data center where data-center employees might have access to it. The code was written to accept credit cards, but never to send them out again, except in encrypted form, and only to the payment processor. Access to the box required a thumb drive, held in secure storage, and a password. (Note: As of a couple years ago, this was no longer the case, as we began using a proper credit card vault instead.)&lt;/p&gt;
&lt;p&gt;Over the next couple of months, the system came together nicely, being designed and redesigned to be flexible, so more products could be added in the future, while still being simple and robust. When I left that December, the system was up and running, billing customers each month. Overall, the project seemed like a total success.&lt;/p&gt;
&lt;p style=&#34;text-align:center&#34;&gt;&lt;img src=&#34;/static/img/copilot/collage.jpg&#34;&gt;&lt;/p&gt;

&lt;p&gt;Upon returning to Fog Creek the following summer, I found that was not the case. While I was away, &lt;a href=&#34;http://www.fogcreek.com/fogbugz/&#34;&gt;FogBugz&lt;/a&gt; had grown from an install-only product to its own hosted solution. As with Copilot, this new SaaS-y version of FogBugz required a subscription billing system. So one of the developers on the FogBugz team added a significant amount of new code to support it.&lt;/p&gt;
&lt;p&gt;While part of this new code was to deal with cases I had not foreseen in the original version, much more duplicated existing concepts in a different and incompatible way. (This might sound like an admonishment of the developers adding that new code, but most of the blame lies with me for not communicating, through documentation, the intent of the features they had duplicated.)&lt;/p&gt;
&lt;p&gt;As time went on, the code base continued to grow organically. Occasionally, a change in one side of the code would cause billing errors for the other side. Bugs were introduced that caused miscalculations in customers bills. Other bugs caused duplicate payments to be triggered without properly recording them.&lt;/p&gt;
&lt;p&gt;When &lt;a href=&#34;http://fogcreek.com/kiln/&#34;&gt;Kiln&lt;/a&gt; came along it needed to be added to the system as well. Because of its tight integration with FogBugz, even more code warts were added on to deal with the possibility that accounts might only have Kiln, only have FogBugz, or have both.&lt;/p&gt;
&lt;p&gt;In all, thousands of developer hours were spent developing and maintaining something that had nothing to do with the software our customers were paying us for. Time that we could have spent on writing new features and fixing bugs for customers was instead spent digging into stringy old billing code. What&#39;s worse, the system always was and, unless some &lt;a href=&#34;http://www.joelonsoftware.com/articles/fog0000000069.html&#34;&gt;great rewrite happens&lt;/a&gt;, will always be a mess. (Little known fact: The odds of such a rewrite happening on such a critical system are 2&lt;sup&gt;276709&lt;/sup&gt; to 1 against.) The fact is, writing billing software is not Fog Creek&#39;s core competency.&lt;/p&gt;
&lt;p style=&#34;text-align:center&#34;&gt;&lt;img src=&#34;/static/img/copilot/copilot.jpg&#34;&gt;&lt;/p&gt;

&lt;p&gt;I bring this story up because it seems to closely parallel the situation that lead to &lt;a href=&#34;http://blog.linode.com/2013/04/16/security-incident-update/&#34;&gt;Linode&#39;s recent security incident&lt;/a&gt;, in which they lost both their password database as well as their entire credit card database. (Fortunately, Fog Creek never suffered a similar loss of credit card data while we were still storing it ourselves.) In these sorts of security breaches, passwords are relatively easy to fix by requiring a password reset. The credit cards, however, are a much bigger problem, since they are often used many different places, requiring worried customers to update their credit card with every vendor they work with.&lt;/p&gt;
&lt;p&gt;(Fortunately, the credit card numbers were encrypted in the database. Unfortunately, they decided to store the public &lt;em&gt;and private&lt;/em&gt; key for those credit card numbers on the same server. According to Linode, the private key is encrypted with a &#34;complex passphrase&#34; which is &#34;not guessable, sufficiently long and complex, not based on dictionary words, and not stored anywhere but in our heads&#34;.)&lt;/p&gt;
&lt;p&gt;So how did Linode lose their entire credit card database to a hacker? Putting aside the technical details (which involve a zero-day exploit of ColdFusion), it comes down to Linode, a great VPS provider, spending time developing sensitive, complex systems that were outside of both their core competency and their main business. They, like Fog Creek, are not a payment processing company. Literally speaking, the system brings in the money, it&#39;s not what their customers pay them for. If, instead, they&#39;d simply paid for one of the many affordable credit card vaults available, whose job it is to securely store credit card numbers, this never would have happened.&lt;/p&gt;</description>
            <pubDate>Apr 19, 2013</pubDate>
            <link>http://tghw.com/blog/when-the-intern-writes-the-billing-system</link>
            <guid>http://tghw.com/blog/when-the-intern-writes-the-billing-system</guid>
        </item>
        
        
        <item>
            <title>Well that sucks, what else you got?</title>
            <description>&lt;h2&gt;The Conversation&lt;/h2&gt;
&lt;p&gt;It was getting towards the end of the breakfast hour on the second day of &lt;a href=&#34;http://businessofsoftware.org/&#34;&gt;Business of Software&lt;/a&gt;, and people started getting up to refill their coffee before the first session, leaving only &lt;a href=&#34;http://blog.asmartbear.com/&#34;&gt;Jason Cohen&lt;/a&gt; and me to chat while we finished our meal.&lt;/p&gt;
&lt;p&gt;&#34;So what do you do?&#34; he asked me. I explained that I used to work for &lt;a href=&#34;http://fogcreek.com/&#34;&gt;Fog Creek&lt;/a&gt;, but now I was off on my own, trying to start a company that provides &lt;a href=&#34;https://www.snaposit.com/&#34;&gt;photo backup for serious photographers&lt;/a&gt;. He asked the questions I&#39;ve come to expect from people in the tech industry. &#34;How is it different than &lt;a href=&#34;http://db.tt/WhyfYBHJ&#34;&gt;Dropbox&lt;/a&gt;/&lt;a href=&#34;http://www.backblaze.com/partner/af3947&#34;&gt;BackBlaze&lt;/a&gt;? Where are you storing the files?&#34; And so on.&lt;/p&gt;
&lt;p&gt;Then he asked the key question. &#34;How&#39;s it going so far?&#34;&lt;/p&gt;
&lt;p&gt;&#34;Well, to be honest, very slowly.&#34; I proceeded to describe how we&#39;d gotten a strong showing of interest by being featured on &lt;a href=&#34;http://betali.st/&#34;&gt;betali.st&lt;/a&gt;, only to have to drastically restructure pricing in a way that significantly cut our margins. Then, how, even with the new pricing, conversion rates were dismally low. I explained who our competition was and how we were having trouble explaining to our users why we were better. I repeated an observation that a former coworker had made, that the photography market is inverted, amateurs have plenty of money but don&#39;t care (that much) if they lose their photos, while professionals, whose businesses could be devastated be losing a single shot, don&#39;t have a lot of extra money to spend. Lastly, I pointed out that an effective marketing campaign would almost necessarily rely on convincing people that something bad (i.e. losing all of their photos) will likely happen to them sometime in the future, a particularly unappealing proposition to me.&lt;/p&gt;
&lt;p&gt;Jason listened patiently while I explained all of this, and then summed it all up.&lt;/p&gt;
&lt;p&gt;&#34;Well that sucks, what else you got?&#34;&lt;/p&gt;
&lt;h2&gt;The Realization&lt;/h2&gt;
&lt;p&gt;It had slowly been occurring to me over the past week. Snaposit was probably done. My co-founder, &lt;a href=&#34;http://keacher.com&#34;&gt;Jeff&lt;/a&gt; and I had already put it on the back burner to focus on Jeff&#39;s &lt;a href=&#34;https://www.blurity.com/&#34;&gt;photo deblurring software&lt;/a&gt;, Blurity. Further development was becoming harder to justify.&lt;/p&gt;
&lt;p&gt;Over the course of Business of Software, I became more open about talking with people about the problems we were running into. The hope was that the more experienced entrepreneurs I was talking to would be able to provide some reassurance. But reassurance was not forthcoming. If anything, I was hearing more reasons why it would be a tough sell.&lt;/p&gt;
&lt;p&gt;My talk with Jason gelled it all together in that single phrase. &#34;Well that sucks, what else you got?&#34;&lt;/p&gt;
&lt;p&gt;I realized it at the time, but it took me another few days before I could admit it. Keeping Snaposit going just didn&#39;t make any sense. Sure, it wasn&#39;t hemorrhaging cash, but it did have a slow leak. More importantly, it was still demanding enough attention to be detracting from other projects. To keep it running in the hopes that it might miraculously take off at some point in the future was unrealistic. It was time to shut it down.&lt;/p&gt;
&lt;h2&gt;The Causes&lt;/h2&gt;
&lt;h4&gt;Poor Conversion Rates&lt;/h4&gt;
&lt;p&gt;While we were thrilled with the response from betali.st, the subsequent conversions were abysmally low. With those numbers, we would have to find traffic sources ten times larger than betali.st, every week for two years before we would even reach the level of &#34;lifestyle business&#34;. Of course, we could hope to improve the conversion rate or the incoming traffic, but the numbers were still pretty poor. More realistically, it would take us much longer to hit the sort of revenue levels we were looking for.&lt;/p&gt;
&lt;h4&gt;Misunderstanding Our Market&lt;/h4&gt;
&lt;p&gt;In hind sight, there was a disconnect between what people said they thought was a good idea and what they would actually pay for. Almost everyone we talked to said something similar: &#34;That&#39;s a really good idea.&#34; We heard it enough times that we really thought we were onto something. But there were two problems with this feedback: First, we were talking to more software developers, friends, and family than actual photographers. Second, we were just getting feedback on the idea itself, not on whether people would pay for it or not. Of course people think an automatic backup service is a good idea. It&#39;s like flossing, one of those things that everyone knows they &lt;em&gt;should&lt;/em&gt; do, but the majority of people still neglect actually doing.&lt;/p&gt;
&lt;p&gt;We also didn&#39;t fully understand what photographers wanted and needed. One of Snaposit&#39;s big features was that it backed up your entire library faster than a general backup service. It did this by compressing the photos to full resolution, high quality JPEGs, which saved anywhere from 50%-90% of the size. The downside of this, of course, is that photographers who shoot in RAW would only have a JPEG copy backed up. We figured this was a reasonable compromise. In a catastrophic event, wouldn&#39;t a photographer rather have a JPEG copy than nothing at all? It turns out the answer was no. But we didn&#39;t ask that question, because we thought the answer was so obvious.&lt;/p&gt;
&lt;p&gt;Lastly, we wrote the first version of the Snaposit desktop application for Windows. We figured, &#34;We&#39;re photographers who use Windows, we&#39;ll be able to find beta testers for this version and we&#39;ll get to the Mac version once all the bugs are ironed out.&#34; Nope. We couldn&#39;t find a single beta tester who used Windows.&lt;/p&gt;
&lt;h4&gt;The Loss of a Founder&lt;/h4&gt;
&lt;p&gt;For various reasons, the amount of personal runway Jeff and I had differed greatly. At a point, it became very clear that Snaposit would not be pulling in revenue before we reached the end of Jeff&#39;s runway. He decided that, in order to remain financially secure, he would shift his focus to &lt;a href=&#34;https://www.blurity.com/&#34;&gt;Blurity&lt;/a&gt;, which was much closer to having a reliable revenue stream. I fully supported his decision, but it meant that the majority of the Snaposit work fell to me after that point. While this seemed feasible at the time, in retrospect, it did cut the chances of Snaposit&#39;s success. Unfortunately, there wasn&#39;t really any other way around it, it was just the reality of the situation. To this day, I still fully support Jeff&#39;s decision.&lt;/p&gt;
&lt;h2&gt;The Lessons&lt;/h2&gt;
&lt;p&gt;Of course, the experience was not a total loss, by any means. We learned a lot from failing. Below is a quick list of what we learned about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to apply for Y Combinator and Tech Stars.&lt;/li&gt;
&lt;li&gt;How to integrate Stripe&#39;s subscription plans.&lt;/li&gt;
&lt;li&gt;Python on the desktop with WxPython.&lt;/li&gt;
&lt;li&gt;Mac development and deployment.&lt;/li&gt;
&lt;li&gt;How to organize and form an LLC.&lt;/li&gt;
&lt;li&gt;A better look at the backup industry.&lt;/li&gt;
&lt;li&gt;That Jeff and I work well together.&lt;/li&gt;
&lt;li&gt;How to run an effective &lt;a href=&#34;http://99designs.com/&#34;&gt;99designs&lt;/a&gt; competition.&lt;/li&gt;
&lt;li&gt;Twitter&#39;s Bootstrap framework.&lt;/li&gt;
&lt;li&gt;Desktop deployment and installers.&lt;/li&gt;
&lt;li&gt;How to ask better questions about our market.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All told, we actually did quite well. For this experience, we spent less than $1,000. Compared to an entrepreneurship class at any college, that&#39;s quite cheap!&lt;/p&gt;
&lt;h2&gt;The Next Step&lt;/h2&gt;
&lt;p&gt;Jeff is continuing to work on &lt;a href=&#34;https://www.blurity.com/&#34;&gt;Blurity&lt;/a&gt;. The &lt;a href=&#34;http://thenextweb.com/dd/2012/09/13/image-correction-app-blurity-now-available-mac-os-x/&#34;&gt;recent&lt;/a&gt; &lt;a href=&#34;http://lifehacker.com/5942893/blurity-fixes-blurry-photos-makes-them-worth-sharing-with-others&#34;&gt;press&lt;/a&gt; &lt;a href=&#34;http://www.applesfera.com/aplicaciones/blurity-llega-a-mac-recupera-la-nitidez-en-las-fotos-borrosas&#34;&gt;he&#39;s&lt;/a&gt; &lt;a href=&#34;http://www.petapixel.com/2012/09/13/blurity-magically-deblurs-photos-affected-by-slow-shutters-and-shaky-hands/&#34;&gt;gotten&lt;/a&gt; has kicked Blurity into overdrive and he&#39;s continuing to knock it out of the park.&lt;/p&gt;
&lt;p&gt;As for me, there are a few small side projects that could use some attention. I&#39;m also getting back into writing. A few larger ideas are percolating, but nothing&#39;s quite finished brewing yet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Comments for this post can be found on &lt;a href=&#34;http://news.ycombinator.com/item?id=4661636&#34;&gt;Hacker News&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;</description>
            <pubDate>Oct 16, 2012</pubDate>
            <link>http://tghw.com/blog/well-that-sucks-what-else-you-got</link>
            <guid>http://tghw.com/blog/well-that-sucks-what-else-you-got</guid>
        </item>
        
        
        <item>
            <title>Gatekeeper: Using FUD to get Developers to Pony Up</title>
            <description>&lt;p&gt;A new user comes to your site and downloads your installer. They extract the disk image and fire up the PKG  file. They&#39;re greeted with this message.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Corrupt&#34; src=&#34;//cdn.tghw.com/static/img/gatekeeper/corrupt.png?1&#34;&gt;&lt;/p&gt;
&lt;p&gt;&#34;Hmm,&#34; they think to themselves, &#34;maybe something went wrong with the download.&#34; So they download it again, extract the disk image and run the PKG file again. Same error. The file is damaged. Now running late to pick up their kids from school, your new users leaves, likely never to come back.&lt;/p&gt;
&lt;p&gt;This is their first introduction to Gatekeeper, a new feature of OS X 10.8, a.k.a. Mountain Lion. Intended as an anti-malware feature, Gatekeeper prevents downloaded applications from running, depending on their source. Similar to the SmartScreen in Windows, Gatekeeper presents the user with a warning when they are trying to run unsigned applications.&lt;/p&gt;
&lt;p&gt;However, there are two important differences between Gatekeeper and SmartScreen.&lt;/p&gt;
&lt;p&gt;First, with SmartScreen, the user has the option to continue running the application, despite not being signed. However, the default option for Gatekeeper provides no option to continue.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Gatekeeper dialog&#34; src=&#34;//cdn.tghw.com/static/img/gatekeeper/no-open.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;(Note, for applications, unlike PKG files, the warning dialog is somewhat more helpful, though it still does not allow the user to actually run anything.)&lt;/p&gt;
&lt;p&gt;This causes problems for any developers who have not paid Apple $100 for the Mac Developer Program, as the users are not left with any obvious way of continuing past the warning. This includes many developers who have chosen &lt;a href=&#34;http://mattgemmell.com/2012/08/24/releasing-outside-the-app-store/&#34;&gt;not to release via the App Store&lt;/a&gt;. &lt;a href=&#34;http://keacher.com/&#34;&gt;Jeff&lt;/a&gt; and I have run into this problem already with users of both &lt;a href=&#34;https://www.snaposit.com/&#34;&gt;Snaposit&lt;/a&gt; and &lt;a href=&#34;https://www.blurity.com/&#34;&gt;Blurity&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The second, and possibly more troubling , is that Apple is the only source for developer certificates. With SmartScreen, there are a wide variety of certificate authorities and brokers to choose from, each of which offers different pricing options, so the developer has a chance to comparison shop, which yields prices on the order of a third of the cost of the Mac Developer Program. But for Mac developers, Apple has created an artificial barrier instead of using existing and well established signing practices in order to make themselves a monopoly for developer certificates.&lt;/p&gt;
&lt;h3&gt;Is there any way around it?&lt;/h3&gt;
&lt;p&gt;Yes, but you&#39;re going to have to educate your users. Each and every one of them.&lt;/p&gt;
&lt;p&gt;There are two options:&lt;/p&gt;
&lt;p&gt;The first, and easiest, is to instruct your users to Control-Click (or right-click) the application once they&#39;ve downloaded and installed it. From the context menu, the&#39;ll need to choose &#34;Open&#34;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Context menu&#34; src=&#34;//cdn.tghw.com/static/img/gatekeeper/ctrl-click.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;When they start the application this way, they&#39;ll be presented with a slightly different warning dialog, which allows them to continue.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Gatekeeper dialog&#34; src=&#34;//cdn.tghw.com/static/img/gatekeeper/ctrl-open.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;The next time they launch the application, they shouldn&#39;t see any warnings.&lt;/p&gt;
&lt;p&gt;The other option is to have them disable Gatekeeper entirely. To do this, have them go to System Preferences and choose Security &amp;amp; Privacy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;System preferences&#34; src=&#34;//cdn.tghw.com/static/img/gatekeeper/system-prefs.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;Once there, they&#39;ll need to click the lock in order to make changes. Once they&#39;ve unlocked the preferences, they&#39;ll need to choose &#34;Anywhere&#34; from the list of options under &#34;Allow applications downloaded from:&#34;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;Security preferences&#34; src=&#34;//cdn.tghw.com/static/img/gatekeeper/security-prefs.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;This will essentially disable Gatekeeper, reverting their computer&#39;s security to a state similar to OS X Lion. Obviously, this isn&#39;t ideal, but if it&#39;s something they might run into often, it might be the best choice.&lt;/p&gt;</description>
            <pubDate>Aug 29, 2012</pubDate>
            <link>http://tghw.com/blog/gatekeeper-using-fud-to-get-developers-to-pony-up</link>
            <guid>http://tghw.com/blog/gatekeeper-using-fud-to-get-developers-to-pony-up</guid>
        </item>
        
        
        <item>
            <title>Snaposit is Live!</title>
            <description>&lt;p&gt;As I &lt;a href=&#34;http://tghw.com/blog/pull-hard&#34;&gt;wrote about a few months ago&lt;/a&gt;, we applied to Y Combinator&#39;s summer class this year. We got an interview with Paul Graham himself, but ultimately we were not accepted into the program. But we didn&#39;t let that stop us.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So what are we going to do?&lt;/p&gt;
&lt;p&gt;We&#39;re going to grab our bootstraps and pull hard.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&#39;m proud to announce that, after several months of hard work, our product and company, &lt;a href=&#34;https://www.snaposit.com/&#34;&gt;Snaposit&lt;/a&gt; has officially launched!&lt;/p&gt;
&lt;p&gt;We flipped the switch yesterday, moving all of our beta users onto actual subscription plans. (Heavily discounted, of course, to thank them for their help.) As with all launch days, there were a few small bugs that cropped up, but overall the day was pretty quiet, which is always a good sign.&lt;/p&gt;
&lt;p&gt;But we&#39;re not done yet. In fact, it might be safe to say that the past few months were the easy part. Now we have the task of making people aware of Snaposit and convincing them of how useful it is.&lt;/p&gt;
&lt;p&gt;So with the celebratory drinks out of the way, it&#39;s time to get back to work. We&#39;ve done a good job of pulling our own bootstraps so far, but there&#39;s a good bit more that needs to be done before we&#39;re fully on our feet.&lt;/p&gt;</description>
            <pubDate>Aug 02, 2012</pubDate>
            <link>http://tghw.com/blog/snaposit-is-live</link>
            <guid>http://tghw.com/blog/snaposit-is-live</guid>
        </item>
        
        
        <item>
            <title>Go Lock Your Laptop, Right Now</title>
            <description>&lt;p&gt;My father&#39;s home was burgled today. Fortunately, everyone is okay and everything that was taken can be replaced. As with most burglaries, the list of items taken is a little strange and the list of items not taken is even stranger.&lt;/p&gt;
&lt;p&gt;One thing the burglars did get was my dad&#39;s laptop. It&#39;s a first-version MacBook Air, probably of little value at this point. But, it did have a wealth of information on it.&lt;/p&gt;
&lt;p&gt;My first question to my dad was &#34;Did the computer have a password?&#34;. He didn&#39;t remember, which probably means it didn&#39;t. Of course, requiring a password to log in by no means guarantees that someone can&#39;t get in to the computer. But it does pose a significant road block to most people, and that&#39;s the point of any type of security: make it difficult enough that it&#39;s no longer worth someone&#39;s time or effort to break into it.&lt;/p&gt;
&lt;p&gt;Consider for a second what sort of data someone would have if they got a hold of your computer. If you&#39;re like most people, your browser knows most of your passwords. That means access to your email, which means access to everything else. Speaking of email, they&#39;d probably have access to every email you&#39;ve ever sent or received, especially if you use a desktop email client like Outlook or Thunderbird. And then your files. Pictures of friends and family. Financial documents.&lt;/p&gt;
&lt;p&gt;Now consider how easily your computer could walk off. As humans, we tend to have a flawed belief that it will never happen to us, but it has to happen to someone. Laptops are designed to be portable. And desktops are pretty easy to pick up and carry off.&lt;/p&gt;
&lt;p&gt;So consider this a reminder to &lt;em&gt;at least&lt;/em&gt; make sure your computer have a good password. It will act as a solid castle wall, if your computer is stolen. Also, get all of your passwords into a password vault, not your browser. Personally, I like &lt;a href=&#34;https://lastpass.com/&#34;&gt;LastPass&lt;/a&gt;, but there are many good ones out there. (If you do choose LastPass, make sure your sessions time out after a certain amount of idle time, so the passwords are harder to use.) If you have any sensitive files on your computer, consider encrypting them with a tool such as &lt;a href=&#34;http://www.truecrypt.org/&#34;&gt;TrueCrypt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lastly, make sure you secure &lt;em&gt;all&lt;/em&gt; of your computers. Especially that one in your pocket. It&#39;s the easiest to lose, and contains as much information as any of your other computers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; I forgot to add this part, but you also may want to consider installing a lojack. Personally, I use &lt;a href=&#34;http://preyproject.com/&#34;&gt;Prey&lt;/a&gt;, which will send you location information, screen shots, and pictures from the webcam. You can either pay them for service, or set it up yourself, which is pretty easy to do.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update 2:&lt;/em&gt; A reader wrote in suggesting that I also mention using full drive encryption. If you&#39;re using Windows, BitLocker (built into some versions of Windows 7) or TrueCrypt can do this for you. On Mac, use File Vault. Full drive encryption would completely prevent an attacker from gaining any access to the data on the machine.&lt;/p&gt;</description>
            <pubDate>Jun 14, 2012</pubDate>
            <link>http://tghw.com/blog/go-lock-your-laptop-right-now</link>
            <guid>http://tghw.com/blog/go-lock-your-laptop-right-now</guid>
        </item>
        
    </channel>
</rss>