DEV Community

Sospeter Mong'are
Sospeter Mong'are

Posted on

How to Set Up a Node.js CI/CD Pipeline on cPanel Using GitHub Actions and Passenger

If you’re hosting your Node.js application on a cPanel-based server, you can automate deployments using GitHub Actions.
This guide walks you through setting up a simple, production-ready CI/CD pipeline that automatically deploys your code and restarts the app on every push to the main branch.


🧩 Why Use CI/CD with cPanel?

Traditionally, developers log in to cPanel, upload updated files, and manually click the Restart button after every change.
That approach is slow, repetitive, and error-prone.

By integrating GitHub Actions, you can:

  • Deploy new code automatically on every push.
  • Run builds and dependency installations remotely.
  • Restart your Node.js app automatically using Passenger (the process manager used by cPanel for Node.js apps).

🛠️ Prerequisites

Before you begin, make sure you have:

  • A Node.js app hosted on cPanel (e.g., api.exampledomain.com).
  • SSH access enabled on your cPanel account.
  • Your app is already running via Passenger (cPanel’s Node.js app handler).
  • A GitHub repository containing your app source code.

🔑 1. Store Your cPanel Credentials as GitHub Secrets

In your GitHub repository:

  1. Go to Settings → Secrets and variables → Actions → New repository secret.
  2. Add the following secrets:
Secret Name Description
SSH_HOST Your cPanel server IP or domain
SSH_USERNAME Your cPanel username (e.g. webhost123)
SSH_PASSWORD Your cPanel account password
SSH_PORT Usually 22

⚙️ 2. Create the GitHub Actions Workflow

Inside your repository, create a new file:

.github/workflows/deploy.yml
Enter fullscreen mode Exit fullscreen mode

Paste the following configuration:

name: Deploy Node.js App to cPanel

on:
  push:
    branches:
      - main  

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: 🧩 Checkout code
        uses: actions/checkout@v3

      - name: ⚙️ Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '22'

      - name: 📦 Install dependencies
        run: npm install

      - name: 🏗️ Build (if needed)
        run: npm run build || echo "No build script"

      - name: 🚀 Deploy to cPanel via SSH
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          port: ${{ secrets.SSH_PORT }}
          source: "., !.git"
          target: "/home/webhost123/api.exampledomain.com"
          strip_components: 1

      - name: 🔁 Restart Node.js App via Passenger
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          port: ${{ secrets.SSH_PORT }}
          script: |
            echo "🔧 Activating virtual environment..."
            source /home/webhost123/nodevenv/api.exampledomain.com/22/bin/activate

            echo "📂 Navigating to app directory..."
            cd /home/webhost123/api.exampledomain.com

            echo "📦 Updating dependencies..."
            npm update

            echo "✅ Node version: $(node --version)"
            echo "✅ NPM version: $(npm --version)"

            echo "♻️ Restarting Node.js app via Passenger..."
            mkdir -p tmp && touch tmp/restart.txt

            echo "✅ Application deployed and restarted successfully!"

      - name: ✅ Deployment Success
        run: echo "🎉 Deployment to api.exampledomain.com was successful!"
Enter fullscreen mode Exit fullscreen mode

🧠 How It Works

  1. Trigger:
    The workflow runs automatically whenever code is pushed to the main branch.

  2. Build and Upload:
    GitHub Actions installs dependencies and uploads the latest build to your cPanel app directory via SSH.

  3. Virtual Environment Activation:
    The workflow activates your Node.js virtual environment created by cPanel (usually located in /home/USERNAME/nodevenv/APP_FOLDER/22/bin/activate).

  4. Passenger Restart:
    The command

   mkdir -p tmp && touch tmp/restart.txt
Enter fullscreen mode Exit fullscreen mode

signals Passenger to gracefully restart your app without downtime.


🧩 Folder Structure Example

On your cPanel server, the structure typically looks like:

/home/webhost123/
│
├── nodevenv/
│   └── api.exampledomain.com/
│       └── 22/
│           ├── bin/
│           └── lib/
│
└── api.exampledomain.com/
    ├── index.js
    ├── package.json
    └── tmp/
Enter fullscreen mode Exit fullscreen mode

The tmp/restart.txt file is automatically created or updated by your pipeline to restart Passenger.


🧩 Common Issues

Issue Cause Fix
pm2: command not found cPanel uses Passenger, not PM2 Replace PM2 commands with the Passenger restart method
❌ App doesn’t restart Missing tmp folder Add mkdir -p tmp && touch tmp/restart.txt
⚠️ SSH fails Wrong credentials or port Double-check GitHub secrets

✅ Benefits of This Setup

  • No manual uploads or restarts.
  • Automatic environment activation.
  • Works natively with cPanel Node.js hosting.
  • Can be extended for build steps, testing, or notifications.

🎉 Final Thoughts

With this setup, every time you push to your main branch, your Node.js application hosted on cPanel is automatically deployed, updated, and restarted — all without you ever logging into cPanel.

It’s a simple but powerful CI/CD pipeline for small to mid-scale Node.js apps hosted on shared servers.

Top comments (0)