5 min read

This guide covers three ways to deploy code from GitHub to your GoZen VPS, from a manual git pull to fully automated GitHub Actions.

Method 1: Manual Git Pull (Simplest)

The most straightforward approach. SSH into your server, clone the repo, and pull updates when needed.

Initial Setup

  1. SSH into your server:

      ssh root@your-server-ip
      
  2. Generate an SSH key on the server (if you don’t have one):

      ssh-keygen -t ed25519 -C "[email protected]"
    cat ~/.ssh/id_ed25519.pub
      
  3. Add the public key to GitHub:

    • Go to your repo > Settings > Deploy keys > Add deploy key
    • Paste the public key
    • Check “Allow write access” only if the server needs to push
  4. Clone the repository:

      cd /var/www
    git clone [email protected]:yourusername/yourrepo.git yourdomain.com
      

Deploying Updates

Whenever you push changes to GitHub:

  ssh root@your-server-ip
cd /var/www/yourdomain.com
git pull origin main
  

If your project needs a build step:

  git pull origin main
npm install          # or composer install, pip install, etc.
npm run build        # if applicable
sudo systemctl restart nginx   # or your web server
  

Method 2: Webhook + Deploy Script

Automate the pull by having GitHub notify your server whenever you push.

1. Create a Deploy Script

On your server, create a script that pulls and builds:

  sudo nano /var/www/deploy.sh
  
  #!/bin/bash
cd /var/www/yourdomain.com
git pull origin main 2>&1

# Add build steps if needed
# npm install
# npm run build

# Restart services if needed
# sudo systemctl restart nginx

echo "Deployed at $(date)"
  
  chmod +x /var/www/deploy.sh
  

2. Set Up a Webhook Listener

Install a lightweight webhook server:

  sudo apt install webhook
  

Create a webhook config:

  sudo nano /etc/webhook.conf
  
  [
  {
    "id": "deploy",
    "execute-command": "/var/www/deploy.sh",
    "command-working-directory": "/var/www/yourdomain.com",
    "trigger-rule": {
      "match": {
        "type": "payload-hmac-sha256",
        "secret": "your-webhook-secret",
        "parameter": {
          "source": "header",
          "name": "X-Hub-Signature-256"
        }
      }
    }
  }
]
  

Start it as a service. The Ubuntu/Debian package includes a systemd unit that reads /etc/webhook.conf and listens on port 9000, and it keeps running after you log out and across reboots:

  sudo systemctl enable --now webhook
sudo systemctl status webhook
  

3. Proxy the Hook Through Nginx

webhook speaks plain HTTP, so don’t point GitHub at port 9000 directly. Send the hook through the Nginx site that already serves yourdomain.com over HTTPS. Add this inside its server { ... } block:

  location /hooks/ {
    proxy_pass http://127.0.0.1:9000/hooks/;
}
  
  sudo nginx -t
sudo systemctl reload nginx
  

You don’t need to open port 9000 in the firewall. GitHub reaches the hook on port 443.

4. Configure GitHub Webhook

  1. Go to your repo > Settings > Webhooks > Add webhook
  2. Payload URL: https://yourdomain.com/hooks/deploy
  3. Content type: application/json
  4. Secret: same as in your webhook config
  5. Events: “Just the push event”
  6. Click Add webhook

Now every push to your repo triggers an automatic deployment.

Method 3: GitHub Actions (Most Reliable)

GitHub Actions can SSH into your server and deploy automatically on every push. This is the most flexible approach.

1. Add Server SSH Key to GitHub Secrets

  1. On your server, create a deploy key:

      ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -C "github-actions"
    cat ~/.ssh/deploy_key.pub >> ~/.ssh/authorized_keys
    cat ~/.ssh/deploy_key   # copy the PRIVATE key
      
  2. In your GitHub repo, go to Settings > Secrets and variables > Actions

  3. Add these secrets:

    • SSH_PRIVATE_KEY: the private key content
    • SSH_HOST: your server’s IP or hostname
    • SSH_USER: the SSH username (usually root or a deploy user)

2. Create the Workflow

Create .github/workflows/deploy.yml in your repo:

  name: Deploy to Server

on:
  push:
    branches: [ main ]

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

      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/yourdomain.com
            git pull origin main
            npm ci
            npm run build
            npm prune --omit=dev
            sudo systemctl restart nginx
  

3. Push and Watch

  git add .
git commit -m "Add deployment workflow"
git push origin main
  

Go to your repo’s Actions tab to see the workflow run. Green checkmark = deployed.

Advanced: Build on GitHub, Deploy Artifacts

For projects that need a build step (Next.js, Hugo, etc.), build on GitHub and deploy only the output:

  name: Build and Deploy

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '24'

      - name: Install and Build
        run: |
          npm ci
          npm run build

      - name: Deploy to Server
        uses: burnett01/rsync-deployments@7
        with:
          switches: -avzr --delete
          path: dist/
          remote_path: /var/www/yourdomain.com/
          remote_host: ${{ secrets.SSH_HOST }}
          remote_user: ${{ secrets.SSH_USER }}
          remote_key: ${{ secrets.SSH_PRIVATE_KEY }}
  

This builds on GitHub’s infrastructure (fast and free) and only syncs the built files to your server.

Security Best Practices

  • Use a dedicated deploy user instead of root. Create a user with limited permissions:
      adduser deploy
    chown -R deploy:deploy /var/www/yourdomain.com
      
  • Use deploy keys (read-only) instead of personal access tokens
  • Never commit secrets to your repository. Use GitHub Secrets for sensitive values.
  • Restrict webhook access to GitHub’s IP ranges if possible
  • Log deployments so you can trace what was deployed and when

Which Method to Choose?

MethodBest ForComplexity
Git pullSolo developers, small projectsLow
WebhookSmall teams, simple projectsMedium
GitHub ActionsTeams, CI/CD pipelines, build stepsMedium-High

Last updated 21 Oct 2026, 00:00 +0300. history

Was this page helpful?