Setup a CD Pipeline for a Website on Ubuntu

By Anurag Singh

Updated on May 25, 2025

Setup a CD Pipeline for a Website on Ubuntu

In this tutorial, we'll setup a CD Pipeline for a Website on Ubuntu 24.04.

In today’s fast-paced development environment, having a reliable Continuous Deployment (CD) pipeline allows us to deliver updates to our website rapidly and confidently. In this guide, we’ll walk through setting up a CD pipeline for a simple static or dynamic website on an Ubuntu server.

We’ll leverage Git for version control, GitHub Actions for our Continuous Integration (CI), and an automated deployment script on the server to pull changes and restart services as needed. By the end, our website updates will flow seamlessly from code commit to live production with minimal manual intervention.

Prerequisites

Before we begin, let’s ensure we have the following in place:

  • A Ubuntu 24.04 dedicated server or KVM VPS.
  • A public or private GitHub repository containing your website’s source code.
  • An SSH key generated on your local machine, with the public key added to your GitHub account for cloning private repos.
  • Basic Shell Knowledge.

Setup a CD Pipeline for a Website on Ubuntu

1. Prepare the Ubuntu Server

Update packages

sudo apt update && sudo apt upgrade -y

Keeping the system updated ensures we have the latest security patches and software features.

Install Git and other essentials

sudo apt install -y git curl build-essential

These tools will help us clone repositories and build any frontend assets.

Create a Deployment User

sudo adduser deployer
sudo usermod -aG sudo deployer

Running deployments under a dedicated user improves security by limiting access.

Set Up SSH Access

Switch to the new user:

sudo su - deployer

Create an .ssh directory and add your public key:

mkdir ~/.ssh && chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys

Paste your public key, save, then:

chmod 600 ~/.ssh/authorized_keys

2. Clone the Website Repository

Generate a Deploy Script Directory

mkdir ~/site && cd ~/site

Clone from GitHub

git clone git@github.com:your-org/your-website.git .

Test a Local Build (if applicable)

If you’re using a static site generator or Node.js:

# Example for a Node.js build
npm install
npm run build

Confirm that the generated files appear (e.g., in dist/ or public/).

3. Create a Deployment Script

We’ll write a Bash script that pulls the latest code and restarts our web service.

Create deploy.sh

nano ~/site/deploy.sh

Populate with the following:

#!/usr/bin/env bash
set -e

echo "🔄 Starting deployment at $(date)"

# Navigate to site directory
cd /home/deployer/site

# Fetch and reset to latest main branch
git fetch origin main
git reset --hard origin/main

# Install dependencies & build (if needed)
if [ -f package.json ]; then
  npm ci
  npm run build
fi

# Restart the web server (example using systemd)
sudo systemctl restart site.service

echo "✅ Deployment completed at $(date)"

Make it executable

chmod +x ~/site/deploy.sh

4. Configure the Web Service

Assuming we’re serving via a simple Node.js or static file server under systemd:

Create a systemd Service

sudo nano /etc/systemd/system/site.service

Example for a Node.js Express App:

[Unit]
Description=Our Simple Website
After=network.target

[Service]
Type=simple
User=deployer
WorkingDirectory=/home/deployer/site
ExecStart=/usr/bin/node server.js
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable and Start

sudo systemctl daemon-reload
sudo systemctl enable site.service
sudo systemctl start site.service

Verify

sudo systemctl status site.service

Ensure the service is active and listening (you can also test via curl localhost).

5. Set Up GitHub Actions for CI/CD

We’ll trigger our deploy.sh on the server whenever code is merged into main.

Add a Workflow File

In your repository, create .github/workflows/deploy.yml.

Populate with:

name: CI/CD Pipeline

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

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

      - name: Run tests (optional)
        run: |
          # Add your test commands here
          echo "Running tests..."

      - name: Deploy to Ubuntu server
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: deployer
          key: ${{ secrets.SERVER_SSH_KEY }}
          port: 22
          script: |
            cd /home/deployer/site
            ./deploy.sh

Configure GitHub Secrets

In your repo’s Settings → Secrets:

  • SERVER_HOST: your server’s IP or domain
  • SERVER_SSH_KEY: the private SSH key (matched to the public key added earlier)

6. Test the Pipeline

Push a Change

echo "<!-- Deployed at $(date) -->" >> index.html
git add index.html
git commit -m "Test CD pipeline"
git push origin main

Monitor GitHub Actions

Navigate to the Actions tab and watch the workflow run.

Verify on the server. SSH into the server:

ssh deployer@your-server
tail -n 20 /home/deployer/site/deploy.log

Or simply reload the website in a browser and see your timestamped comment.

7. Enhance and Secure

  • Rollback Strateg: Keep a copy of the previous release (e.g., Git tags) to revert quickly if something breaks.
  • SSL with Let’s Encrypt: Install Certbot and configure HTTPS to secure traffic:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com

Monitoring & Alerts: Integrate basic uptime monitoring (e.g., UptimeRobot) and log shipping (e.g., using Promtail + Grafana Loki).

Conclusion

In this tutorial, we've setup a CD Pipeline for a Website on Ubuntu 24.04. By following these steps, we’ve built a robust Continuous Deployment pipeline where each commit to main automatically triggers a secure SSH connection to our Ubuntu server, pulls the latest code, builds the project, and restarts our service. This setup empowers us to focus on writing features instead of manual deployments, driving higher efficiency and reliability in our web development workflow.