DevOps
Infrastructure as Code
Project: Automated Express Deployment

Project: Automated Express Deployment

In this capstone project, we will build a production-ready automation pipeline using Ansible to deploy an Express.js application. We will automate everything from server updates and dependency installation to process management and reverse proxy configuration.


๐Ÿ—๏ธ Architecture Overview

Our automation will transform a bare Linux server into a secure web host with the following layers:


๐Ÿ“‚ Project Structure

Organize your Ansible project directory as follows:

ansible-project/
โ”œโ”€โ”€ inventory           # Host definitions
โ”œโ”€โ”€ deploy.yml          # Main playbook
โ””โ”€โ”€ templates/          # Dynamic configuration files
    โ”œโ”€โ”€ nginx.conf.j2   # Nginx template
    โ””โ”€โ”€ app.service.j2  # Systemd service template

๐Ÿ› ๏ธ Phase 1: The Inventory

Define your application servers in the inventory file:

[webservers]
app_server_primary ansible_host=1.2.3.4 ansible_user=ubuntu

๐Ÿš€ Phase 2: The Master Playbook (deploy.yml)

The playbook automates the entire lifecycle.

- name: Deploy Express.js Application
  hosts: webservers
  become: true
  vars:
    app_repo: "https://github.com/example/express-app.git"
    app_path: "/var/www/express-app"
    node_version: "20.x"
 
  tasks:
    - name: ๐Ÿ“ฆ Install Node.js and Global Dependencies
      shell: "curl -fsSL https://deb.nodesource.com/setup_{{ node_version }} | bash - && apt-get install -y nodejs nginx git"
 
    - name: ๐Ÿ“‚ Clone Application Repository
      git:
        repo: "{{ app_repo }}"
        dest: "{{ app_path }}"
        update: yes
 
    - name: โš™๏ธ Install Npm Dependencies
      npm:
        path: "{{ app_path }}"
 
    - name: ๐Ÿ›ก๏ธ Setup Systemd Service
      template:
        src: templates/app.service.j2
        dest: "/etc/systemd/system/express-app.service"
      notify: Restart Express
 
    - name: ๐ŸŒ Configure Nginx Reverse Proxy
      template:
        src: templates/nginx.conf.j2
        dest: "/etc/nginx/sites-available/default"
      notify: Restart Nginx
 
  handlers:
    - name: Restart Express
      systemd:
        name: express-app
        state: restarted
        daemon_reload: yes
 
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted

โš™๏ธ Phase 3: Dynamic Templates

1. Systemd Service (templates/app.service.j2)

This ensures your app starts automatically if the server reboots or the process crashes.

[Unit]
Description=Express App
After=network.target
 
[Service]
Type=simple
User=ubuntu
WorkingDirectory={{ app_path }}
ExecStart=/usr/bin/node index.js
Restart=always
 
[Install]
WantedBy=multi-user.target

2. Nginx Configuration (templates/nginx.conf.j2)

Maps external web traffic to your internal Node.js port.

server {
    listen 80;
    server_name localhost;
 
    location / {
        proxy_pass http://localhost:3000;
        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;
    }
}

๐Ÿ Execution & Final Verification

  1. Run the playbook:

    ansible-playbook -i inventory deploy.yml
  2. Verify the service:

    systemctl status express-app
  3. Visit the IP: Open your browser at http://<your-server-ip> to see your Express.js app live!