Logo
  • AI Chat
  • Blog
  • Passion
  • Projects
  • Experience
  • Contact
  • Contact
    © 2025 | Dajour Walker
  • Twitter-colorCreated with Sketch.
  • CI/CD
    GitHub Actions

    CI/CD Deployment on Ubuntu VPS Using GitHub Actions

    Jun 28, 2024|

    5m read

    Post image

    Table of Contents

    1. Why CI/CD is Crucial for Modern Development
    2. Enhancing Development Efficiency
    3. Improving Code Quality and Consistency
    4. My Journey to CI/CD Implementation
    5. Prerequisites
    6. Tools and Technologies
    7. Setup Your Environment
    8. Step-by-Step Guide
    9. 1. Setting Up SSH Keys in VPS
    10. 2. Configuring GitHub Actions
    11. Conclusion
    12. Benefits of CI/CD with GitHub Actions
    13. Next Steps

    Implementing Continuous Integration and Continuous Deployment (CI/CD) is crucial for maintaining a streamlined and efficient development workflow. In this guide, we will explore how to set up CI/CD on an Ubuntu VPS using SSH for deploying a Next.js project with GitHub Actions.

    Why CI/CD is Crucial for Modern Development

    Enhancing Development Efficiency

    CI/CD automates the testing and deployment processes, which significantly reduces the time and effort required to deliver high-quality software. By continuously integrating code changes and automatically deploying them to production, development teams can ensure that their applications are always in a deployable state.

    Improving Code Quality and Consistency

    Automated testing and integration help identify issues early in the development cycle, ensuring that only code that passes predefined quality checks is deployed. This consistency leads to more stable and reliable applications, reducing the risk of bugs and errors in production.

    My Journey to CI/CD Implementation

    I decided to write this article to share my experience in setting up a CI/CD pipeline for a Next.js project. After facing challenges with manual deployments and inconsistent build processes, I realized the need for a robust solution to streamline these tasks. GitHub Actions provided an integrated platform to automate the entire workflow, from code changes to deployment on an Ubuntu VPS.

    Prerequisites

    Tools and Technologies

    • Ubuntu VPS: Ensure you have an Ubuntu server set up.
    • SSH Access: Secure Shell access to your VPS.
    • GitHub Repository: Your project hosted on GitHub.
    • Next.js Project: Example project for deployment.

    Setup Your Environment

    • Install Node.js and npm: Required for Node.js project
    • Install pm2: Monitoring Project
    • Install Git: Version control system.

    Step-by-Step Guide

    1. Setting Up SSH Keys in VPS

    • Generate SSH Key Pair: ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    • Setup SSH Key for authorization: Copy generated public key content to .ssh/authorized_keys
    • GitHub Secrets: You should create your GitHub secrets for your repository. Go to your repository > Settings > Secrets > Actions > New repository secret.
    • Create GitHub Secrets
    No alt-tag provided

    Here are required Github Secrets

    PERSONAL_GITHUB_TOKEN=Your GitHub Token to pull your repo.

    VPS_IP=Your Ubuntu Server IP (Or you can input the domain instead of IP)

    VPS_USERNAME=Your username to login to your Server (e.g. ubuntu)

    SSH_PRIVATE_KEY=Past your SSH private key that you generated in the server
    SSH_PASSPHRASE=Your password to login to your Server

    • Create GitHub Vars

    Create MY_APP=(your product website link)

    2. Configuring GitHub Actions

    • Create Workflow File: .github/workflows/deploy.yml
    • Define Workflow Triggers: Specify when the workflow should run (e.g., on push to main branch).
    • Setup SSH connection using actions/checkout@v2

    • Add code to show the environment status.

    This is example full code to deploy on main branch with production environment.

    • Deploy to VPS: try to commit and push to your main branch with updated project

    Conclusion

    Benefits of CI/CD with GitHub Actions

    • Automation: Reduces manual intervention.
    • Reliability: Ensures consistent and reliable deployments.
    • Speed: Faster development cycles and quicker releases.

    Next Steps

    • Monitor Your Deployments: Set up monitoring and alerts.
    • Enhance Security: Regularly update your dependencies and server.
    • Optimize Performance: Continuously improve your build and deployment processes.

    By following this guide, you will have a robust CI/CD pipeline set up on your Ubuntu VPS, making your Next.js project deployments smoother and more efficient. Happy coding!

    Follow on Medium

    deploy.yml
    name: Auto Deploy in VPS after Push in Production
    
    on:
      push:
        branches:
          - main
    jobs:
      deploy:
        name: Deploy project
        permissions:
          deployments: write
        runs-on: ubuntu-latest
        steps:
          - name: Checkout Repository
            uses: 'actions/checkout@v2'
            with:
              ref: main
              token: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
          - name: Create GitHub deployment
            uses: chrnorm/deployment-action@v2
            id: deployment
            with:
              token: '${{ github.token }}'
              environment-url: ${{ vars.MY_APP }}
              environment: production
          - name: Set up SSH Key and Deploy my App on Server
            # run: |
            uses: appleboy/ssh-action@master
            env:
              GITHUB_TOKEN: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
            with:
              host: ${{ secrets.VPS_IP }}
              username: ${{ secrets.VPS_USERNAME }}
              key: ${{ secrets.SSH_PRIVATE_KEY }}
              passphrase: ${{ secrets.SSH_PASSPHRASE }}
              port: 22
              script: |
                git config --global url."https://${{ secrets.PERSONAL_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com"
                cd chatg/
                git pull origin main
                npm ci
                npm run frontend
                pm2 restart chatg --update-env
    deploy.yml
    - name: Update deployment Status (success)
      if: success()
      uses: chrnorm/deployment-status@v2
      with:
        token: '${{ github.token }}'
        environment-url: ${{ vars.MY_APP }}
        state: 'success'
        deployment-id: ${{ steps.deployment.outputs.deployment_id }}
    
    - name: Update deployment status (failure)
      if: failure()
      uses: chrnorm/deployment-status@v2
      with:
        token: '${{ github.token }}'
        environment-url: ${{ vars.MY_APP }}
        state: 'failure'
        deployment-id: ${{ steps.deployment.outputs.deployment_id }}
    deploy.yml
    name: Auto Deploy in VPS after Push in Production
    
    
    on:
      push:
        branches:
          - main
    jobs:
      deploy:
        name: Deploy project with Nginx
        permissions:
          deployments: write
        runs-on: ubuntu-latest
        steps:
          - name: Checkout Repository
            uses: 'actions/checkout@v2'
            with:
              ref: main
              token: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
          - name: Create GitHub deployment
            uses: chrnorm/deployment-action@v2
            id: deployment
            with:
              token: '${{ github.token }}'
              environment-url: ${{ vars.MY_APP }}
              environment: production
          - name: Set up SSH Key and Deploy my App on Server
            # run: |
            uses: appleboy/ssh-action@master
            env:
              GITHUB_TOKEN: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
            with:
              host: ${{ secrets.VPS_IP }}
              username: ${{ secrets.VPS_USERNAME }}
              key: ${{ secrets.SSH_PRIVATE_KEY }}
              passphrase: ${{ secrets.SSH_PASSPHRASE }}
              port: 22
              script: |
                git config --global url."https://${{ secrets.PERSONAL_GITHUB_TOKEN }}:@github.com".insteadOf "https://github.com"
                cd chatg/
                git pull origin dev-branch
                npm ci
                npm run frontend
                pm2 restart chatg --update-env
          - name: Update deployment Status (success)
            if: success()
            uses: chrnorm/deployment-status@v2
            with:
              token: '${{ github.token }}'
              environment-url: ${{ vars.MY_APP }}
              state: 'success'
              deployment-id: ${{ steps.deployment.outputs.deployment_id }}
          
          - name: Update deployment status (failure)
            if: failure()
            uses: chrnorm/deployment-status@v2
            with:
              token: '${{ github.token }}'
              environment-url: ${{ vars.MY_APP }}
              state: 'failure'
              deployment-id: ${{ steps.deployment.outputs.deployment_id }}