from heroku to google’s cloud compute engine

Creating a GCE Nginx and node.js server


I’ve spent what felt like a lifetime on the business side of things. So much so that when I recently came back into tech and started playing around with Heroku, it literally blew my mind away. It’s hard to believe that just an eye blink ago, deploying a web application meant compiling my own Gentoo server and painfully configuring each and one my stack components to work together. Now, with a simple git push, I can be fully live on Heroku. Simply amazing.

But alas, Heroku and its peers have one problem: HIPAA compliance. Or lack there of.

why i need google’s cloud compute engine

Having HIPAA compliance is a requirement for many healthcare companies. After a long search and weighing between many options (#article to come), google cloud emerged as the best option for my needs.

Regrettably, google cloud provides HIPAA compliance only for:

  • Compute Engine
  • Cloud Storage
  • Cloud Datastore
  • Cloud SQL

No App Engine support (and no node.js via App Engine anyways).

So it looks like building servers back in the “good o’e days” might come in handy after all.

Reminder: there are many components to HIPAA compliance, of which I will not cover any here in detail. And there’s a lot more to compliance than simply using google cloud or adding SSL.


back to basics…

With needing to deploy a node.js server/application, my only option is to utilize Google Compute Engine (gce).

1. setting up a google cloud account

There are many tutorials on how to create and configure your google cloud account / compute engine. I won’t go into those specifics.

For this tutorial, you’ll need:

  • An active google compute engine (gce) instance running on Debian 7 Wheezy / backports-Wheezy (I’m using debian-7-wheezy-v20140415)
  • Locally installed google cloud (cli) sdk

2. installing node.js

Vanilla gce instances require us to install our own packages.

To install node.js and npm: (using v0.10.28 as example below)

gce-vm$ wget -O nodejs.tar.gz http://nodejs.org/dist/v0.10.28/node-v0.10.28-linux-x64.tar.gz
gce-vm$ tar -xzf nodejs.tar.gz
gce-vm$ sudo cp node-v0.10.28-linux-x64/bin/* /usr/local/bin/
gce-vm$ sudo cp -r node-v0.10.28-linux-x64/lib/* /usr/local/lib/
gce-vm$ sudo mkdir -p /usr/local/share/man/man1
gce-vm$ sudo cp -r node-v0.10.28-linux-x64/share/man/man1/node.1 /usr/local/share/man/man1
gce-vm$ curl https://www.npmjs.org/install.sh | sudo sh

3. installing nginx

There are many discussions on nginx with a reverse proxy in front of node.js. I won’t go into this topic here but may explore this in #future posts where I’ll discuss topics like improving nginx configuration and using google cloud load balancer.

Installing nginx is a bit tricky since the default Debian 7 Wheezy source list does not provide this package.

You’ll need to manually add nginx package locations to the deb source list using nano:

gce-vm$ sudo nano /etc/apt/sources.list

Add the following sources below the existing lists, and save.

deb http://nginx.org/packages/mainline/debian/ wheezy nginx
deb-src http://nginx.org/packages/mainline/debian/ wheezy nginx
adding new deb source lists for nginx

Since this is a new source list, you’ll need to add the nginx.org signing key.

gce-vm$ wget http://nginx.org/keys/nginx_signing.key
gce-vm$ sudo apt-key add nginx_signing.key

Finally, update your apt-get and install nginx:

gce-vm$ sudo apt-get update
gce-vm$ sudo apt-get install nginx

nginx should be installed successfully and started running on port:80. (But you may not be able to access it yet until you configure the firewall — see below.)

4. configuring the firewall

If you haven’t already added firewall rules to your google cloud project, you need to add tcp:http (port 80) and tcp:https (port 443) rules so visitors can access your server.

You can do so by using the following gcutil commands or by add directly using the google web UI.

If using gctuil, enable http and https using the following commands on your own machine. In a new terminal window:

your-machine$ gcutil —project=yourcloudproject addfirewall allow-http —description=”All http allowed.” —allowed=”tcp:http” 
your-machine$ gcutil —project=yourcloudproject addfirewall allow-https —description=”All https allowed.” —allowed=”tcp:https” 

5. testing your setup

Test out if your gce instance (nginx) is working properly by opening a browser and navigating to your gce’s external IP address.

beautiful! server works!

Success!

I recommend taking a snapshot of your gce instance now if you don’t need anything more complicated. This way it saves time when replicating into new instances.


advanced setup

Now the real fun begins.

6. setting up nginx as a reverse proxy to node.js

I believe one of the best way to serve out my node.js solution is to use nginx as a front end server. nginx can act a reverse proxy servicing all http(s) requests while node.js sits behind it and only responds to required requests. I like this setup and it’s also fairly simple to setup.

We’ll need to edit nginx site configuration files. You can either start a new file or edit the default.conf. For simplicity sake let’s edit directly in default.conf.

gce-vm$ cd /etc/nginx/conf.d/
gce-vm$ sudo nano default.conf

Assuming you anticipate your node.js server to run on port 3000, edit the location / {} to the following and save:

location / {
proxy_pass http://localhost:3000; #change port to your node.js port
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
changing nginx server configs

Reload your nginx server with these new configurations:

gce-vm$ sudo /etc/init.d/nginx restart

Now try to navigate to your site. It should error out because — duh — there’s no node.js server running yet.

No problem! This is expected right now.

7. getting your node.js server/application up and running

Now that nginx is configured correctly, you’ll need to get your node.js server running. There are many tutorials on best node.js server practices in a production environment, but I’m going to skip a lot of that for now.

I’ll assume you’re hosting your code on github or similar repository. Begin by installing git into your gce instance:

gce-vm$ sudo apt-get install git

and clone your repository to your directory:

gce-vm$ cd ~
gce-vm$ git clone https://github.com/your_repo.git

Assuming you’re using node.js with express.js v4+, simply make sure your node modules are ready and launch your server like you normally would:

gce-vm$ cd your_repo/
gce-vm$ npm install
gce-vm$ npm start

Now point your browser again to your external ip address, and viola! You should see your gce console output successful http requests.

It works!

Congratulations. A successful nginx reverse proxy to node.js server.

8. setting up SSL

Finally, it wouldn’t be a HIPAA compliant solution if there wasn’t SSL. Thankfully, by having nginx as a proxy, it provides an easy way to encrypt your node.js server traffic.

Let nginx do all the SSL work seamlessly☺

To start, you’ll need SSL certificate and key from a signing authority (i.e. RapidSSL, Comodo, GoDaddy, etc.) Alternatively you can setup your own via OpenSSL, but I won’t be covering that here.

Move your certificate and key files to a directory of your choice — I prefer /etc/nginx/keys/

productionSSLcertificate.crt
productionSSLkey.key

Go ahead and edit the nginx server configuration:

gce-vm$ sudo nano /etc/nginx/conf.d/default.conf

Add / modify with the following with SSL options:

server{ 
listen 80;
listen 443 ssl;
server_name localhost;
 ssl_certificate /etc/nginx/keys/productionSSLcertificate.crt;
ssl_certificate_key /etc/nginx/keys/productionSSLkey.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;

.....
location / {
....
}
}
SSL enabled nginx configuration

Save and restart your nginx server.

gce-vm$ sudo /etc/init.d/nginx restart

Navigate to https://YourServerIP. And just like that, SSL is now enabled for your nginx / node.js server.

Secured SSL site

There’s a lot more to configuring a more production ready server including using tools like pm2 to manage your node.js server, creating a better nginx proxy through enabling load balancing, gzip compression, etc. I may explore these and document them here on this blog in the #future.

Meanwhile, that’s it for now. Good luck and hopefully these steps have provided you with good guidance on how to do it within your own google cloud environment.