CI/CD Pipeline in Locally

.github_workflows_deploy.yml

name: Deploy to VPS
# Triggers a deploy whenever main is pushed to.
# Manual trigger also available via the Actions tab (workflow_dispatch).
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: SSH into VPS and run deploy script
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
port: ${{ secrets.VPS_SSH_PORT || 22 }}
script: |
cd /var/www/your-nestjs-app
./deploy.sh main
- name: Notify on failure
if: failure()
run: |
echo "Deployment failed — check the Actions log for details."
# Optional: add a Slack/Discord webhook call here too

Local_CI_CD_README.md

deploy.yml — GitHub Actions CI/CD for VPS Deployment via SSH

Triggers a deploy to your VPS every time you push to main. Works by SSHing into the server and running the deploy.sh script that's already sitting there — this workflow doesn't build or deploy anything itself, it just remotely triggers the build.

How it works

  1. On push to main (or manual trigger from the Actions tab), GitHub Actions spins up a runner.
  2. The appleboy/ssh-action step connects to your VPS over SSH using stored secrets.
  3. It runs cd /var/www/your-nestjs-app && ./deploy.sh main — the actual git pull, build, and PM2 reload all happen on the VPS, not on the GitHub runner.
  4. If the SSH step fails (bad build, script error, connection issue), the job fails and shows up red in the Actions tab.

Why deploy this way instead of building on the runner and pushing artifacts?

Simpler and matches a single-VPS setup: no artifact registry, no SCP step, no build cache to manage between two machines. The trade-off is the VPS itself does the build work, which is fine for small-to-medium apps but means a broken npm ci eats CPU on your production box for a few seconds. For heavier apps, building in CI and rsyncing a dist/ folder over is the next step up — not covered here.

Prerequisites

  • deploy.sh already present and executable on the VPS (see the companion deploy.sh gist)
  • A dedicated SSH key pair generated just for this, not your personal key:
    ssh-keygen -t ed25519 -C "github-actions-deploy" -f deploy_key
  • The public key (deploy_key.pub) added to ~/.ssh/authorized_keys on the VPS for the deploy user
  • The private key (deploy_key) added as a GitHub repo secret

Setup

In your repo: Settings → Secrets and variables → Actions → New repository secret

Secret name Value
VPS_HOST Your server IP or domain
VPS_USER The deploy user (e.g. deployer, never root)
VPS_SSH_KEY The full private key content (deploy_key)
VPS_SSH_PORT Optional — only needed if you changed SSH from port 22

Drop this file at .github/workflows/deploy.yml in your repo.

Security notes

  • Never use your root SSH key here — create a deploy-only user with a scoped key, ideally one that can only access the app directory.
  • Rotate the key if it's ever exposed (leaked log, compromised laptop, etc.) — revoke it from authorized_keys on the VPS and generate a new pair.
  • workflow_dispatch is included so you can trigger a manual redeploy from the GitHub UI without needing a new commit — useful for retrying a failed deploy.
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论