This post describes the steps necessary to install Node.js and the Ghost publishing platform on Windows Server IIS. Ghost is a Node.js web application, specifically for blogging. To run Node.js applications in IIS, you need the iisnode module. Here is how to install all of this.
Install Node.js and iisnode on the web server, add an iisnode handler, a URL Rewrite rule and an <iisnode> section to your web.config, and let your Node.js app listen on process.env.PORT. Most errors come down to NTFS permissions: node.exe needs read access starting from the root of the drive.
I originally wrote this post in 2014 for Node.js v0.10, iisnode 0.2.7 and Ghost 0.4.1. All of these versions are long outdated, and the Ghost configuration (config.js, core\index.js) works differently in current Ghost releases. Use this post as background on how iisnode hosts Node.js applications in IIS, not as a current installation guide.
Ghost and Node.js on Windows IIS
Ghost is a simple, powerful publishing platform, developed in Node.js. Node.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
After reading Scott Hanselman's post about installing and running node.js applications within IIS on Windows, I wanted to run Ghost on IIS. Tomasz Janczuk developed the iisnode module to run Node.js on IIS, so this should work for Ghost too... Guess we need to install iisnode in IIS then 🙂
Step 1: get and install Node.js, iisnode and Ghost
First you need all the software:
- Grab a copy of
node-v0.10.26.x86.msi(ornode-v0.10.26.x64.msi) - Grab a copy of
iisnode-full-iis7-v0.2.7-x86.msi(oriisnode-full-iis7-v0.2.7-x64.msi); choose the right flavor for your architecture - Grab a copy of
ghost-0.4.1.zipfrom ghost.org - Install the software on your IIS web server and verify iisnode is registered as a module.
- Unzip
ghost-0.4.1.zipand place it in your webroot. Be aware that Ghost cannot be installed in a subdirectory called 'ghost'.
Step 2: set up and configure iisnode and Ghost rewrites
Create a web.config file to configure iisnode. It needs to contain a handler for iisnode:
<handlers>
<add name="iisnode"
path="index.js"
verb="*"
modules="iisnode"
/>
</handlers>
Add a URL Rewrite Module rewrite rule for Ghost in your web.config:
<rewrite>
<rules>
<rule name="Ghost">
<match url="/*" />
<conditions>
<add input="{PATH_INFO}" pattern=".+\.js\/debug\/?" negate="true" />
</conditions>
<action type="Rewrite" url="index.js" />
</rule>
</rules>
</rewrite>
This rule requires the IIS URL Rewrite Module. Here is how to install IIS URL Rewrite Module on Windows Server.
In the web.config file, you need to configure iisnode too:
<iisnode node_env="%node_env%"
loggingEnabled="true"
debuggingEnabled="true"
devErrorsEnabled="true"
nodeProcessCommandLine="c:\path\to\node.exe"
/>
Depending on your web server security and configuration, you might need to add or tweak NTFS file permissions. The node.exe process needs some read permissions starting from the partition drive (C:, D:, or E: for example).
Step 3: set up and configure Ghost
Important: you need to configure Ghost locally on your development machine.
- Copy
config.example.jstoconfig.js - Edit your production environment:
url: 'http://www.example.com',
host: 'http://www.example.com',
port: process.env.PORT // this one is important!
- Edit
core\index.jsfor production:
// process.env.NODE_ENV = process.env.NODE_ENV || 'development';
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
- Make sure files and folders are writeable
- Install the necessary Node.js modules for production; run from within your Ghost directory:
npm install --production - Dry run: run
node.exe index.jsfrom within your Ghost directory, and fix any errors that may occur.
Now everything should run fine when you upload Ghost to your webroot. The log files iisnode creates are placed in $webroot/iisnode/*.txt.
Troubleshooting Node.js, iisnode and Ghost errors
Incorrectly configured file permissions: how to fix Application has thrown an uncaught exception and is terminated.
As stated earlier in this article, the node.exe process requires read permissions starting from the partition drive for the IUSR user, or the group under which the website and application run. The special permissions needed are Traverse folder / execute file, List folder / read data and Read attributes. This may be a security concern. If file permissions are set up wrong, you can expect the following exception:
Application has thrown an uncaught exception and is terminated:
Error: EPERM, operation not permitted 'd:\'
at Object.fs.lstatSync (fs.js:679:18)
at start (fs.js:1240:10)
at Object.realpathSync (fs.js:1228:3)
at tryFile (module.js:142:15)
at Function.Module._findPath (module.js:181:18)
at Function.Module._resolveFilename (module.js:336:25)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (C:\Program Files (x86)\iisnode\interceptor.js:210:1)
Correcting the file permissions resolves this error.
Node.js Hello World example
A small hello world Node.js application comes in handy to debug Node.js or iisnode configuration issues. Here's one:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello, world!');
}).listen(process.env.PORT);
console.log("Node.js running!");
Important to note is the .listen(process.env.PORT) line: using iisnode, you cannot let your Node.js app listen on a TCP port of your own choice. IIS serves the default HTTP and HTTPS ports (80 and 443) and iisnode passes requests to your app through the address in process.env.PORT.
Errors during WordPress JSON import into Ghost
WordPress export to Ghost: errors will happen.
Are you trying to import WordPress content into Ghost and is that giving you a hard time? See my post on how to export and migrate WordPress to Ghost for a solution to the HTTP 500 Internal Server Error:
A problem was encountered while importing new content to your blog. Error: unknown
One thing you must not forget is that IIS acts as a reverse proxy, utilizing the iisnode module, for Node.js web applications like Ghost. You may find out the "hard" way, for example when you get too many redirect errors after setting up an SSL certificate.
Once Ghost runs, you probably want it to send email too: send email with Ghost using SMTP authentication and TLS encryption.