This repository provides a GitHub Actions CI/CD template to automatically update code from Git and restart a Linux service or PM2-managed app on a remote server using SSH.
🚀 Ideal for deploying updates to remote Git projects directly from your GitHub repository.
- ✅ Automatic deployment on push to main(or any branch)
- 🔐 Secure connection via SSH (using GitHub secrets)
- 🌀 Pulls the latest code from Git
- 🔁 Restarts a Linux service or PM2 process
- 🔧 Easy to fork and adapt for any project
.github/
└── workflows/
   └── deploy.yml # CI/CD workflow
- Remote server with:
- Git installed
- PM2 (for Node.js apps) or a systemd-managed service
- SSH access configured
 
- GitHub repository with:
- This template copied or forked
- Required secrets added (see below)
 
Go to your repo → Settings → Secrets and variables → Actions → New repository secret and add:
| Secret Name | Description | 
|---|---|
| SSH_HOST | IP or domain of your remote server | 
| SSH_USERNAME | SSH user with access to the project directory | 
| SSH_KEY | Private SSH key (no passphrase) | 
| SSH_PASSWORD | SSH password with access to the project directory | 
| PROJECT_DIRECTORY | Absolute path of the Git project on the server | 
| RESTART_COMMAND | Command to restart the service or PM2 app | 
name: Deploy via SSH by Key
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v4
      - name: Set up SSH
        uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_KEY }}
      - name: Connect and Deploy
        run: |
          ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'EOF'
            cd ${{ secrets.PROJECT_DIRECTORY }}
            git fetch origin main
            git reset --hard origin/main
            git clean -fd
            if [ -n "${{ secrets.RESTART_COMMAND }}" ]; then
              eval "${{ secrets.RESTART_COMMAND }}"
            fi
          EOFname: Deploy via SSH by Password
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Install sshpass
        run: sudo apt-get update && sudo apt-get install -y sshpass
      - name: Deploy to Server via SSH
        env:
          SSHPASS: ${{ secrets.SSH_PASSWORD }}
        run: |
          sshpass -e ssh -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << EOF
            cd ${{ secrets.PROJECT_DIRECTORY }}
            git fetch origin main
            git reset --hard origin/main
            git clean -fd
            if [ -n "${{ secrets.RESTART_COMMAND }}" ]; then
              eval "${{ secrets.RESTART_COMMAND }}"
            fi
          EOF- Fork this repo (or copy deploy.yml to your own)
- Add the required GitHub secrets
- Ensure SSH access from GitHub to your remote server
- Push to main branch - the deployment runs automatically!
Change main to another branch in the on.push.branches section
Use different RESTART_COMMAND values such as:
- pm2 restart app-name
- sudo systemctl restart my-service
- npm run build && pm2 reload ecosystem.config.js
You can manually trigger a run from GitHub:
Go to Actions → Deploy via SSH → Run workflow
MIT License - feel free to use and adapt.
Max Base (Ali)
🔗 GitHub: @BaseMax