Manually uploading files to your VPS via FTP or SCP is error‑prone and time‑consuming. GitHub Actions automates deployment whenever you push code to your repository.

This guide shows you how to set up a GitHub Actions workflow that deploys to a VPS using SSH.

What You'll Need

A GitHub repository with your website code (HTML, PHP, Node.js, etc.), a VPS with SSH access (check our VPS reviews if you need one), and basic knowledge of YAML syntax.

Step 1: Set Up SSH Key Pair

Generate an SSH key pair on your local machine (if you don't have one):

ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/github-actions

This creates github-actions (private key) and github-actions.pub (public key).

Add the public key to your VPS:

ssh-copy-id -i ~/.ssh/github-actions.pub user@your_server_ip

Step 2: Add Secrets to GitHub Repository

Go to your GitHub repository → Settings → Secrets and variables → Actions → New repository secret.

Add two secrets:

  • VPS_HOST – Your server's IP address or domain
  • VPS_USERNAME – Your SSH username
  • VPS_SSH_KEY – The content of the private key (~/.ssh/github-actions)

To add the private key, copy the entire file content including -----BEGIN OPENSSH PRIVATE KEY----- and -----END OPENSSH PRIVATE KEY-----.

Step 3: Create GitHub Actions Workflow

In your repository, create a directory .github/workflows/ and add a file named deploy.yml.

name: Deploy to VPS

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh/
          echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan -H ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts

      - name: Deploy via rsync
        run: |
          rsync -avz --delete ./ user@${{ secrets.VPS_HOST }}:/var/www/html/

This workflow triggers on every push to the main branch. It checks out your code, sets up SSH, then syncs files via rsync.

Step 4: Customize for Your Environment

Adjust the rsync command for your specific setup.

Exclude certain files:

rsync -avz --delete --exclude '.git' --exclude 'node_modules' ./ user@${{ secrets.VPS_HOST }}:/var/www/html/

Run commands after deployment (e.g., restart service):

- name: Restart service
  run: |
    ssh user@${{ secrets.VPS_HOST }} 'sudo systemctl restart myapp'

Use different branch: Change branches: [ main ] to branches: [ master ] or branches: [ develop ].

Step 5: Test the Workflow

Push a change to your repository's main branch:

git add .
git commit -m "Test deployment"
git push origin main

Go to your repository → Actions tab. You should see the workflow running. After completion, check your VPS to confirm files updated.

Common Issues and Fixes

"Permission denied (publickey)" – Check that the public key is properly added to VPS's ~/.ssh/authorized_keys. Also ensure the private key secret is correct.

"No such file or directory" – The destination directory on VPS may not exist. Create it first via SSH.

"rsync: command not found" – Install rsync on your VPS: sudo apt install rsync -y (Ubuntu) or sudo yum install rsync -y (CentOS).

Next Steps

Once automated deployment works, you can extend the workflow to run tests, build static sites, or notify Slack on success/failure.

Need a VPS to practice on? Check our recommended VPS providers.