Hosting meteor.js app in IIS

Posted on 10 Comments

meteorjsMaking reactive and real-time web applications is in fashion these days. Among popular real-time programming frameworks are meteor.js, knockout.js and signalr. Both Knockout and SignalR are developed by Microsoft employees, and integrate seamlessly with Microsoft products. Meteor, on the other hand, is though based on the cross-platform node.js, it is more Linux / Mac-centric than it is Windows. In fact, Meteor’s official documentation is also designed with instructions that pertain to Linux. They don’t even have an official Windows installer for their framework, but depend on a certain Tom Wijsman for that.

It’s true that Linux/Apache is still the dominant server stack, but we still have thousands of corporations that rely on Microsoft’s Windows servers and IIS. And deploying a meteor app on a Windows server is a real pain in the butt because the ever so elegant command meteor bundle doesn’t work in Windows. Last I heard from Tom, implementation of meteor bundle in Windows was in the works. But meteor-win won’t support it until at least v0.5.1.

Although there are workarounds like using a Vagrant VM or msysgit for deploying meteor apps on Windows servers, as I found out through my forum thread, all these workarounds are either too cumbersome or don’t work in all cases. During my constant searching on ways to deploy my meteor app on Windows, I stumbled upon an excellent utility called iisnode, which does that in the best and most elegant way possible.

iisnode is basically meant to host node.js applications is IIS, but again as meteor apps themselves are node.js apps only, using iisnode to host them just works. But some setup and configuration is required before your app is fully hosted.

Prepare your meteor app for deployment
First, create & run a meteor app in Windows (don’t forget to run it in production mode — use the command meteor --production — to make sure static_cacheable folder is produced along; this is the folder that contains compressed & combined CSS and JS files). This will generate the folder “.meteor\local\build” inside your app’s root folder. This is the folder whose contents we actually deploy on server. Edit the file “.meteor\local\build\server\server.js” (toward the end of file).

replace:

app.listen(port, function() {
    if (argv.keepalive)
        console.log("LISTENING"); // must match run.js
});

with:

app.listen(process.env.PORT);

This is to ensure you are using the overloaded version of listen method that accepts named pipes as ports to listen for HTTP requests. Behind the scenes, iisnode achieves integration of IIS with a node.js app’s webserver by redirecting traffic received on IIS’s port (usually 80) to a randomly generated named-pipe port of node’s webserver, and vice-versa.

Next, create a zip of the build folder making sure all the sub-folders of “server\node_modules” get copied into it. Let’s name the zip as bundle.zip. Now your app’s deployment package is ready.

Set up node and mongodb
Download and install the right node.js version for your server.
Download and install the right MongoDB version for your server.

Now your server is set to run node.js applications that rely on mongodb for data, as is the case with meteor.

Configure environment variables
meteor apps depend on two crucial environment variables — ROOT_URL and MONGO_URL. Access the System Properties dialog, go to the Advanced tab, and click on Environment Variables button. In the System Variables section, add two new variables similar to the following. In most cases, MONGO_URL won’t change.

ROOT_URL=http://yoursite.com
MONGO_URL=mongodb://localhost

Set up iisnode
Get an appropriate iisnode installer for your IIS from github, and install it normally on your server. This will add a handler and module named iisnode in IIS that will handle the serving of your node.js applications. If required, restart IIS — execute iisreset in Command Prompt.

You can test if iisnode is alive and kicking by setting up samples (that get installed alongside iisnode) — from the administrative command prompt call %programfiles%\iisnode\setupsamples.bat, and then go to http://localhost/node.

Setup URL Rewrite
If not already installed, setup URL Rewrite IIS module right away. You’ll be needing this for rewriting all your meteor app’s traffic to its main.js.

Host your meteor app
It’s time now! Unzip your deployment package bundle.zip to a desired location on server. Next, set the virtual directory location of your Default Web Site in IIS to point to your unzipped app folder.

Now, in the root of your app, create a web.config.

<configuration>
  <system.webServer>
    <rewrite>
      <rules configSource="rewrite.config" />
    </rewrite>
    <!-- indicates that the main.js file is a node.js application 
    to be handled by the iisnode module -->
    <handlers>
      <add name="iisnode" path="main.js" verb="*" modules="iisnode" />
    </handlers>
        <defaultDocument>
            <files>
                <add value="main.js" />
            </files>
        </defaultDocument>
  </system.webServer>
</configuration>

Finally, create Rewrite.config with the following rewrite rules.

<rules>
	<rule name="Rewrite to combined CSS file">
		<match url="^([A-Za-z0-9]+.css)" />
		<action type="Rewrite" url="static_cacheable/{R:1}" />
	</rule>
	<rule name="Rewrite to combined JS file">
		<match url="^([A-Za-z0-9]+.js)" />
		<action type="Rewrite" url="static_cacheable/{R:1}" />
	</rule>
	<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
		 <match url="iisnode" />
	</rule>
	<!-- iisnode debugging support -->
	<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">                    
		<match url="^main.js\/debug[\/]?" />
	</rule>
	<!-- A meteor app's public folder generally contains images -->
	<rule name="StaticContent">
		 <action type="Rewrite" url="public{{REQUEST_URI}}" />
	</rule>
	<rule name="DynamicContent">
		 <conditions>
			  <add input="{{REQUEST_FILENAME}}" matchType="IsFile" negate="True" />
		 </conditions>
		 <action type="Rewrite" url="main.js" />
	</rule>
</rules>

Optionally, put a iisnode.yml file in the root of your app folder.

Access your meteor app in browser
Go to http://yoursite.com/ and enjoy the view!

10 thoughts on “Hosting meteor.js app in IIS

  1. v0.5.2 of meteor win is out, but meteor bundle still isn’t supported. So iisnode is still the only reliable way out.

  2. Never place too much reliance upon what a party says when it isn’t in power, they flip flop around even more than the party in government.

  3. Nice Anurag!!!!

  4. @Chip:
    Thanks. Are you, by chance, building a real-time app?

  5. Please update it to Meteor 1.0

  6. This is outdated and no longer true. There is no “.meteor\local\build\server\server.js”

  7. Any update on this for Meteor 1.0? I’ve got a meteor app that is working on Windows Server 2008 R2, but it will not work with iisnode. The ETW trace complains about named pipes, and I’m not sure what to use for Rewrite rules.

  8. @Eric – I haven’t yet had the chance to work on meteor 1.0 yet. As for rewrite rules, perhaps you can check iisnode’s source on github for the latest rules.

  9. Hi Anurag, I cannot find file: server.js inside .meteor\local\build\server directory. Do you know any up-to-date guide that show about hosting meteor.js in IIS ? How can I contact you if I still have some questions to ask?

  10. @Marvin – I’ve not worked on the latest versions of Meteor. But I have no doubt that server.js is still getting generated somewhere as it’s the node’s starting point. Perhaps the build directory has changed from .meteor\local\build to something else.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.