Overview

Manually uploading files to your VPS via FTP or SCP is error‑prone and time‑consuming. 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.