Deploying Node.js Applications with Ansible

Ansible is a devops IT automation tool similar to Chef and Puppet that can be used to automate your IT infrastructure. The following content outlines a Node.js deployment strategy using Ansible. The strategy performs the following :

  • Prepares the application environment
  • Pulls the applications from a Private Github repo
  • Installs the applications dependencies
  • Daemonizes the application

Installing Ansible

Before we even get started, make sure you have Ansible installed on your local machine along with the Ansible inventory file and the group_var directory.

Ubuntu :

sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible

Mac ox :

brew install ansible

We are going to need some configuration files and directories.

mkdir -p /usr/local/etc/ansible/group_vars
touch /usr/local/etc/ansible/hosts

hosts Directory

The hosts file should contain your Ansible inventory.

group_vars Directory

The group_vars directory should contain your Ansible Playbook variables.

Configuring Inventory

Ansible Inventory is basically a list of IP addresses that point to your applications servers. In our case, it is the public IP address of our application EC2 instance. You can learn more about Ansible Inventory here. To add inventory to Ansible, add the following to the hosts file that was created earlier :

inv1 ansible_ssh_host=

Create a app.yml variable file in /usr/local/etc/ansible/group_vars directory and insert the following :

ansible_ssh_user: ubuntu

Sanity Test

Lets run a sanity test to make sure everything we have done so far is working. Run the following in your local machine.
ansible -m ping all -vvv. If Ansible has connected to the remote machine successfully, you should see a blob of green JSON text. If you see a blob of red JSON text, you might have an error that you are going to have to investigate.

Create A Playbook

Ansible uses the concept of Playbooks. Playbooks contain instruction that get executed during the deployment process. Playbooks are to Ansible like Recipes are to Chef. You may want to learn more about Ansible Playbooks here.

Create a new yaml file in your application directory and name it app.yml. Add the following to the app.yml (Dont forget to change the variables and paths to your own):

- hosts: my_app
  sudo: yes

    - homeDir: /home/ubuntu
    - appDir : app
    - repo: my_app
    - account: mbejda
    - privateKey: /Users/milos/.ssh/id_rsa

  - name: Install Packages
    apt: name={{ item }} update_cache=yes state=latest
      - build-essential
      - npm
      - nodejs-legacy
      - git
      - mcrypt
      - nginx
      - curl

  - name: Install pm2
    npm: name=pm2 global=yes production=yes

  - name: Create APP Directory
    file: path={{homeDir}}/{{appDir}} state=directory

  - name: Copy Private Key
    copy: src={{privateKey}} dest={{homeDir}} mode=0600

  - name: Git Clone Repo
    git:{{account}}/{{repo}}.git dest={{homeDir}}/{{appDir}} update=yes force=yes accept_hostkey=yes key_file={{homeDir}}/id_rsa
    register: git_finished

  - name: Running NPM install
    npm: path={{homeDir}}/{{appDir}}/backened
    register: npm_finished
    when: git_finished.changed

  - name: Stop APP
    sudo_user: ubuntu
    command: pm2 stop app chdir={{homeDir}}/{{appDir}}/backened
    ignore_errors: yes

  - name: Start APP
    sudo_user: ubuntu
    command: pm2 start index.js --name app chdir={{homeDir}}/{{appDir}}/backened
    ignore_errors: yes
    when: npm_finished.changed


Install Packages

Installs the necessary dependencies that are required to run the application.

Install pm2

PM2 is the daemon tool that is used to keep the application running.

Create APP Directory

Creates the root app directory.

Copy Private Key

Copies our local private key to the app directory. This is important so we can pull the application from Github in the next step.

Git Clone Repo

Git is used to clone the application to the server.

Running NPM install

Executes npm install so the application dependencies ared installed.

Stop APP

PM2 daemon is stopped so we can restart it later. PM2 throws an error if the application does not exist. We can get around the error using ignore_errors:yes.

Start APP

Application becomes daemonized.

Deploying The Application

To deploy the application to the server, run the following against the app file that was created earlier.
ansible-playbook app.yml. This can take a few seconds to finish. Once the automation is complete, SSH into the server and make sure everything is running smoothly. Enjoy.