<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Elad Ben-Israel</description><title>hackingonstuff</title><generator>Tumblr (3.0; @eladb)</generator><link>http://hackingonstuff.net/</link><item><title>cantest: avoid regression in HTML5 canvas rendering code</title><description>&lt;p&gt;In a project we are working on we have quite a lot of code that eventually draws on an HTML5 canvas. Since we work in a team and have multiple layers of code involved in generating the final result, there&amp;#8217;s always a chance for regression (like in any other codebase).&lt;/p&gt;

&lt;p&gt;This is applicable to any codebase that generates visual elements on an HTML5&amp;#160;&lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an initial step, we needed a very basic tool that can simply run a canvas drawing function and compare the result to a predefined expectation PNG. This way, we can create a set of tests that protect us against regressions. In the future we might extend this tool to support testing regression of dynamic scenes as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/eladb/node-cantest"&gt;node-cantest&lt;/a&gt; is a simple library/tool that runs test functions (exported by a node.js module) and compares the rendered result to a pre-existing expectation PNG file. If the results differ, it optionally pops up a browser window with the two PNGs.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s run through a simple example.&lt;/p&gt;

&lt;h3&gt;Create a drawing function&lt;/h3&gt;

&lt;p&gt;Create a directory for our hello world example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ mkdir hello-cantest
$ cd hello-cantest
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create &lt;code&gt;hello.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/3046190"&gt;https://gist.github.com/3046190&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;Create a test&lt;/h3&gt;

&lt;p&gt;First, install &lt;a href="https://github.com/learnboost/node-canvas"&gt;node-canvas&lt;/a&gt; so that the test can create a &lt;code&gt;CanvasRenderingContext2D&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ npm install canvas
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note that node-canvas uses &lt;a href="http://en.wikipedia.org/wiki/Cairo_(graphics)"&gt;Cairo&lt;/a&gt; for rendering, so see any notes under the &lt;a href="https://github.com/learnboost/node-canvas"&gt;node-canvas github page&lt;/a&gt; for details on installing it on various platforms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let&amp;#8217;s create the test &lt;code&gt;hello-test.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/3046222"&gt;https://gist.github.com/3046222&lt;/a&gt;&lt;/div&gt;

&lt;h3&gt;Run for the first time to generate output&lt;/h3&gt;

