Skip to content

GitHub → Server (CI/CD Deploy via SSH)#


A. GitHub Actions Workflow (Deploy)#

Job (example: Django / Python)#

name: Deploy to Production

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Deploy to Server
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          port: 22
          script: |
            set -e
            cd /var/www/Project1

            git config --global --add safe.directory /var/www/Project1 || true

            if [ ! -d .git ]; then
              git init
              git remote add origin git@github.com-Project1:${{ github.repository }}.git
              git fetch origin
              git checkout -b main origin/main
            else
              git fetch origin
              git reset --hard origin/main
            fi

            source venv/bin/activate
            pip install -r requirements.txt
            python manage.py migrate --noinput
            python manage.py collectstatic --noinput
            sudo systemctl restart Project1.service

            echo "Deployment completed successfully"

B. Server-side SSH Setup#

1️⃣ Key for GitHub Actions → Server access#

ssh-keygen -t ed25519 -C "github-actions-server-access" -f ~/.ssh/github_actions_key -N ""
cat ~/.ssh/github_actions_key.pub >> ~/.ssh/authorized_keys
  • Private key → GitHub Secrets (SSH_PRIVATE_KEY)
  • Public key → server authorized_keys

2️⃣ Deploy key for Server → GitHub (git pull)#

ssh-keygen -t ed25519 -C "backend-deploy" -f ~/.ssh/backend_deploy_key -N ""
  • Add PUBLIC key to GitHub repo → Deploy Keys (Read-only or Read/Write)

3️⃣ SSH config (MULTI-REPO PRO SETUP)#

# ~/.ssh/config

Host github.com-Project1
  HostName github.com
  User git
  IdentityFile ~/.ssh/backend_deploy_key
  IdentitiesOnly yes
  StrictHostKeyChecking no

Host github.com-Project2
  HostName github.com
  User git
  IdentityFile ~/.ssh/project2_deploy_key
  IdentitiesOnly yes
  StrictHostKeyChecking no

Permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
ssh-keyscan github.com >> ~/.ssh/known_hosts

C. Git Setup on Server#

cd /var/www/Project1

git remote set-url origin git@github.com-Project1:ORG/Project1.git
git fetch origin
git checkout main

D. Why TWO keys? (important)#

Purpose Key Reason
Actions → Server github_actions_key Allows CI to SSH into server
Server → GitHub backend_deploy_key Allows server to pull code

✅ Least-privilege ✅ Clean revocation ✅ Multi-repo safe


Template note: Replace Project1, Project2, and service names per project.