Skip to content

This repository offers a GitHub Actions-powered CI/CD pipeline for deploying a Node.js service, integrating Terraform for DigitalOcean droplet provisioning, Ansible for server configuration and deployment, and systemd for service management, with secure secret handling and optional SSH-based workflows.

Notifications You must be signed in to change notification settings

roadmap-sh-kzwolenik95/nodejs-service-deployment

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Challenge link: https://roadmap.sh/projects/nodejs-service-deployment

Challenge goals

The goal of this project is to practice setting up a CI/CD pipeline for a Node.js service using GitHub Actions.

Prerequisites

Before deploying the website, ensure you have the following:

  1. HCP Terraform account - create an organization (e.g., "roadmap-sh") and generate an API token

  2. Digital Ocean API token required for managing cloud resources on DigitalOcean

  3. SSH key pair - used by ansible and you to connect to the server

  4. GitHub repo configured with secrets and variables, these can be set up quickly using the gh cli tool

    gh variable set DO_KEY_NAME -b <digitalocean keyname> # https://cloud.digitalocean.com/account/security
    
    gh secret set DIGITALOCEAN_API_TOKEN -b <digital ocean api token>
    gh secret set SSH_PRIV_KEY -b "$(cat <private key file path>)"
    gh secret set HCP_TERRAFORM_TOKEN -b <hcp terraform token>

Running the pipelines

There are two pipelines set up. Both are activated manually, one is used to deploy the project the other one are used to clean up resources.

Ansible role to deploy the app

First we use a set_fact module to extract repository name from the repository url, this could change for other users that fork this repo

- name: Extract repository name from URL
  ansible.builtin.set_fact:
    repository_name: "{{ repository_url.split('/')[-1].split('.')[0] }}"

We need to get the files to the machine, we use ansible git module (git must be installed on the remote machine, we took care of that in the base role)

- name: Fetch app files # noqa: latest
  ansible.builtin.git:
    repo: "{{ repository_url }}"
    dest: "{{ ansible_facts.user_dir }}/{{ repository_name }}"

We use shell module to run commands to install dependencies and build the app, we need to chdir to the nodejs app directory

- name: Install npm depdendencies and build app
  ansible.builtin.shell: |
    npm install
    npm run build
  args:
    executable: /bin/bash
    chdir: "{{ ansible_facts.user_dir }}/{{ repository_name }}/hello-world-app"
  changed_when: true

Finally we create systemd service and run the server, the service will take care of maitaining the server running

Service file template:

[Unit]
Description=NodeJS Hello World service
After=network.target

[Service]
User=root
Group=root
WorkingDirectory={{ working_directory }}
ExecStart=bash -c "npm start"
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
- name: Create service unit
  ansible.builtin.template:
    src: templates/nodejs-server-service.j2
    dest: /etc/systemd/system/nodejs-server.service
    owner: root
    group: root
    mode: "0644"
  vars:
    working_directory: "{{ ansible_facts.user_dir }}/{{ repository_name }}/hello-world-app"

- name: Reload daemon and start the new service
  ansible.builtin.systemd:
    name: nodejs-server.service
    state: started
    enabled: true
    daemon_reload: true

About

This repository offers a GitHub Actions-powered CI/CD pipeline for deploying a Node.js service, integrating Terraform for DigitalOcean droplet provisioning, Ansible for server configuration and deployment, and systemd for service management, with secure secret handling and optional SSH-based workflows.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published