&lt;p&gt;First, install &lt;a href="https://github.com/eladb/node-cantest"&gt;node-cantest&lt;/a&gt; globally (might require &lt;code&gt;sudo&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ npm install -g cantest
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now, run it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cantest hello-test.js
[hello-test.js] hello-test.png created
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This test basically &lt;em&gt;failed&lt;/em&gt; (returned exit code &lt;code&gt;1&lt;/code&gt;). It failed because it could not find &lt;code&gt;hello-test.png&lt;/code&gt; which is the default name for an expectation file. Since this is a common use case, &lt;strong&gt;cantest&lt;/strong&gt; simply created this file for you.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s verify that the result is what we wanted. Open &lt;code&gt;hello-test.png&lt;/code&gt; and it should look like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m6mqai6vFO1r17aj7.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;This looks exactly like we expected, so I&amp;#8217;m feeling okay keeping it as the expectation file. In case this is not what you wanted, this is where you iterate on your rendering code and make it look awesome.&lt;/p&gt;

&lt;p&gt;If we run &lt;strong&gt;cantest&lt;/strong&gt; again, the test will succeed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cantest hello-test.js --verbose
[hello-test.js] Test passed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So our project now consists of the following files:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;hello.js&lt;/code&gt; - That&amp;#8217;s our rendering function. All it does is export a &lt;code&gt;function(ctx)&lt;/code&gt; which, when called, draws those nasty looking rectangles on the canvas. You can use &lt;a href="https://github.com/azer/onejs"&gt;onejs&lt;/a&gt; or &lt;a href="https://github.com/substack/node-browserify"&gt;node-browserify&lt;/a&gt; to bundle CommonJS modules for client side consumption so exporting a function for client use makes a lot of sense for us.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hello-test.js&lt;/code&gt; - That&amp;#8217;s the test. Basically, it calls the rendering function, passing in a &lt;a href="https://github.com/learnboost/node-canvas"&gt;node-canvas&lt;/a&gt; &lt;code&gt;CanvasRenderingContext2D&lt;/code&gt; context.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hello-test.png&lt;/code&gt; - That&amp;#8217;s the expectation file. It was conveniently generated by &lt;a href="https://github.com/eladb/node-cantest"&gt;node-cantest&lt;/a&gt; and should be kept alongside &lt;code&gt;hello-test.js&lt;/code&gt; so that &lt;strong&gt;cantest&lt;/strong&gt; can compare the rendering result to it.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The next step will be to make some change in our &lt;code&gt;hello.js&lt;/code&gt; function and rerun the test to make sure we didn&amp;#8217;t break anything:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/3046303"&gt;https://gist.github.com/3046303&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&amp;#8230;and run &lt;strong&gt;cantest&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cantest hello-test.js
[hello-test.js] Test failed. See actual output in .actual.hello-test.png
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Your browser window should pop up and show something like this (&lt;code&gt;--no-browse&lt;/code&gt; will disable this behavior):&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m6mqbgptmv1r17aj7.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Oh, yeah&amp;#8230; Now we can see that the inner blue rectangle changed it&amp;#8217;s height. Obviously this is a stupid example, but you get the point. In more complex rendering systems, there are multiple layers of rendering and if something changes in lower layers you would want to know if it has any affect on higher layers.&lt;/p&gt;

&lt;p&gt;At this point we could:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Decide that this is a good output and overwrite our expectation file by overwriting &lt;code&gt;hello-test.png&lt;/code&gt; with &lt;code&gt;.actual.hello-test.png&lt;/code&gt; (this file is created by &lt;a href="https://github.com/eladb/node-cantest"&gt;node-cantest&lt;/a&gt; and not deleted in case the test fails).&lt;/li&gt;
&lt;li&gt;Figure out that we found a bug and fix it by editing &lt;code&gt;hello.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Some caveats&lt;/h2&gt;

&lt;h3&gt;Static only for now&lt;/h3&gt;

&lt;p&gt;In this initial version &lt;a href="https://github.com/eladb/node-cantest"&gt;node-cantest&lt;/a&gt; is good only for static rendering. It&amp;#8217;s good enough for us for now, but we do understand that we might need to provide some support for changing scenes. This is basically just recording the rendered results and storing it as expectation.&lt;/p&gt;

&lt;h3&gt;Fonts on multiple platforms&lt;/h3&gt;

&lt;p&gt;If you run the tests on multiple platforms (e.g. locally on your Mac and in a build server like &lt;a href="http://travis-ci.org"&gt;travis-ci&lt;/a&gt;, you should be aware that text is rendered differently on different platforms. There&amp;#8217;s a different variety of fonts and the results are not always the same.&lt;/p&gt;

&lt;p&gt;This essentially might cause your tests to break because the resulting PNG will be different from the expectation PNG. To work around this, use common fonts that exist on most platforms (or make sure you are using a single platform to run your tests).&lt;/p&gt;

&lt;h2&gt;Follow up&lt;/h2&gt;

&lt;p&gt;See the &lt;strong&gt;cantest&lt;/strong&gt; &lt;a href="https://github.com/eladb/node-cantest/blob/master/README.md"&gt;README&lt;/a&gt; file for more details on the command line interface and the library API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cantest&lt;/strong&gt; is open source under the MIT license. Contributions/issues/pull requests/feedback/remarks are very welcome and appreciated.&lt;/p&gt;

&lt;hr&gt;&lt;p&gt;Elad Ben-Israel
@emeshbi&lt;/p&gt;</description><link>http://hackingonstuff.net/post/26483937826</link><guid>http://hackingonstuff.net/post/26483937826</guid><pubDate>Wed, 04 Jul 2012 12:46:00 +0300</pubDate></item><item><title>Your Own Little node.js PaaS - Part 1</title><description>&lt;p&gt;PaaS (platform-as-a-service) services are blooming these days (&lt;a href="http://www.heroku.com/"&gt;Heroku&lt;/a&gt;, &lt;a href="http://nodejitsu.com/"&gt;Nodejitsu&lt;/a&gt;, &lt;a href="http://nodester.com/"&gt;nodester&lt;/a&gt;, &lt;a href="https://www.cloudcontrol.com"&gt;cloudcontrol&lt;/a&gt; and &lt;a href="http://mrdanadams.com/2012/node-js-paas-hosting-services/"&gt;many more&lt;/a&gt;). All offer some awesome features. I set out to try and set up a very simple node.js PaaS for myself within an Amazon EC2 Ubuntu instance. It obviously lacks many of the features in commercial PaaS services but it&amp;#8217;s a lot of fun and also gives you complete control over the runtime environment. For me, I needed some non-node Linux services running alongside my app (e.g. SMTP, squid, sshd).&lt;/p&gt;

&lt;p&gt;This post will walk through:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Creating a simple &amp;#8220;hello world&amp;#8221; repository and pushing it into github.&lt;/li&gt;
&lt;li&gt;Launching an EC2 instance and deploying this repository on it.&lt;/li&gt;
&lt;li&gt;Setting up a github post-receive hook to automatically redeploy the &lt;code&gt;#master&lt;/code&gt; branch whenever changes are committed.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;In a future post I will use &lt;a href="https://github.com/eladb/node-connect-girror"&gt;connect-girror&lt;/a&gt; to host multiple apps on a single EC2 instance.&lt;/p&gt;

&lt;p&gt;Some background:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="https://help.ubuntu.com/community/EC2StartersGuide"&gt;Amazon EC2 and Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://learn.github.com/p/intro.html"&gt;git&lt;/a&gt; and &lt;a href="https://help.github.com"&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nodejs.org"&gt;node.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h1&gt;Creating the root repository&lt;/h1&gt;

&lt;p&gt;The first step is to create a git repository that will serve as the root of your PaaS:&lt;/p&gt;

&lt;p&gt;Create a &lt;a href="https://github.com/new"&gt;new github repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m62vcgxKzm1r17aj7.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Clone this repo to your local box:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979066"&gt;https://gist.github.com/2979066&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Create an initial &lt;code&gt;app.js&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2978873"&gt;https://gist.github.com/2978873&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;This is the canonical node.js &amp;#8220;Hello, world&amp;#8221;. Notice that the port we are listening to is defined in &lt;code&gt;process.env.port&lt;/code&gt;. This will be set later in the Ubuntu upstart script that keeps this app alive on the production server. Port 5000 is used as fallback for the development environment.&lt;/p&gt;

&lt;p&gt;Now commit the changes and push them into github:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979049"&gt;https://gist.github.com/2979049&lt;/a&gt;&lt;/div&gt;

&lt;h1&gt;Launch an Amazon EC2 instance&lt;/h1&gt;

&lt;p&gt;The next step is to launch an Amazon EC2 instance. I&amp;#8217;m using Ubuntu here but you could use any other *nix machine. Details will vary, especially around setup and the init scripts (&lt;a href="http://upstart.ubuntu.com/"&gt;upstart&lt;/a&gt; in Ubuntu).&lt;/p&gt;

&lt;p&gt;A list of available stock Ubuntu instances is available &lt;a href="http://cloud-images.ubuntu.com/releases/precise/release/"&gt;here&lt;/a&gt;. I have been successfully using a &lt;a href="https://console.aws.amazon.com/ec2/home?region=eu-west-1#launchAmi=ami-ab9491df"&gt;64-bit ebs-backed instance&lt;/a&gt;. Note that an non-ebs root store might not have enough space for the stuff we need on this box.&lt;/p&gt;

&lt;p&gt;When launching your instance, paste the gist below in the &lt;code&gt;userdata&lt;/code&gt; field of the instance, altering the &lt;code&gt;REPO&lt;/code&gt; variable to point to your newly created github repository.&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2980597"&gt;https://gist.github.com/2980597&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;In case this is a private repository, you can use the &lt;code&gt;https://USER:PASSWORD@github.com/account/repo&lt;/code&gt; scheme, or install a github private key on your server and use the github ssh endpoint (git@github.com/account/repo.git).&lt;/p&gt;

&lt;p&gt;This script basically does the following:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Installs nodejs, npm, git, gnu make and gcc compiler for c++. The latter two are required for compiling native modules in case you will use any.&lt;/li&gt;
&lt;li&gt;Installs &lt;a href="https://github.com/eladb/node-girror"&gt;girror&lt;/a&gt;, which is a node.js module/utility I created that facilitates in syncing clean mirrors of git repositories to a local directory.&lt;/li&gt;
&lt;li&gt;Creates &lt;code&gt;/etc/init/paas.conf&lt;/code&gt; which is an &lt;a href="http://upstart.ubuntu.com/"&gt;Ubuntu upstart&lt;/a&gt; script invoked during system initialization. When &lt;code&gt;start paas&lt;/code&gt; is called (or the system is initialized), this script will fetch any changes from the app&amp;#8217;s git repository, call &lt;code&gt;npm install&lt;/code&gt; (in case there&amp;#8217;s a &lt;code&gt;package.json&lt;/code&gt; file in the app&amp;#8217;s working directory and then start &lt;code&gt;node app.js&lt;/code&gt; from the app&amp;#8217;s directory (setting &lt;code&gt;port&lt;/code&gt; to &lt;code&gt;80&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Starts the &lt;code&gt;paas&lt;/code&gt; service we just created.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m62vdbWkAc1r17aj7.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;In the firewall settings, open up at least port 22 (SSH) and port 80 (HTTP).&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m62vdmwklj1r17aj7.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;After you hit &lt;strong&gt;Launch&lt;/strong&gt;, EC2 will spin up the new instance for you and will run the userdata script you specified. Note that the initial boot might take a few minutes (about 5) since we are installing a few things.&lt;/p&gt;

&lt;p&gt;If everything goes well (see the &lt;strong&gt;System Log&lt;/strong&gt; in the AWS console for debugging), at this point your app should be running and you should be able to hit it via HTTP (replace with your own Amazon instance DNS):&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979054"&gt;https://gist.github.com/2979054&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;How cool is this man?&lt;/p&gt;

&lt;h1&gt;Tailing logs from your server&lt;/h1&gt;

&lt;p&gt;Logs are appended into &lt;code&gt;/var/log/paas.log&lt;/code&gt;, so tailing them should be quite easy:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979056"&gt;https://gist.github.com/2979056&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;I like to keep an open &lt;a href="http://iterm.sourceforge.net/"&gt;iTerm&lt;/a&gt; frame with this command running at all times so I can see what&amp;#8217;s up with my apps.&lt;/p&gt;

&lt;h1&gt;Set up a GitHub hook&lt;/h1&gt;

&lt;p&gt;The next step is to add a hook handler to our app and set up a github post-commit hook which will send an HTTP POST to your instance whenever changes are committed into the master branch.&lt;/p&gt;

&lt;p&gt;Edit your &lt;code&gt;app.js&lt;/code&gt; and add the following code:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2978879"&gt;https://gist.github.com/2978879&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;The mechanism for handling post-commit triggers is simply to exit the app using &lt;code&gt;process.exit(1)&lt;/code&gt;. This will trigger a &lt;code&gt;respawn&lt;/code&gt; by the upstart script which will call &lt;code&gt;girror $REPO $WORKDIR&lt;/code&gt; which will fetch any changes from &lt;code&gt;$REPO&lt;/code&gt;. This is very preliminary and not very sophisticated but actually works&amp;#8230; One thing you would need for a more advanced workflow is only respond to changes within the &lt;code&gt;#master&lt;/code&gt; branch (or any other branch that you wish deployed). This way, you could control exactly which changes affect your production environment.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Security notice&lt;/strong&gt;: since the root app contains the super secret deployment endpoint, you should probably make it a private repository and not public.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Commit and push the changes to github:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979574"&gt;https://gist.github.com/2979574&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Now, you will need to redeploy your app manually by invoking upstart&amp;#8217;s &lt;code&gt;restart&lt;/code&gt; command. You can do this remotely using ssh:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979059"&gt;https://gist.github.com/2979059&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;In the logs, you should see something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Starting app from &lt;a href="https://github.com/eladb/mylittlepaas"&gt;https://github.com/eladb/mylittlepaas&lt;/a&gt;
16:26:27 - TRACE - done
My little PaaS (v2) started on port 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Did you notice &lt;code&gt;v2&lt;/code&gt;? Yeah!!&lt;/p&gt;

&lt;p&gt;The next step is to setup a github &lt;a href="https://help.github.com/articles/post-receive-hooks"&gt;post receive hook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In your repository&amp;#8217;s administration page, under &lt;strong&gt;Service Hooks&lt;/strong&gt; (!https://github.com/&lt;em&gt;account&lt;/em&gt;/&lt;em&gt;repo&lt;/em&gt;/admin/hooks), add a &lt;strong&gt;WebHook URL&lt;/strong&gt; that points to your secret deployment endpoint. In our case it is &lt;a href="http://ec2xxx.compute.amazonaws.com/mysupersecretdeploymentendpoint:"&gt;http://ec2xxx.compute.amazonaws.com/mysupersecretdeploymentendpoint:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_m62wiu2HDi1r17aj7.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Update Settings&lt;/strong&gt; and then &lt;strong&gt;Test Hook&lt;/strong&gt; while monitoring your tailed logs. You should see deployment activity going:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Post-receive trigger. Exiting in 1 second
Starting app from &lt;a href="https://github.com/eladb/mylittlepaas"&gt;https://github.com/eladb/mylittlepaas&lt;/a&gt;
16:53:14 - TRACE - done
My little PaaS (v2) started on port 80
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we are getting somewhere&amp;#8230;&lt;/p&gt;

&lt;p&gt;If you &lt;code&gt;GET /&lt;/code&gt;, you will see the new version deployed:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979060"&gt;https://gist.github.com/2979060&lt;/a&gt;&lt;/div&gt;

&lt;h1&gt;Installing npm packages&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;paas.conf&lt;/code&gt; upstart script executes &lt;code&gt;npm install&lt;/code&gt; before starting your app. This means that any npm packages you specify under the &lt;code&gt;dependencies&lt;/code&gt; field of your app&amp;#8217;s &lt;code&gt;package.json&lt;/code&gt; file will be installed automatically before the app starts. One disadvantage of this approach is that sometimes modules use wildcard semver versioning when specifying dependencies, which can potentially cause app breakage if some module misbehaved and did not adhere to npm&amp;#8217;s versioning guidelines. npm provides a mechanism called &lt;a href="http://npmjs.org/doc/shrinkwrap.html"&gt;shrinkwrapping&lt;/a&gt; which allows you to fix the versions of all the modules and submodules you are using. This is the best practice for bundling app dependencies.&lt;/p&gt;

&lt;p&gt;Another approach is to commit all dependent modules directly into your repository&amp;#8217;s &lt;code&gt;node_modules&lt;/code&gt; directory. This will work only if you are not using modules with native parts which must be compiled on the target architecture.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s install the &lt;a href="https://github.com/Marak/asciimo"&gt;asciimo&lt;/a&gt; module and emit some ascii art.&lt;/p&gt;

&lt;p&gt;Edit your app&amp;#8217;s &lt;code&gt;package.json&lt;/code&gt; and add &lt;code&gt;asciimo@0.3.1&lt;/code&gt; under the &lt;code&gt;dependencies&lt;/code&gt; field:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2979605"&gt;https://gist.github.com/2979605&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Now, install and shrinkwrap:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2980212"&gt;https://gist.github.com/2980212&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Edit &lt;code&gt;app.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2980218"&gt;https://gist.github.com/2980218&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Commit and push:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2980228"&gt;https://gist.github.com/2980228&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Code should be now be deployed automatically (and npm installed), so &lt;code&gt;GET /&lt;/code&gt; should yield:&lt;/p&gt;

&lt;div class="gist"&gt;&lt;a href="https://gist.github.com/2980244"&gt;https://gist.github.com/2980244&lt;/a&gt;&lt;/div&gt;

&lt;h1&gt;Recap&lt;/h1&gt;

&lt;p&gt;So, at this point we have:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;A running ec2 instance hosting the node.js app under a github hosted repository.&lt;/li&gt;
&lt;li&gt;Any changes to the master branch of this repository will be automatically fetched and the app will be restarted.&lt;/li&gt;
&lt;li&gt;Logs can be tailed via ssh using &lt;code&gt;tail -f /var/log/paas.log&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;In the next post I will extend this app to host apps from multiple repositories using &lt;a href="https://github.com/eladb/node-connect-girror"&gt;connect-girror&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Any comments/feedback/ideas/contributions/flaming are very welcome!&lt;/p&gt;</description><link>http://hackingonstuff.net/post/25741331955</link><guid>http://hackingonstuff.net/post/25741331955</guid><pubDate>Sun, 24 Jun 2012 01:33:00 +0300</pubDate><category>node.js</category><category>paas</category><category>amazon</category><category>ec2</category><category>apps</category><category>deployment</category><category>github</category><category>girror</category><category>connect-girror</category></item><item><title>Setting up a squid proxy on AWS</title><description>&lt;h4&gt;1. Launch a micro &lt;a href="https://console.aws.amazon.com/ec2/home?region=us-east-1#launchAmi=ami-4dad7424"&gt;Ubuntu EC2 instance&lt;/a&gt;&lt;/h4&gt;

&lt;p&gt;If you don&amp;#8217;t have an Amazon AWS account, you can sign up for one &lt;a href="http://aws.amazon.com"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;2. SSH into your new instance and install squid&lt;/h4&gt;

&lt;pre&gt;&lt;code&gt;$ sudo apt-get update
$ sudo apt-get install squid3
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;3. Update squid configuration&lt;/h4&gt;

&lt;p&gt;Edit &lt;code&gt;/etc/squid3/squid.conf&lt;/code&gt; as root:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo nano /etc/squid3/squid.conf
acl all src all
acl SSL_ports port 443
acl CONNECT method CONNECT
http_access allow all
http_port 3128
hierarchy_stoplist cgi-bin ?
coredump_dir /var/spool/squid3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Please note that this configuration is not very secure. See &lt;a href="http://wiki.squid-cache.org/ConfigExamples"&gt;squid configuration wiki&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;Restart squid for configuration to be reloaded:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ sudo restart squid
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;4. Add inbound port 3128 to the instance security group&lt;/h4&gt;

&lt;p&gt;Instances are usually launched on the default security group (unless you specify otherwise).&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Access the &lt;a href="https://console.aws.amazon.com/ec2/home?region=us-east-1&amp;amp;#s=SecurityGroups"&gt;security groups&lt;/a&gt; section in the EC2 console&lt;/li&gt;
&lt;li&gt;Add a custom TCP inbound rule for port 3128 and apply the change.&lt;/li&gt;
&lt;/ol&gt;&lt;h4&gt;5. Configure your browser to use the proxy server&lt;/h4&gt;

&lt;p&gt;Depending on your OS/browser, you should configure the system to access the Internet via the proxy for both HTTP and HTTPS (e.g. &lt;strong&gt;ec1-11-11-11-11.compute-2.amazonaws.com:3128&lt;/strong&gt;).&lt;/p&gt;</description><link>http://hackingonstuff.net/post/23929749838</link><guid>http://hackingonstuff.net/post/23929749838</guid><pubDate>Mon, 28 May 2012 17:42:00 +0300</pubDate><category>proxy</category><category>ec2</category><category>amazon</category><category>aws</category><category>squid</category><category>squid3</category><category>http-proxy</category></item></channel></rss>
