How to Automate Application Deployment to a Ubuntu Vps with Github Actions and SSH Deploy Keys

Learning how to automate application deployment to a Ubuntu VPS with GitHub Actions and SSH deploy keys can save you hours every week. Instead of manually SSHing into your server every time you push code, you can let GitHub do the heavy lifting. Every push to your main branch triggers a workflow that connects to your server, pulls the latest code, and restarts your application automatically. This tutorial walks you through the entire process from start to finish. You’ll generate SSH deploy keys, configure your VPS, set up a GitHub Actions workflow, and test a live deployment. Whether you’re running a Node.js app, a PHP project, or a WordPress plugin, this approach works across the board. By the end, you’ll have a repeatable, reliable deployment pipeline that runs without any manual steps.

Prerequisites for Automating Application Deployment to a Ubuntu VPS

Before you start, make sure you have the following in place.

Required access and software:

  • A Ubuntu 20.04 or 22.04 VPS (DigitalOcean, Linode, Vultr, or similar)
  • Root or sudo access to your server
  • A GitHub account with a repository containing your application code
  • Basic familiarity with the Linux command line
  • SSH client installed on your local machine

Assumed knowledge: You should know how to connect to a server via SSH and edit files using a terminal editor like nano or vim. You don’t need to know GitHub Actions in depth. This tutorial explains every step.

Estimated time: 30 to 45 minutes.

Your VPS should already have your application files in a directory, such as /var/www/myapp. If you’re starting from scratch, clone your repo manually once before setting up automation. That gives the workflow a clean base to pull updates into.

How to Set Up SSH Deploy Keys for GitHub Actions Deployment

For a related walkthrough, see: How to Set Up and Configure Pfsense Firewall From Scratch

SSH deploy keys let GitHub Actions authenticate with your server securely. You generate a key pair, add the private key to GitHub, and add the public key to your server.

Step 1: Generate an SSH key pair on your local machine.

Run this command. Replace the comment with something descriptive:

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

When prompted for a passphrase, press Enter twice to leave it empty. GitHub Actions can’t enter a passphrase interactively.

Step 2: Add the public key to your VPS.

Copy the public key content first:

cat ~/.ssh/github_deploy_key.pub

Now SSH into your server and append that key to the authorized_keys file:

ssh your_user@your_server_ip
mkdir -p ~/.ssh
nano ~/.ssh/authorized_keys

Paste the public key on a new line, then save the file. Set correct permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Step 3: Add the private key to GitHub Secrets.

On your local machine, display the private key:

cat ~/.ssh/github_deploy_key

Copy the entire output, including the header and footer lines. In your GitHub repository, go to Settings → Secrets and variables → Actions → New repository secret. Name it SSH_PRIVATE_KEY and paste the private key as the value. Save it.

Add two more secrets:

  • SSH_HOST , your server’s IP address
  • SSH_USER , the Linux user that owns your app directory

For more details on GitHub Actions secrets, see the official GitHub encrypted secrets documentation.

How to Configure the GitHub Actions Workflow to Deploy to Ubuntu

Now you’ll create the workflow file that runs on every push to your main branch.

Step 4: Create the workflow directory in your project.

In your local project folder, run:

mkdir -p .github/workflows

Step 5: Create the deployment workflow file.

Create a new file called deploy.yml:

nano .github/workflows/deploy.yml

Paste in the following workflow:

name: Deploy to Ubuntu VPS

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up SSH key
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts

      - name: Deploy via SSH
        run: |
          ssh -i ~/.ssh/deploy_key ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'EOF'
            cd /var/www/myapp
            git pull origin main
            npm install --production
            pm2 restart myapp
          EOF

Adjust the commands inside the EOF block to match your application. For a PHP app, you might run composer install. For WordPress, you might clear a cache or run a build script.

Step 6: Commit and push the workflow file.

git add .github/workflows/deploy.yml
git commit -m "Add GitHub Actions deployment workflow"
git push origin main

GitHub will immediately detect the new workflow and trigger a run.

Step 7: Verify the deployment ran successfully.

Go to your GitHub repository. Click the Actions tab. You’ll see the workflow running or completed. Click into it to see each step’s output. A green checkmark means your deployment succeeded. If any step fails, the logs show exactly what went wrong.

For reference on Ubuntu server security best practices when opening SSH access, see the Ubuntu Server security documentation.

Troubleshooting Common Deployment Errors

Even with a clean setup, things can go wrong. Here are the most common issues and how to fix them.

Permission denied (publickey)
This usually means the public key wasn’t added correctly to authorized_keys. Double-check that the key is on one line with no line breaks. Also confirm the file permissions are 600 and the .ssh directory is 700.

Host key verification failed
The ssh-keyscan step in your workflow handles this automatically. If you’re still seeing this error, check that SSH_HOST matches the exact IP or hostname your server uses.

git pull fails with “not a git repository”
Your app directory on the server needs to be a cloned Git repository. SSH into your server and run git status inside the directory. If it’s not a repo, clone it manually first:

cd /var/www
git clone https://github.com/yourusername/yourrepo.git myapp

pm2 command not found
If you’re using pm2 for Node.js process management, make sure it’s installed globally on your server:

npm install -g pm2

Workflow doesn’t trigger on push
Check that your default branch is named main. If it’s master, update the branches value in your workflow file accordingly.

Tip: Always test your SSH connection manually from your local machine before relying on GitHub Actions. Run ssh -i ~/.ssh/github_deploy_key your_user@your_server_ip to confirm it works without a password prompt.

Conclusion

You now know how to automate application deployment to a Ubuntu VPS with GitHub Actions and SSH deploy keys. Every push to your main branch will now trigger a secure, automated deployment without any manual steps. This setup is clean, auditable, and easy to extend. You can add steps to run tests before deploying, send Slack notifications on success or failure, or deploy to multiple servers in parallel. Start with this basic workflow and build on it as your project grows. Automated deployments reduce human error and give your team confidence that what’s in the repo matches what’s running in production. That’s a solid foundation for any project.

Similar Posts