Post

VPS setup

VPS setup

Perfect — we can make a fully generic GitHub Actions → VPS deployment guide that works for any project type. This will give you a reference for future projects, and you can just plug in a project-specific deploy.sh and optionally generate a workflow YAML using an LLM.

Here’s the generic guide:


Generic GitHub Actions → VPS Deployment Guide


Step 1 — Generate SSH Key for GitHub Actions

On your local machine:

1
ssh-keygen -t rsa -b 4096 -f deploy_key -C "github-action-deploy"

This creates:

  • deploy_key → private key (keep secret)
  • deploy_key.pub → public key

Do not upload the private key publicly.


Step 2 — Add Public Key to VPS

  1. Copy the public key:
1
2
type deploy_key.pub  # Windows
cat deploy_key.pub   # Linux/macOS
  1. On your VPS, add it to the deploy user’s authorized keys:
1
2
3
4
mkdir -p ~/.ssh
echo "PASTE_PUBLIC_KEY_HERE" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
  1. Test SSH access with:
1
ssh -i "deploy_key" user@vps.example.com

Step 3 — Add GitHub Secrets

Go to GitHub → Repo → Settings → Secrets and Variables → Actions → New repository secret:

Secret NameValue
DEPLOY_SSH_KEYcontents of deploy_key (private key)
VPS_HOSTVPS IP or domain
VPS_USERSSH username
VPS_PORTSSH port (default: 22)
KNOWN_HOSTShost key (see next step)

Step 4 — Generate known_hosts

1
ssh-keyscan -t rsa -p 22 vps.example.com > known_hosts
  • Open known_hosts and copy the line starting with vps.example.com ssh-rsa ...
  • Add it to GitHub secrets as KNOWN_HOSTS.

Step 5 — Prepare Folder on VPS

1
2
ssh -i "deploy_key" user@vps.example.com
mkdir -p ~/Projects/my_project
  • Replace ~/Projects/my_project with the folder where you want your project deployed.

Step 6 — Create Generic deploy.sh Script

1
nano ~/Projects/my_project/deploy.sh

Example generic script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env bash
set -e

echo "🚀 Starting deployment..."

cd ~/Projects/my_project

# --- Run project-specific deploy commands ---
# Examples:
# - Install dependencies
# - Build project
# - Restart service
# These are placeholders — customize per project

echo "✅ Deployment completed successfully!"

Make it executable:

1
chmod +x ~/Projects/my_project/deploy.sh

In future projects, replace the placeholders with project-specific commands (Node, Python, Docker, etc.).


Step 7 — Install rsync on VPS

1
2
apt update
apt install -y rsync

Required for GitHub Actions to upload files.


Step 8 — Create GitHub Actions Workflow

  1. Create file:
1
2
mkdir -p .github/workflows
nano .github/workflows/deploy.yml
  1. Paste generic workflow:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
name: Deploy to VPS

on:
  push:
    branches: [ "main" ]  # change branch if needed

jobs:
  deploy:
    runs-on: ubuntu-latest

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

      - name: Start SSH agent and add key
        uses: webfactory/ssh-agent@v0.9.1
        with:
          ssh-private-key: $

      - name: Add known_hosts
        run: |
          mkdir -p ~/.ssh
          echo "$" > ~/.ssh/known_hosts
          chmod 644 ~/.ssh/known_hosts

      - name: Copy files to VPS
        run: |
          rsync -avz --delete --exclude='.git' ./ $@$:~/Projects/my_project/
        env:
          RSYNC_RSH: "ssh -p $ -o StrictHostKeyChecking=yes"

      - name: Run remote deploy script
        run: |
          ssh -p $ $@$ "cd ~/Projects/my_project && ./deploy.sh || echo 'No deploy.sh found'"
  1. Commit and push:
1
2
3
git add .github/workflows/deploy.yml
git commit -m "Add generic deploy workflow"
git push origin main

Step 9 — Test Deployment

  1. Go to GitHub → Actions tab → confirm workflow runs automatically on push.
  2. Check logs:

    • rsync uploads files
    • deploy.sh executes on VPS

Step 10 — Customizing for Future Projects

  1. Replace deploy.sh contents with project-specific commands:

    • Node.js: npm install, npm run build, pm2 restart
    • Python: pip install -r requirements.txt, systemctl restart service
    • Docker: docker-compose pull && docker-compose up -d
  2. Update workflow YAML only if:

    • Project folder changes
    • You need extra environment variables
    • You want additional steps (tests, linting, etc.)

Step 11 — Optional: PM2 or systemd service

  • For long-running apps (Node, Python), configure PM2 or systemd to restart your app after reboot.
  • Example PM2 setup:
1
2
3
4
npm install -g pm2
pm2 start server.js --name my_project
pm2 startup systemd
pm2 save

Step 12 — Troubleshooting

ErrorSolution
Permission denied (publickey)Check DEPLOY_SSH_KEY and authorized_keys on VPS
Host key verification failedVerify KNOWN_HOSTS matches ssh-keyscan output
rsync: command not foundInstall rsync on VPS: apt install -y rsync
deploy.sh not foundEnsure it exists in the VPS folder and is executable (chmod +x deploy.sh)

This post is licensed under CC BY 4.0 by the author.