Amazon Web Services SDK (abstraction over the AWS API) is a powerful and convenient tool which allows developers to automate any AWS operation (provisioning of new resources, managing them and build-out of cloud infrastructures) in a programming language which is already familiar to you: Java, Python, Go, and many other including Node.js of course!

The goal of this tutorial is to teach you basics of AWS SDK by configuring access to the AWS API and running a few EC2 operations. In this tutorial, I will teach you how to write a Node script to create an instance with Node hello world (use User Data), and run it. Make sure you see the Hello World via public DNS. By the end, you’ll know how to get started with AWS Node SDK.

The tutorial is broken down in the following steps:

  1. Set up your credentials
  2. Create user data
  3. Create Node script
  4. Run EC2, tag it
  5. Test and terminate

Next we will go over all the commands, code and settings, to implement the task of running the AWS EC2 with the use of the Node script and AWS SDK Node module.

1. Set up your credentials

Copy access ID and secret key from AWS Console. Paste them in config.json:

{
  "accessKeyId": "your access key",
  "secretAccessKey": "your secret access key",
  "region": "us-west-1"
}

2. Create user data

Create a user data shell script which will install Node v6 on the EC2 instance, copy the Hello World code to the EC2 instance and start the HTTP web server right after the launch. This is called User Data. EC2 will run this script on the instance launch (but not on the reboot).

You might use this code as an inspiration (code/sdk/user-data.sh):

#!/bin/bash -ex
# user data to install node, download hello world server code and stat the app
# output user data logs into a separate place for debugging
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
# get node into yum
curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
# install node (and npm) with yum
yum -y install nodejs
# install pm2 to restart node app
npm i -g [email protected]
# get source code for hello world node server from GitHub's gist (could be private GitHub repo or private S3)
curl "https://gist.githubusercontent.com/azat-co/41b7abc276eb0a773696c3c8d757e87e/raw/5cea0aee743a8a5a0270b09ab5f8d168848be6ec/hello-world-server-port.js" > /home/ec2-user/hello-world-server.js
sudo chmod 755 /home/ec2-user/hello-world-server.js # optional
# restart pm2 and thus node app on reboot
echo "PORT=80">>/etc/environment
crontab -l | { cat; echo "@reboot sudo pm2 start /home/ec2-user/hello-world-server.js -i 0 --name \"node-app\""; } | crontab -
# start the server
sudo pm2 start /home/ec2-user/hello-world-server.js -i 0 --name "node-app"

The code above is pulling source code for the HTTP web server from GitHub’s gist (azat-co profile). If you are curious, here’s the Node server code (code/sdk/hello-world-server-port.js):

const port = process.env.PORT || 3000
require('http')
  .createServer((req, res) => {
    console.log('url:', req.url)
    res.end('hello world')
  })
  .listen(port, (error)=>{
    console.log(`server is running on ${port}`)
  })

It’s a great idea to test your HTTP server locally on your developer machine. You can easily do it by running:

node hello-world-server-port.js

Or if you want to specify a different port instead of 3000, then you can do so with the PORT environment variable. For example, to use 80 use this:

sudo PORT=80 node hello-world-server-port.js

Depending on the port number, you can test the response from the HTTP web server with the URLs like http://localhost:3000 or http://localhost for 3000 and 80 correspondingly.

3. Create Node script

You can use Node as a scripting language to automate any AWS task. You can add parameters to your scripts to make them flexible (region, instance type, source code, etc.).

Create a project manifest file by running in a brand new folder:

mkdir provision-infra
cd provision-infra
npm init -y

Install AWS Node/JavaScript SKD:

npm i -SE aws-sdk

For this lab, your goal is to launch an instance with automatic environment and app setup in user data. Feel free to add more to this example (security group, key pair, etc.). List of the Node SDK API is here. It closely follows and mimics the AWS CLI commands. My example is this (code/sdk/provision-infra.js)

// Load the SDK for JavaScript
const AWS = require('aws-sdk')
// Load credentials and set region from JSON file
// AWS.config.loadFromPath('./config.json')

// Create EC2 service object
var ec2 = new AWS.EC2({apiVersion: '2016-11-15', region: 'us-west-1'})
const fs = require('fs')
var params = {
  ImageId: 'ami-9e247efe', // us-west-1 Amazon Linux AMI 2017.03.0 (HVM), SSD Volume Type
  InstanceType: 't2.micro',
  MinCount: 1,
  MaxCount: 1,
  UserData: fs.readFileSync('./user-data.sh', 'base64'),
  GroupIds: ['SECURITY_GROUP_ID']
}

// Create the instance
ec2.runInstances(params, function(err, data) {
   if (err) {
      console.log('Could not create instance', err)
      return
   }
   var instanceId = data.Instances[0].InstanceId
   console.log('Created instance', instanceId)
   // Add tags to the instance
   params = {Resources: [instanceId], Tags: [
      {
         Key: 'Role',
         Value: 'aws-course'
      }
   ]}
   ec2.createTags(params, function(err) {
      console.log('Tagging instance', err ? 'failure' : 'success')
   })
})

Imagine a scenario in which you can pass a link to the source code separately from the user data. In other words, our Node and user data scripts can be used without modifications for future deployments of the new versions of the app Node Hello World… or a fully-functional REST API? It’s up to you. The EC2 environment is good for production. :-)

4. Launch EC2

The way you launch a Node script is with the node {filename.js} command. For example,

cd code/sdk
node provision-infra.js

Note: You must have user-data.sh in the same folder as your Node script or change the path to the user-data.sh in provision-infra.js. Notice the instance ID. My output was:

Created instance i-04dd20a0983596f9c
Tagging instance success

5. Test and terminate

Wait a few moments (anywhere from 30seconds to 1–2 minutes) and get the public URL (DNS name) using the instance ID from step 4. (See lab 1 for how to do it; hint: describe-instances.)

Open the public URL in the browser and observe hello world.

Reboot your instance using reboot-instances and instance ID. For example,

aws ec2 reboot-instances --instance-ids i-04dd20a0983596f9c

Terminate your instance using its ID.

Troubleshooting

  • The instance is running but I don’t see Hello World: Make sure you are looking at the same port (80 or 3000 or some other value) as you have in your environment variable and/or Node server source code
  • I still don’t see anything: Make sure your security group and network (some corporate networks block non-standard ports like 3000) are open. You might have to create a new security group and/or go on a guest network without corporate proxy.

Wrap-up

For more AWS tutorials, there are other posts in this series on Amazon Web Services:

Lastly, make sure to checkout some free preview lectures of NodeU courses: