<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PerfectAPI Blog</title>
	<atom:link href="http://blog.perfectapi.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.perfectapi.com</link>
	<description>Notes from the Perfect API Team</description>
	<lastBuildDate>Thu, 16 Feb 2012 16:25:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>An experiment in re-use</title>
		<link>http://blog.perfectapi.com/2012/an-experiment-in-re-use/</link>
		<comments>http://blog.perfectapi.com/2012/an-experiment-in-re-use/#comments</comments>
		<pubDate>Thu, 16 Feb 2012 16:25:17 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://dukeytoo.wordpress.com/?p=167</guid>
		<description><![CDATA[The next time that you have the opportunity to re-write part or all of an existing software application, consider performing this experiment. It is a thought experiment to help you determine what are the most valuable pieces of code that you will write, and perhaps achieve some enlightenment on the nature of software. The experiment [...]]]></description>
			<content:encoded><![CDATA[<p>The next time that you have the opportunity to re-write part or all of an existing software application, consider performing this experiment.</p>
<p>It is a thought experiment to help you determine what are the most valuable pieces of code that you will write, and perhaps achieve some enlightenment on the nature of software. The experiment can be done in your head or with a pen &amp; paper:</p>
<hr />
<p>Review the existing application, and find all of the parts that you think are re-usable in your current effort. Perhaps there will be just a few, perhaps there will be none, perhaps there will be a bunch.</p>
<p>Consider each of the re-usable parts and answer the questions:</p>
<ul>
<li>why is this re-usable?</li>
<li>what would have to change in the current effort to make this not re-usable?</li>
</ul>
<p>Now, skip forward in time and imagine you have successfully completed re-writing the parts that you decide to re-write. It was a wonderful success, and the application has grown and expanded in wonderful ways.</p>
<p>Technologies have changed, it is 10 years in the future, and it is time for the next re-write. Perform the experiment again, and write down the answers that you will want to have this time.</p>
<hr />
<p>The point of the experiment is to highlight that there is very little value intrinsically stored in source code. The only things that have long-term value are <span style="font-weight: bold;">abstractions and standards</span>.</p>
<p>Standards (html, css) are valuable only as long as the technology survives. They are valuable because everyone is dependent on them, and it simply costs too much to abandon them completely.</p>
<p>A sub-category of standards are vendor-specific technologies. Think VB6 forms, .NET forms, ASP or PHP or XAML. They still have value, but they come with the cost of a technology tie-in &#8211; they are only valuable as long as the technology lives.</p>
<p>Many standards are a form of debt. You accept that you will get a lower cost of development today, but that the application will only be able to be maintained and grow as long as the technology or standard is viable. It is often a very good type of debt, because there is a balloon payment at the end that you will never have to make (because the application will die before it is necessary).</p>
<p>Abstractions are longer-lived, because they can represent some fundamental domain knowledge. They are valuable as long as the domain and your assumptions do not change.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/an-experiment-in-re-use/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a PaaS in 1 week &#8211; retrospective</title>
		<link>http://blog.perfectapi.com/2012/writing-a-paas-in-1-week-retrospective/</link>
		<comments>http://blog.perfectapi.com/2012/writing-a-paas-in-1-week-retrospective/#comments</comments>
		<pubDate>Tue, 14 Feb 2012 15:18:09 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[paas]]></category>
		<category><![CDATA[perfectapi]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=526</guid>
		<description><![CDATA[Well the week was last week, and while it was not as successful as I would have liked, it was a very productive week. Dogfooding http://en.wikipedia.org/wiki/Eating_your_own_dog_food.  The week was very valuable to me in that I discovered several bugs in the node-perfectapi package.  I also discovered some new features that would be helpful, so that [...]]]></description>
			<content:encoded><![CDATA[<p>Well <a href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/">the week</a> was last week, and while it was not as successful as I would have liked, it was a very productive week.</p>
<h2>Dogfooding</h2>
<p><a href="http://en.wikipedia.org/wiki/Eating_your_own_dog_food">http://en.wikipedia.org/wiki/Eating_your_own_dog_food</a>.  The week was very valuable to me in that I discovered several bugs in the <a href="https://github.com/perfectapi/node-perfectapi">node-perfectapi</a> package.  I also discovered some new features that would be helpful, so that was great because it will help me make the product better.</p>
<h2>Design</h2>
<p>My design had a couple of flaws.  That&#8217;s not so bad really &#8211; in my experience at least, a design seldom survives coding without some changes.  Luckily they were not major flaws &#8211;  I needed one more component to better manage the load on user-facing endpoints, and I needed to add something to support configuration of the deployed services.</p>
<h2>Usability</h2>
<p>Although the pieces are all working together, it is not yet a usable solution.  For one thing, there is only a publish function, no way to update or remove packages.  For another, you really need to be able to configure services for them to work.</p>
<h2>Learning new things</h2>
<p>This was one of the major gains for me &#8211; I learned all about <a href="http://redis.io/">Redis</a>.  It was not pretty.  The <a href="https://github.com/mranney/node_redis">node-redis</a> module I used works really great, but it is at a very low level.  Coding against Redis feels a but like coding in assembly language.  Concatenating strings to form keys feels wrong, as does the process of having to create my own indexes, and do my own serializing and deserializing of objects.  There is definitely a market for modules that take the Redis experience and add a layer of abstraction in order to lower the workload.</p>
<p>I also discovered the <a href="https://github.com/caolan/async">async</a> module.  Without it, coding against Redis in Node.js is next to impossible.  Really, it is ridiculously hard.  Painful like hard exercise (but without the health  benefits).</p>
<p>Another discovery was testing with <a href="http://visionmedia.github.com/mocha/">mocha</a> and <a href="https://github.com/visionmedia/should.js">should</a>.  This was also a little frustrating at times, because one page (albeit a long page) of mocha documentation really does not cut it.  However once I got the hang of it, it was nice to have some tests running.</p>
<h2>Next Steps</h2>
<p>I&#8217;ve invested enough in this that I think I will continue to improve it until it is usable for my purposes.  Not in one week though <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I&#8217;m also working on creating an AMI image for <a href="http://www.nodester.com/">Nodester</a>.  While I rejected Nodester for my own purposes (it does not have the features I wanted), I still would like to contribute a little to that project.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/writing-a-paas-in-1-week-retrospective/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a PaaS (using Node.js) in 1 week &#8211; Friday</title>
		<link>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-friday/</link>
		<comments>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-friday/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 14:28:23 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=521</guid>
		<description><![CDATA[This is a continuation of the post Writing a PaaS (using Node.js) in 1 week – Monday. Well Friday is done, and it was one of those days where a stupid bug eats hours of the day.  Pushed through it though (went to lunch &#8211; my favorite technique) I failed to get everything done that [...]]]></description>
			<content:encoded><![CDATA[<p>This is a continuation of the post <a title="Permanent Link to Writing a PaaS (using Node.js) in 1 week – Monday" href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/" rel="bookmark">Writing a PaaS (using Node.js) in 1 week – Monday</a>.</p>
<p>Well Friday is done, and it was one of those days where a stupid bug eats hours of the day.  Pushed through it though (went to lunch &#8211; my favorite technique) <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I failed to get everything done that I wanted to in 5 days, but at the same time I have met all of my original goals, except for an Amazon AMI image for hosting the front-end proxy.</p>
<h2>The Good</h2>
<p>All of the components are now functioning together.  The code is split into the following:</p>
<ul>
<li><a href="https://github.com/perfectapi/node-paas-registry" target="_blank">Service registry</a> &#8211; a single service which is responsible for maintaining all of the information about the installed services</li>
<li><a href="https://github.com/perfectapi/node-paas-machine-proxy" target="_blank">Machine proxy</a> &#8211; a self configuring reverse proxy running on each host machine</li>
<li><a href="https://github.com/perfectapi/node-paas-machine-host" target="_blank">Machine host</a> &#8211; a self configuring service host running on each host machine.  When it finds an eligible service, it installs it.  Also doubles as a command line interface to register applications (when run on a client machine)</li>
<li>Front-end proxy &#8211; a pre-configured <a href="http://www.apsis.ch/pound" target="_blank">pound</a> reverse proxy running in front of the machines hosts, directing traffic and terminating the SSL endpoint (https).</li>
</ul>
<p>I was able to use the CLI to register multiple apps, and the machine host and proxy services picked them up, installed them and exposed them correctly via the reverse proxy.  That is awesome!  Its just the happy path, but it makes me happy <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I have an Amazon AMI ready for the host machine.  It is <a id="amiLink" href="https://console.aws.amazon.com/ec2/home?region=us-east-1#launchAmi=ami-114b9b78" target="_blank">ami-114b9b78</a>.  Login as user `ubuntu`.  There is a readme.txt in the home folder with further instructions to configure the services.  But its not much use without a server running the machine registry <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h2>The Bad</h2>
<p>I realized that the frontend proxy needs to be self-configuring too, in order to direct the traffic to the correct machine(s).  So I&#8217;ll have to write another component.  The good part is that it can re-use a lot of the logic of the machine proxy code.</p>
<p>I also realized that I am not handling configuration for the services, which is an essential piece.  For example, if I install a service that depends on another, then I need to configure the endpoint for that other.  Perfectapi allows for service configuration through environment variables, but the service registry and the machine host do not yet have a way to make use of that technique.  I&#8217;ll have to add some code for that.</p>
<h2>The Ugly</h2>
<p>The code is not production ready.   It handles the happy path ok, but needs more work to be able to recover from problems (e.g. when a service fails to install).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-friday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a PaaS (using Node.js) in 1 week – Thursday</title>
		<link>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-thursday/</link>
		<comments>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-thursday/#comments</comments>
		<pubDate>Fri, 10 Feb 2012 15:24:51 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=518</guid>
		<description><![CDATA[This is a continuation of a previous post - Writing a PaaS (using Node.js) in 1 week – Monday. Thursday is over, the output of which is at https://github.com/perfectapi/node-paas-machine-host.  The purpose of the machine-host is to wait around until it sees that something needs hosting, and then host it.  It also takes care of the main command-line [...]]]></description>
			<content:encoded><![CDATA[<p>This is a continuation of a previous post - <a title="Permanent Link to Writing a PaaS (using Node.js) in 1 week – Monday" href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/" rel="bookmark">Writing a PaaS (using Node.js) in 1 week – Monday</a>.</p>
<p>Thursday is over, the output of which is at <a href="https://github.com/perfectapi/node-paas-machine-host">https://github.com/perfectapi/node-paas-machine-host</a>.  The purpose of the machine-host is to wait around until it sees that something needs hosting, and then host it.  It also takes care of the main command-line interface, providing the ability to publish an app from the command line.</p>
<p>The biggest challenge yesterday was that I had originally designed the upload of a packages files as a &#8220;push&#8221;, i.e. zip up you package and publish it.  Unfortunately that causes a number of issues, the main one being that Node.js doesn&#8217;t yet have a nice unzip component.  I looked at a lot of possible packages that could handle it, but their APIs were very low level and I don&#8217;t have time to deal with that complexity.   Also, the zip files turn out to be quite big, which slows things down.  Finally, its not that friendly to make people zip it up.</p>
<p>So&#8230;I switched to a &#8220;pull&#8221; model, where the host will pull the files out of Git.  That limits us currently to publishing publicly accessible packages stored on github or similar host, but hat can change later.</p>
<p>Another challenge was something that I ave struggled with every time I try to use it &#8211; Nodes support for spawning processes.  There are 3-4 different ways to spawn a process, but the problem is that for any given scenario, only one of them works properly.  So I try `spawn`, then I debug it because it is not working, then finally I try `exec` and it works right away.  Aargh.  Not  good.</p>
<p>Anyway, enough writing this blog; I still have a lot to do if I want to get something working by the end of the day&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-thursday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a PaaS (using Node.js) in 1 week – Wednesday</title>
		<link>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-wednesday/</link>
		<comments>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-wednesday/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 14:57:02 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[paas]]></category>
		<category><![CDATA[perfectapi]]></category>
		<category><![CDATA[proxy]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=514</guid>
		<description><![CDATA[This is a continuation of previous posts: Writing a PaaS (using Node.js) in 1 week – Monday Writing a PaaS (using Node.js) in 1 week – Tuesday Well Wednesday is done.  The reverse proxy is written, code at https://github.com/perfectapi/node-paas-machine-proxy. As a reminder, the purpose of the reverse proxy was to provide a single IP + host [...]]]></description>
			<content:encoded><![CDATA[<p>This is a continuation of previous posts:</p>
<ul>
<li><a title="Permanent Link to Writing a PaaS (using Node.js) in 1 week – Monday" href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/" rel="bookmark">Writing a PaaS (using Node.js) in 1 week – Monday</a></li>
<li><a title="Permanent Link to Writing a PaaS (using Node.js) in 1 week – Tuesday" href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-tuesday/" rel="bookmark">Writing a PaaS (using Node.js) in 1 week – Tuesday</a></li>
</ul>
<p>Well Wednesday is done.  The reverse proxy is written, code at <a href="https://github.com/perfectapi/node-paas-machine-proxy">https://github.com/perfectapi/node-paas-machine-proxy</a>.</p>
<p>As a reminder, the purpose of the reverse proxy was to provide a single IP + host endpoint to each machine (host) on which multiple services are running.  We can run multiple services on that host, or multiple instances of the same service.  The reverse proxy provides routing and round-robin load balancing between the services.  Each service runs on a unique path, e.g. http://host/service1, http://host/service2.</p>
<p>A higher level proxy will provide routing between machines and SSL termination, providing endpoints like https://mydomain.com/service1.</p>
<p>The reverse proxy must also automatically update its configuration when it detects a change in the Service Registry, and expose load information for the host (so that we can know when it is over capacity).</p>
<h2>How did it go?</h2>
<p>I had some conflict on whether to use one of the node.js reverse proxies (<a href="https://github.com/substack/bouncy" target="_blank">bouncy</a>, <a href="https://github.com/nodejitsu/node-http-proxy" target="_blank">node-http-proxy</a>) for the routing, or to use a more mature Linux package.  In the end I decided to go with <a href="http://haproxy.1wt.eu/" target="_blank">haproxy</a>, mainly because it has detection of when a particular endpoint is not responding, and can switch that endpoint off.  This should prove useful for when problems occur, or when services are being upgraded or scaled down.</p>
<p>It also supports hot-switching of the proxy configuration, which is awesome.</p>
<p>Once the decision was made, configuring haproxy was not very hard.  I had to take the time to read its configuration manual (a gigantic text file, argh).  Ok, I just skimmed it <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Testing</h2>
<p>I did less testing on this component than I did on the service registry.  I think its one of those things where you can only find the issues once you start loading up services and seeing what happens.</p>
<p>I did do enough testing to know that the code does what I want &#8211; its just a matter of figuring out if what I want will work in practice.  So I&#8217;ll do that on Thursday/Friday, and hopefully it will work itself out.</p>
<h2>Determining Load</h2>
<p>Determining the load was fairly easy.  I use a combination of the node-provided</p>
<pre>os.loadAvg()</pre>
<p>method, and calling</p>
<pre>ps -A u</pre>
<p>to find the process using the most CPU percentage.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-wednesday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a PaaS (using Node.js) in 1 week – Tuesday</title>
		<link>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-tuesday/</link>
		<comments>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-tuesday/#comments</comments>
		<pubDate>Wed, 08 Feb 2012 03:37:40 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[async]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[paas]]></category>
		<category><![CDATA[perfectapi]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=508</guid>
		<description><![CDATA[This is a continuation of the post Writing a PaaS (using Node.js) in 1 week – Monday. Well I&#8217;m going to call Tuesday done. The Service Registry is written and installed on my server. Source code is at https://github.com/perfectapi/node-paas-registry.  As with all perfectapi APIs, there is an automatic test app page.  I&#8217;ve exposed this one to [...]]]></description>
			<content:encoded><![CDATA[<p>This is a continuation of the post <a title="Permanent Link to Writing a PaaS (using Node.js) in 1 week – Monday" href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/" rel="bookmark">Writing a PaaS (using Node.js) in 1 week – Monday</a>.</p>
<p>Well I&#8217;m going to call Tuesday done. The Service Registry is written and installed on my server. Source code is at <a href="https://github.com/perfectapi/node-paas-registry">https://github.com/perfectapi/node-paas-registry</a>.  As with all perfectapi APIs, there is an automatic test app page.  I&#8217;ve exposed this one to the Internet, at <a href="https://services.perfectapi.com/paas/registry/testapp/">https://services.perfectapi.com/paas/registry/testapp/</a></p>
<p>So I&#8217;m on target, but it was a rough day.  My first challenge was <a title="Redis" href="http://redis.io/" target="_blank">Redis</a>.  I&#8217;ve not used it before, and there was a learning curve involved before I could effectively use it.  I used the <a title="node-redis" href="https://github.com/mranney/node_redis" target="_blank">node-redis</a> package to access it, and that package worked well.  It was just hard, trying to learn all of the commands, and when to use sets or hashes or whatever.  That ate a lot of time.</p>
<p>My next challenge was the async nature of the node-redis client.  Its fine if you&#8217;re just doing one thing, but I had a scenario that went like this:</p>
<ul>
<li>open a connection to the database</li>
<li>get the set of instance ids by service name (via callback)</li>
<li>for each instance id, get the full instance object (via callback), and if it matches some additional criteria then do something with it and stop processing</li>
<li>close the connection to the database</li>
</ul>
<p>The problem was that this is callback hell.  I couldn&#8217;t even figure out where to close the connection.  A little research found me the <a title="async node package" href="https://github.com/caolan/async" target="_blank">async</a> package, which was a lifesaver.  Once I started using that, it became very natural to solve the problem.</p>
<p>Finally, I had some problems with perfectapi <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />   Required parameters are supposed to validate, but they do not seem to be doing so.  I&#8217;ll have to take a look at that separately.</p>
<p>Anyway, lets hope tomorrow goes smoother&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%e2%80%93-tuesday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a PaaS (using Node.js) in 1 week &#8211; Monday</title>
		<link>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/</link>
		<comments>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 17:25:19 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[paas]]></category>
		<category><![CDATA[perfectapi]]></category>
		<category><![CDATA[rackspace]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=497</guid>
		<description><![CDATA[UPDATE: The week is over.  There is a retrospective post here. I have posted Tuesdays notes here, Wednesday&#8217;s notes here, Thursday&#8217;s notes here, and Friday&#8217;s notes here. I have decided to write a simple PaaS (Platform as a Service), in order to demonstrate the capabilities of my perfectapi API framework for Node.js.   I don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>UPDATE:</p>
<ul>
<li>The week is over.  There is a retrospective post <a href="http://blog.perfectapi.com/2012/writing-a-paas-in-1-week-retrospective/">here</a>.</li>
<li>I have posted Tuesdays notes <a href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%E2%80%93-tuesday/">here</a>, Wednesday&#8217;s notes <a title="Writing a PaaS (using Node.js) in 1 week – Wednesday" href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%E2%80%93-wednesday/">here</a>, Thursday&#8217;s notes <a href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-%E2%80%93-thursday/">here</a>, and Friday&#8217;s notes <a href="http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-friday/">here</a>.</li>
</ul>
<hr />
<p>I have decided to write a simple PaaS (<a title="PaaS" href="http://en.wikipedia.org/wiki/Platform_as_a_service" target="_blank">Platform as a Service</a>), in order to demonstrate the capabilities of my <a title="PerfectAPI" href="https://github.com/perfectapi/node-perfectapi" target="_blank">perfectapi API framework</a> for <a title="Node.js" href="http://nodejs.org/" target="_blank">Node.js</a>.   I don&#8217;t want to compete with other PaaS offerings &#8211; this is just a need that my company has &#8211; to demonstrate how to <span style="text-decoration: underline;">simply and easily self-host and scale</span> services developed with perfectapi.</p>
<p>Doing it in one week is a challenge I put to myself, because I have a limited amount of time to devote to this, and because doing it in one week (5 days) can drive a little PR for perfectapi.</p>
<p>So what exactly will I be building?  The platform will have the following qualities:</p>
<ul>
<li>Ability to deploy multiple Node.js perfectapi-based services, and load balance multiple instances of those services</li>
<li>Each PaaS platform supports a single domain endpoint &#8211; in my case it will be services.perfectapi.com</li>
<li>PaaS service endpoints accessible via JavaScript, Node.js, C#, REST and command line, built using perfectapi</li>
<li>Hosted service endpoints accessible via JavaScript, Node.js, C#, REST and command line, built using perfectapi</li>
<li>Provide the groundwork to automatically scale out as load increases (actual feature of automatically scaling out is not in scope for this week, but manually scaling out will be possible)</li>
<li>Services all run behind SSL</li>
<li>Complete code and Amazon AMI images (Ubuntu 11.10)  to be provided, so that others can reproduce the PaaS environment easily</li>
<li>Written in Node.js and using freely available Linux tools where necessary</li>
<li>No security to speak of (limit access using firewalls or shared secrets)</li>
</ul>
<div>I&#8217;ll host all the code in <a title="perfectapi repository on github" href="https://github.com/perfectapi" target="_blank">my projects on github</a>, and update this blog as I progress&#8230;</div>
<h2>Day 1 (Monday) &#8211; Design</h2>
<p>I spent most of Monday in Caribou coffee, researching and designing on my iPad.  Oh, the life I lead <img src='http://c274143.r43.cf1.rackcdn.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The design I have consists of several components.  At the core is the Service Registry, which stores a list of the services installed in my domain.</p>
<h2>Day 2 (Tuesday) - Service Registry</h2>
<p>The service registry maintains a record of detail for each service instance, including the unique service name, and the path on which it will host.  So for example, the following:</p>
<ul>
<li>&#8220;Payment Portal&#8221;, /payments, attributes,  files</li>
<li>&#8220;Payment Portal&#8221;, /payments, attributes, files</li>
<li>&#8220;Mailer&#8221;, /email, files</li>
</ul>
<p>&#8230;represents 3 service instances.  The first two are instances of the same service, and host on the same &#8220;/payments&#8221; path.  The 3rd is another service.  Each instance has its own copy of the files, and has a set of attributes.</p>
<p>In my &#8220;services.perfectapi.com&#8221; domain, the records above would represent 2 endpoints:</p>
<ul>
<li>https://services.perfectapi.com/payments &#8211; load balanced across 2 instances</li>
<li>https://services.perfectapi.com/email &#8211; pointing at a single instance</li>
</ul>
<p>The Service Registry does not create these services, or manage their endpoints, or anything really other than record their existence.   It will have the following API commands and queries:</p>
<ul>
<li>RegisterInstance(service name, path, attributes, files) &#8211; creates a new record of a service instance</li>
<li>UnregisterInstance(service name, path, [host], [port]) &#8211; removes a single matching existing record of a service instance</li>
<li>GetServiceInfo(service name) &#8211; returns array of host, path, port, attributes, files</li>
<li>ListServices &#8211; lists service names</li>
<li>ListUnclaimedServices &#8211; lists service names which do not yet have a port and host specified.  May list the same service name multiple times if their are multiple matches.</li>
<li>ClaimService(service name, path, host, port, attributes) &#8211; updates an unclaimed service instance with new details.  If there are multiple unclaimed instances, then only one will be updated.  If there are no matches, returns an error.</li>
</ul>
<div>For simplicity sake, the line between a service instance and a service definition (or an &#8220;app&#8221;) is going to be blurry.</div>
<p>In version 1, the Service Registry will probably store its data in Redis.  In later versions I would like if it could use DNS-SD.</p>
<h2>Day 3 (Wednesday) - Reverse Proxy</h2>
<p>The Service Registry was a single service for a domain.  The Reverse Proxy is a single service per machine.  The Reverse Proxy monitors the Service Registry, and ensures that all instances on the current machine have a route from outside.  So for example, on the current host we may have the following in the service registry:</p>
<ul>
<li>&#8220;Payment Portal&#8221;, /payments, port 4001, host ABC</li>
<li>&#8220;Payment Portal&#8221;, /payments, port 4002, host ABC</li>
<li>&#8220;Mailer&#8221;, /email, port 4003, host ABC</li>
</ul>
<p>The Reverse Proxy ensures that all services are accessible on port 80, i.e.</p>
<ul>
<li>http://abc/payments &#8211; load balanced across 2 instances</li>
<li>http://abc/email &#8211; pointing at a single instance</li>
</ul>
<p>It also monitors the Service Registry for changes, and when it finds that there is a discrepancy, it updates the proxy configuration to create or remove a route.</p>
<p>In addition to routing traffic, the reverse proxy exposes an endpoint with load information for the machine it is installed on.  It exposes two methods:</p>
<ul>
<li>GetLoad &#8211; returns a number indicating current 5 minute load average.  1.0 or higher indicates that the server load is at or above capacity</li>
<li>GetCulprit &#8211; returns the name of the service instance that is most likely the culprit, i.e. the instance that is using the most CPU.  (I/O ignored because Node.js processes should not be I/O intense, and network ignored because it is unlikely to be a limitation in a cloud environment).</li>
</ul>
<h2>Day 4 &amp; 5 (Thursday &amp; Friday) - Hosting Server</h2>
<p>Like the Reverse Proxy, the Hosting Server runs a single instance per machine.  It contains the bulk of the PaaS functionality.  Specifically, it is responsible for:</p>
<ul>
<li>installing new app instances, on request (copying files, launching the process, ensuring it remains running).</li>
<li>removing app instances, on request</li>
<li>updating App registry when apps are added or removed</li>
</ul>
<p>The expected API methods are:</p>
<ul>
<li>PublishApp &#8211; publishes a new app</li>
<li>DeleteApp &#8211; deletes an existing app</li>
<li>UpdateApp &#8211; combination of a delete and a publish (publish new, then delete old)</li>
<li>GetAppDetails &#8211; returns the attributes of an app</li>
<li>ListApps &#8211; lists all apps</li>
<li>ListAppInstances &#8211; lists the instances for an app</li>
</ul>
<p>The Publish workflow goes something like this:</p>
<ul>
<li>Write new instance(s) to app registry (with empty host and port)</li>
<li>Poll App Registry every 1 minute</li>
<li>If an unclaimed service instance is found, and this server meets to service instance requirements, and this server&#8217;s load is low enough, then claim it (write host and port to Service Registry).</li>
</ul>
<p>The definition of &#8220; this server&#8217;s load is low enough&#8221; is that a call to the Unix &#8220;uptime&#8221; command returns a 5 minute load average number less than 1.0 per CPU of the system.  This criteria should work on both Amazon EC2 Instances and Rackspace Cloud Servers.</p>
<h2>Day 5 (Friday) &#8211; SSL Termination &amp; Load Balancing</h2>
<p>Another Reverse Proxy.  This one is a Linux package called &#8220;pound&#8221;, which can do SSL termination (host the https) as well as load balancing amongst our servers.  It works off of a static configuration file.  The file will not need to change as long as the list of servers remains static.</p>
<h2>Auto Scaling Server (Future)</h2>
<p>The part I will not build this week.  In order to scale out, we need to</p>
<ul>
<li>detect the need to scale &#8211; using GetLoad API call on the Reverse Proxies.</li>
<li>determine which service needs scaling &#8211; using GetCulprit API call on the overloaded Reverse Proxy</li>
<li>update the Service Registry with new instances</li>
</ul>
<p>That takes care of scaling out <span style="text-decoration: underline;">within the existing machines</span> in our cloud.  Once we exhaust the capacity of the existing machines, we have to start using 3rd party services, such as <a title="SCALR" href="http://scalr.net/" target="_blank">SCALR</a> or <a title="Auto Scaling" href="http://aws.amazon.com/autoscaling/" target="_blank">Amazon&#8217;s Auto Scaling</a>.  In that case, it probably makes sense to move the SSL termination and Load Balancing function off of our simple &#8220;pound&#8221; package.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/writing-a-paas-using-node.js-in-1-week-monday/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Demo Page</title>
		<link>http://blog.perfectapi.com/2012/demo-page/</link>
		<comments>http://blog.perfectapi.com/2012/demo-page/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 15:43:33 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ami]]></category>
		<category><![CDATA[amigen]]></category>
		<category><![CDATA[APIs]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[nodejs]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=487</guid>
		<description><![CDATA[I uploaded a new demo page for the PerfectAPI toolset today.  You can find it at http://amigen.perfectapi.com/ or from the link on the main website. The demo is of my &#8220;amigen&#8221; API, which provides a way to generate Amazon AWS images (virtual machines that run in Amazon&#8217;s cloud). The demo page showcases the following PerfectAPI [...]]]></description>
			<content:encoded><![CDATA[<p>I uploaded a new demo page for the PerfectAPI toolset today.  You can find it at <a title="Demo Page" href="http://amigen.perfectapi.com/" target="_blank">http://amigen.perfectapi.com/</a> or from the link on the main website. The demo is of my &#8220;amigen&#8221; API, which provides a way to generate Amazon AWS images (virtual machines that run in Amazon&#8217;s cloud).</p>
<p>The demo page showcases the following PerfectAPI features:<a href="http://c274143.r43.cf1.rackcdn.com/wp-content/uploads/2012/01/perfectapidemopage.png"><img class="alignright  wp-image-488" title="perfectapi demo page" src="http://c274143.r43.cf1.rackcdn.com/wp-content/uploads/2012/01/perfectapidemopage.png" alt="perfectapi demo page" width="278" height="322" /></a></p>
<h5>Self-configuring endpoint</h5>
<p>Simply add a script reference to the provided javascript file in your HTML and then you can directly call the exposed methods of that API without further knowledge of urls</p>
<h5>Simple rpc-style calls</h5>
<p>Calls to the api are simple asynchronous calls in the rpc style (see example code on the demo page). There is no Ajax, JSON, JSONP, REST to worry about &#8211; its just simple Javascript code</p>
<h5>Long-running API calls</h5>
<p>Generating an image can take a while. Normally, this would timeout after 15-30 seconds, however this does not happen with PerfectAPI.</p>
<h5>Test Page</h5>
<p>The demo page is a custom page, but there is also an <a href="https://services.perfectapi.com/amigen/testapp/" target="_blank">automatically generated &#8220;test&#8221; page</a> for the API, where you can explore the API and see actual code in the language of your choice.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/demo-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New perfectapi.com website</title>
		<link>http://blog.perfectapi.com/2012/new-perfectapi.com-website/</link>
		<comments>http://blog.perfectapi.com/2012/new-perfectapi.com-website/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 19:51:33 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=474</guid>
		<description><![CDATA[I put a new version of the perfectapi.com website up today.  Previously I was just displaying this blog at that address. My business model is the common open source one, i.e. make a product that is free &#38; open source and charge for additional services. The page has a signup for the &#8220;public beta&#8221;, which [...]]]></description>
			<content:encoded><![CDATA[<p>I put a new version of the <a title="perfectapi.com" href="http://www.perfectapi.com/">perfectapi.com</a> website up today.  Previously I was just displaying this blog at that address.</p>
<p><a href="http://c274143.r43.cf1.rackcdn.com/wp-content/uploads/2012/01/perfectapidotcom.png"><img class="alignright size-full wp-image-475" title="perfectapi.com" src="http://c274143.r43.cf1.rackcdn.com/wp-content/uploads/2012/01/perfectapidotcom.png" alt="perfectapi.com home page" width="711" height="383" /></a></p>
<p>My business model is the common open source one, i.e. make a product that is free &amp; open source and charge for additional services.</p>
<p>The page has a signup for the &#8220;public beta&#8221;, which is really just a chance for someone that is interested to get in on the ground floor with free support and services.</p>
<p>PerfectAPI is both the name of the business and the name of the product, which can be a little confusing.  The product is a set of tools that facilitate the development of APIs, and the meshing of different APIs together in the cloud in such a way that they form a complete service offering.</p>
<p>Some of my competitors are apigee.com, hook.io (by nodejitsu).  Both of these companies offer a way of building a service offering using APIs, but they have a different focus than each other and myself.</p>
<p>My own focus is based on a vision of interconnected, discoverable services on the Internet, done very simply.  I know what my next steps are and I&#8217;m moving forward with that.</p>
<p>One of those next steps is to try to drive involvement and usage in the Node.js community.  I think <a title="node-perfectapi" href="https://github.com/perfectapi/node-perfectapi" target="_blank">my Node.js offering</a> is still a beta product, but nevertheless is very compelling for someone wanting to create a service API on the Internet.</p>
<p>Another piece I have to get working soon is authorization, i.e. OAUTH, OpenID, etc.</p>
<p>Anyway, if you have any questions, please comment <a title="Contact-Us form on web" href="http://www.perfectapi.com/contact-us.html">on the website itself</a> or leave a comment below.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/new-perfectapi.com-website/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Self-Hosting a Small WordPress Blog or Website on Amazon EC2</title>
		<link>http://blog.perfectapi.com/2012/self-hosting-a-small-wordpress-blog-or-website-on-amazon-ec2/</link>
		<comments>http://blog.perfectapi.com/2012/self-hosting-a-small-wordpress-blog-or-website-on-amazon-ec2/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 18:23:01 +0000</pubDate>
		<dc:creator>DukeyToo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ami]]></category>
		<category><![CDATA[amigen]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://blog.perfectapi.com/?p=456</guid>
		<description><![CDATA[Last week, as part of my effort to move my domains away from godaddy.com, I decided to move this blog.  That move is complete and what you are looking at is now hosted on an Amazon EC2 &#8220;instance&#8221;.  What follows is my experience and notes on the costs of doing this. The Costs First off, [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, as part of my effort to <a title="SOPA sucks" href="http://www.huffingtonpost.com/2011/12/29/godaddy-boycott-dcember-29_n_1174487.html" target="_blank">move my domains away from godaddy.com</a>, I decided to move this blog.  That move is complete and what you are looking at is now hosted on an Amazon EC2 &#8220;instance&#8221;.  What follows is my experience and notes on the costs of doing this.</p>
<h4>The Costs</h4>
<p>First off, on a 3 year hosting plan at Godaddy, I was paying about <strong>$3.20</strong> per month, which is very very cheap.   You cannot get that price directly, but I had some coupons.  A more normal cost for Godaddy is about <strong>$5.00</strong> per month.   My final costs for my new hosting solution on EC2 are:</p>
<ul>
<li><span style="text-decoration: underline;">First year</span>: $0 per month.</li>
<li><span style="text-decoration: underline;">Next 3 years</span>: <strong>$ 6.43</strong> per month, plus bandwidth (mostly free, unless I hit the front page of Reddit).</li>
</ul>
<p>This is not as good as Godaddy, but it is a very acceptable rate to me (given I have complete root access to the machine and can do anything I want with it).</p>
<p>Below is the analysis of the EC2 costs.  For reference, <a title="Amazon EC2 Pricing" href="http://aws.amazon.com/ec2/pricing/" target="_blank">here is a link to the EC2 pricing sheet</a>.  My costs are for the us-east Amazon region &#8211; costs in other regions are different.</p>
<ul>
<li><span style="text-decoration: underline;">First year</span>:  Amazon gives away <a title="750 hours of Amazon EC2 Linux Micro Instance usage (613 MB of memory and 32-bit and 64-bit platform support) – enough hours to run continuously each month" href="http://aws.amazon.com/free/" target="_blank">one t1.micro instance plus bandwidth</a> to new AWS customers for the first year.  This is why the first year is free.</li>
<li><span style="text-decoration: underline;">Next 3 years</span>:  <strong>$100</strong> for 3 years of &#8220;Heavy Utilization Reserved Instance&#8221; (t1.micro), plus $0.005 per hour (<strong>$43.80</strong> per year), do the math and that comes out to <strong>$6.43</strong> per month.</li>
</ul>
<div>Without the reserved instance purchase, the cost would be <strong>$14.60</strong> per month &#8211; significantly more.   Don&#8217;t make the same mistake as I did &#8211; <span style="text-decoration: underline;">wait for your free year to expire <strong>before</strong> purchasing the reserved instance!</span>   (Aaargh!  Actually, its not so bad for me because I plan on having more instances, so the free tier was never going to be enough).</div>
<h4>Actually doing the move &#8211; the easy way</h4>
<p>[UPDATE: I have posted a <a title="Youtube video walking through the easy way" href="http://youtu.be/d87dRlZNCAk?hd=1" target="_blank">short YouTube video</a> on how to do this]</p>
<p>The first step was to go into my existing WordPress blog and do a complete export of my posts and pages (Tools/Export/All Content).  With this downloaded to my local machine, I felt ready to get going.</p>
<p>WordPress boasts a <a title="Famous 5 minute install?" href="http://codex.wordpress.org/Installing_WordPress#Famous_5-Minute_Install" target="_blank">&#8220;famous 5 minute install&#8221;</a>, but don&#8217;t be misled by that &#8211; it can be done, but that depends highly on your Linux skills.  The PerfectAPI vision is to make things simpler, so I have for you the following, with all my experience of doing the move baked in.  Skip to &#8220;the hard way&#8221; further down in this post if you like it that way.</p>
<ul>
<li><a title="Launch an instance like this" href="https://console.aws.amazon.com/ec2/home?region=us-east-1#launchAmi=ami-e5e6328c" target="_blank">ami&#8211;e5e6328c</a> &#8211; a us-east Amazon EC2 Ubuntu 11.10 EBS image that is set to go with what you need.  Assuming you are already signed up and have some experiencing using ssh with Linux machines on EC2, this should give you something close to the 5 minute install.</li>
</ul>
<p>To start with the image above, first launch it into a t1.micro instance.  Be sure to use a security group that allows port 80 (http) access, and one that allows SSH access (port 22).  Once the image is running,  ssh into it using a tool like <a title="A free ssh client for Windows" href="http://www.putty.org/" target="_blank">Putty</a>.  A reasonable &amp; quick guide to using Putty for this purpose <a title="Managing an Amazon EC2 Instance Using PuTTY SSH" href="http://www.keywordintellect.com/amazon-web-services/managing-an-amazon-ec2-instance-using-putty-ssh/" target="_blank">can be found here</a>.  Note that the <span style="text-decoration: underline;">login name for the instance above is &#8220;<strong>ubuntu</strong>&#8220;</span>, not &#8220;root&#8221;.</p>
<p>Once logged in, install WordPress by executing the command:</p>
<pre>sudo ./install.sh</pre>
<p>(This is my custom install script).  Installing in this way ensures your instance has its own unique passwords for mysql and wordpress (not the same as everyone else using the above image).</p>
<p>Once the install completes (10 seconds), go the the <a title="AWS Console - Elastic IP" href="https://console.aws.amazon.com/ec2/home?region=us-east-1#s=Addresses" target="_blank">AWS console</a> and set yourself up an &#8220;Elastic IP&#8221;.  (An elastic IP is just a public IP address that you can point your domain at).  Associate your new Elastic IP with your new instance.    Then, go to your blog at:</p>
<pre>http://your-elastic-ip/</pre>
<p>&#8230;and complete the WordPress setup.  Use Tools/Import/Wordpress to re-import all of your posts and pages.  Setup your theme, play with your widgets, install some plugins.   <span style="text-decoration: underline;"><strong>Do not</strong> change the url of the blog in your General Settings until you are ready to switch over</span>.  Failing to heed this advice will make the new blog redirect to the old whenever you login.  Very annoying and difficult to change back.</p>
<p>Final step is to switch your domain records &#8211; use whatever tools your DNS provider has to point your domain at your elastic IP address.  After that, you can set the correct URL in the General Settings of the new blog.   It can take a while before DNS changes kick in &#8211; if you&#8217;re impatient, you can temporarily <a title="Windows 7 – Edit the Hosts file" href="http://helpdeskgeek.com/windows-7/windows-7-hosts-file/" target="_blank">edit your hosts file</a> to see the changes early.</p>
<p>Put a note on your calendar for 1 year after your Amazon AWS signup date, to purchase yourself a reserved instance, so that the lower pricing kicks in.</p>
<h4>Doing the move &#8211; the hard way</h4>
<p>The first trick for getting any new instance up on Amazon is to find a base AMI image that you like.  I like the Ubuntu images  at <a title="Alestic Ubuntu AMI Images" href="http://alestic.com/index.html" target="_blank">Alestic</a>, so that is where I started.  After creating an image with an instance, you have a way to go before you can even get started on WordPress, for example you need to install a LAMP stack (apache, mysql, php), you want to ensure the instance stays up-to-date with linux security patches, etc.  Anyway, I created scripts to be able to do all of this in a repeatable way, and they can be found on my <a title="amigen source on Github" href="https://github.com/perfectapi/ami-generator" target="_blank">amigenerator project on Github</a>.</p>
<p>If you need, here is a <a title="LAMP and WordPress scripts" href="https://github.com/perfectapi/ami-generator/tree/master/scripts/ubuntu11.10/LAMP" target="_blank">direct link to the scripts</a>.  The scripts only work when run from the ami-generator tool, so looking at them on Github is mostly for education.  The ami-generator tool itself is still in alpha stage, so I am not going to include instructions on how to install/use it here.</p>
<p>My advice &#8211; just do it the easy way instead.  (But if you do have suggestions on how to improve the scripts, please do let me know).</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.perfectapi.com/2012/self-hosting-a-small-wordpress-blog-or-website-on-amazon-ec2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Content Delivery Network via Rackspace Cloud Files: c274143.r43.cf1.rackcdn.com

Served from: blog.perfectapi.com @ 2012-02-22 17:10:57 -->
