Deploy a Node application using Puppet Bolt
Tags: configurationmanagement, puppet, puppetbolt, devops
Published: 2020-11-15 22:21:06

---
title: Deploy a Node application using Puppet Bolt
published: true
date: 2020-11-10 15:01:13 UTC
tags: configurationmanagement,puppet,puppetbolt,devops
canonical_url: https://medium.com/@martezreed/deploy-a-node-application-using-puppet-bolt-de0522335044
---

![](https://cdn-images-1.medium.com/max/1024/1*RK_hTe8SiZzHhceBaCH6hg.png)

Application deployment is a multi-step process that can even include touching multiple machines or systems. In this blog post we’ll look at how we can use Puppet Bolt to deploy a node application. The application is a simple todo application created by [scotch.io](https://github.com/scotch-io/node-todo) that is composed of a node application and a mongodb database. We’ll deploy the application and database on separate servers to show how this can be handled with Puppet Bolt.

We’ll create three (3) Bolt plans that will each be used for a different part of the automation. At a high level we want to install the mongodb database on our database virtual machine and then install our node application on the app virtual machine.

**Plan Overview**

- **todoapp** : The todoapp plan will be the overarching plan that actually handles the orchestration of the application deployment.
- **db** : The **db** plan installs the mongodb database on the database server virtual machine.
- **app** : The **app** plan installs node, npm, git and other prerequisites on the application server virtual machine.

**Forge modules**

The deployment plan uses the following Puppet Forge modules to deploy the application stack.

- puppet/mongodb
- puppet/nodejs
- camptocamp/systemd
- puppetlabs/vcsrepo
- puppet/firewalld

### Initialize the Bolt project

> _Ensure that the latest version of Puppet Bolt is installed before getting started._

Puppet Bolt utilizes **Project** directories as launching points for running Bolt operations. Create a directory for our Puppet Bolt project name **nodeproject.**

```
mkdir nodeproject
```

Change the working directory to **nodeproject** directory

```
cd nodeproject
```

Now that we have a directory for hosting our Bolt project, we need to initialize the project.

```
bolt project init --modules puppet-mongodb,puppet-nodejs,camptocamp-systemd,puppetlabs-vcsrepo,puppet-firewalld
```

The command should generate output similar to that shown below if it ran successfully.

```
Installing project modules

→ Resolving module dependencies, this may take a moment

→ Writing Puppetfile at

/system/path/nodeproject/Puppetfile

→ Syncing modules from

/system/path/nodeproject/Puppetfile to

/system/path/nodeproject/modules

→ Generating type references

Successfully synced modules from /system/path/nodeproject/Puppetfile to /system/path/nodeproject/modules

Successfully created Bolt project at /system/path/nodeproject
```

### Create the Bolt YAML plan

In order to utilize plans in Bolt, we need to create a directory named plans.

```
mkdir plans
```

Now that we have our plans directory created we’ll plan out what we want to accomplish as part of our plan.

The first thing we’ll do is create the todoapp plan that will call the app and db plans. The name of the sub or nested plans are app and db which are referenced in our plan by the name of the bolt project and the plan (**bolt\_project::bolt\_plan)**. The plan accepts two parameters ( **app, db** ) that specify the IP address or FQDN of the virtual machines used for the application and database.

```
---
parameters:
  app:
    type: TargetSpec
  db:
    type: TargetSpec

steps:
  - plan: nodeproject::db
    description: "Deploy todo node application mongodb database"
    parameters:
      db_targets: $db
  - plan: nodeproject::app
    description: "Deploy todo node application"
    parameters:
      app_targets: $app
      db_targets: $db
```

Now that we’ve got the todoapp plan in place we need to create the db plan to install the mongodb database. Create another plan in the **plans** directory named  **db.yaml**.

**Steps**

- Configure mongodb yum repository
- Install mongodb
- Create firewalld rule for mongodb (port 27017)

```
---
parameters:
  db_targets:
    type: TargetSpec

steps:
  - name: installmongo
    targets: $db_targets
    resources:
    - class: mongodb::globals
      parameters:
        version: 4.2.0
        manage_package_repo: true
        server_package_name: mongodb-org-server
        bind_ip: [0.0.0.0]
    - class: mongodb::server
      parameters:
        port: 27017
  - name: configurefirewall
    targets: $db_targets
    resources:
    - class: firewalld
    - firewalld_zone: 'public'
      parameters:
        ensure: present
        purge_ports: true
    - firewalld_port: 'node db'
      parameters:
        ensure: present
        port: 27017
        protocol: tcp
```

Finally, we’re ready to create the app plan to deploy the node application. Deploying the node application requires a number of steps to actually get the application running. The plan accepts the IP address or DNS name of the application virtual machine and the database virtual machine as parameters.

- Install the git package
- Create a firewalld rule for the node application (port 8080)
- Clone the node-todo git repository
- Install node and npm
- Install the node-todo application packages (npm install)
- Write the database configuration file
- Create a systemd unit file for the node application
- Reload the systemd daemon to recognize the unit file changes
- Start the todo-app service

```
---
parameters:
  app_targets:
    type: TargetSpec
  db_targets:
    type: String

steps:
  - name: installprerequisites
    description: "install app prerequisite software"
    targets: $app_targets
    resources:
    - package: git
      parameters:
        ensure: present
  - name: configurefirewall
    targets: $app_targets
    resources:
    - class: firewalld
    - firewalld_zone: 'public'
      parameters:
        ensure: present
        purge_ports: true
    - firewalld_port: 'node app'
      parameters:
        ensure: present
        port: 8080
        protocol: 'tcp'
  - name: installtodoapp
    targets: $app_targets
    resources:
    - vcsrepo: '/opt/node-todo'
      parameters:
        ensure: present
        provider: git
        source: '[https://github.com/scotch-io/node-todo.git'](https://github.com/scotch-io/node-todo.git')
        trust_server_cert: true
    - class: nodejs
    - nodejs::npm: 'app'
      parameters:
        ensure: present
        target: /opt/node-todo
        use_package_json: true
    - file: '/opt/node-todo/config/database.js'
      parameters:
        ensure: present
        content: >
          module.exports = {
            remoteUrl : "mongodb://$db_targets:27017/uwO3mypu",
            localUrl: "mongodb://$db_targets:27017/meanstacktutorials"
          };
    - file: '/etc/systemd/system/todo-app.service'
      parameters:
        ensure: present
        content: >
          [Unit]

          Description=Todo node application

          Documentation=[https://github.com/scotch-io/node-todo](https://github.com/scotch-io/node-todo)

          After=network.target

          [Service]

          Type=simple

          WorkingDirectory=/opt/node-todo

          ExecStart=/usr/bin/npm start

          Restart=on-failure

          [Install]

          WantedBy=multi-user.target
        notify: Class[systemd::systemctl::daemon_reload]
    - class: systemd::systemctl::daemon_reload
    - service: 'todo-app'
      parameters:
        ensure: running
        subscribe: File[/etc/systemd/system/todo-app.service]
```

Now that we’ve created our plans we can ensure that it’s recognized by Bolt by running the following command.

```
bolt plan show
```

If the plan registers properly the output should include the following entries.

- **_nodeproject::todoapp_**
- **_nodeproject::app_**
- **_nodeproject::db_**

```
aggregate::count
aggregate::nodes
aggregate::targets
canary
facts
facts::external
facts::info
nodeproject::app  
nodeproject::db  
nodeproject::todoapp
puppet_agent::run
puppetdb_fact
reboot
secure_env_vars
terraform::apply
terraform::destroy
secure_env_vars
terraform::apply
terraform::destroy
```

With the plans registered we are now ready to run the todoapp plan by running the bolt plan run nodeproject::todoapp command. The plan.

```
bolt plan run nodeproject::todoapp app=10.0.0.41 db=10.0.0.42
```

If the plan ran successfully it should have generated output similar to that displayed below.

```
Starting: plan nodeproject::todoapp
Starting: plan nodeproject::db
Starting: install puppet and gather facts on 10.0.0.42
Finished: install puppet and gather facts with 0 failures in 74.59 sec
Starting: apply catalog on 10.0.0.42
Finished: apply catalog with 0 failures in 35.91 sec
Starting: install puppet and gather facts on 10.0.0.42
Finished: install puppet and gather facts with 0 failures in 8.03 sec
Starting: apply catalog on 10.0.0.42
Finished: apply catalog with 0 failures in 19.44 sec
Finished: plan nodeproject::db in 2 min, 18 sec
Starting: plan nodeproject::app
Starting: install puppet and gather facts on 10.0.0.41
Finished: install puppet and gather facts with 0 failures in 74.78 sec
Starting: apply catalog on 10.0.0.41
Finished: apply catalog with 0 failures in 25.49 sec
Starting: install puppet and gather facts on 10.0.0.41
Finished: install puppet and gather facts with 0 failures in 7.59 sec
Starting: apply catalog on 10.0.0.41
Finished: apply catalog with 0 failures in 18.23 sec
Starting: install puppet and gather facts on 10.0.0.41
Finished: install puppet and gather facts with 0 failures in 8.9 sec
Starting: apply catalog on 10.0.0.41
Finished: apply catalog with 0 failures in 65.48 sec
Finished: plan nodeproject::app in 3 min, 21 sec
Finished: plan nodeproject::todoapp in 5 min, 40 sec
Plan completed successfully with no result
```

Once the command completes successfully we can check that everything worked by opening entering the IP address or FQDN of the Bolt target in a web browser. The site should show the following message.

![](https://cdn-images-1.medium.com/max/1024/1*VPpMrnu6wUck0ha6xepncg.png)

We have now successfully deployed a node application using Puppet Bolt. The automation can be made more elaborate such as interacting with a load balancer, performing database prep operations or more.