To achieve automatic deployment, the safest and most widely adopted industry approach is: Utilizing GitHub Actions to monitor push events, which then trigger a deployment script on the server via SSH.

This method eliminates the need to expose extra ports on your server. All that is required is an environment equipped with Node.js and Git. Below is a detailed, step-by-step tutorial:

Step 1: Server Environment Preparation

First, ensure that your Debian server has the necessary environment installed (Git, Node.js). Astro requires a relatively recent version of Node.js (v20 is recommended).

  1. Log in to your Debian server.
  2. Install Node.js and related tools:
    sudo apt update
    sudo apt install -y curl git rsync
    # Install Node.js v20
    curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
    sudo apt install -y nodejs
  3. Create directories and assign permissions (Assuming you are using a standard user, such as root or ubuntu. It’s recommended not to run services as root. Here, we assume your username is $USER):
    sudo mkdir -p /var/www/source
    sudo mkdir -p /var/www/blog
    sudo chown -R $USER:$USER /var/www/source
    sudo chown -R $USER:$USER /var/www/blog

Step 2: Configure Server Permissions for Pulling Private Repositories

Because your repository is private, the Debian server requires authorization to execute git pull. We will utilize a Deploy Key to achieve this.

  1. Generate an SSH key on your server (simply press Enter for all prompts):
    ssh-keygen -t ed25519 -C "debian-server" -f ~/.ssh/github_deploy_key
  2. Configure the SSH client to instruct GitHub to use this key:
    cat << 'EOF' >> ~/.ssh/config
    Host github.com
        HostName github.com
        IdentityFile ~/.ssh/github_deploy_key
        StrictHostKeyChecking no
    EOF
    chmod 600 ~/.ssh/config
  3. Retrieve the public key:
    cat ~/.ssh/github_deploy_key.pub
    Copy the long string of characters outputted here.
  4. Add the key to your GitHub repository: Navigate to your GitHub webpage -> Access the Private repository -> Settings -> Deploy keys -> Add deploy key. Paste the copied public key, provide a title (e.g., Debian Server), and do not check “Allow write access”.
  5. Perform the initial clone on the server:
    # Replace the git@github.com... address below with your repository's SSH clone URL
    git clone git@github.com:your_username/your_repository.git /var/www/source

Step 3: Write the Automatic Deployment Script

Create a script on the server responsible for pulling code, installing dependencies, building the project, and transferring files.

  1. Create the script file:
    nano /var/www/deploy.sh
  2. Paste the following content (Using rsync instead of standard move or copy ensures seamless file replacement without causing website downtime):
    #!/bin/bash
    # Exit the script if any command fails
    set -e 
    
    echo "=== Starting Astro Blog Deployment ==="
    
    # 1. Navigate to the source code directory
    cd /var/www/source
    
    # 2. Pull the latest code (Assuming your main branch is named 'main')
    echo "-> Pulling latest code..."
    git pull origin main
    
    # 3. Install NPM dependencies
    echo "-> Installing dependencies..."
    npm install
    
    # 4. Build Astro
    echo "-> Building project..."
    npm run build
    
    # 5. Sync the dist directory contents to the target directory
    # Using rsync --delete ensures the target directory perfectly mirrors the dist directory (automatically deleting old files)
    echo "-> Syncing files to /var/www/blog..."
    rsync -av --delete dist/ /var/www/blog/
    
    echo "=== Deployment Completed! ==="
  3. Save and exit (In nano, press Ctrl+O, Enter, then Ctrl+X).
  4. Grant execution permissions to the script:
    chmod +x /var/www/deploy.sh

Step 4: Configure GitHub Actions to Trigger the Script via SSH

Now we need to configure the GitHub repository to automatically log into your server and run the /var/www/deploy.sh script whenever a push occurs.

  1. Generate an SSH key for GitHub Actions on the server:
    ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/gh_actions_key
  2. Add the public key to the server’s authorized list (allowing login via this key):
    cat ~/.ssh/gh_actions_key.pub >> ~/.ssh/authorized_keys
  3. View and copy the private key (Important: Keep this secret!):
    cat ~/.ssh/gh_actions_key
    Copy the entire output (including -----BEGIN... and -----END...).
  4. Configure Secrets in GitHub: Navigate to your GitHub repository -> Settings -> Secrets and variables -> Actions -> New repository secret. Add the following three Secrets sequentially:
    • HOST: Your Debian server’s public IP address.
    • USERNAME: The username used to log into your server (the user you ran the commands with, e.g., root or debian).
    • SSH_KEY: The private key content you just copied (from gh_actions_key).

Step 5: Write the GitHub Actions Workflow File

  1. In the Astro project source code on your local computer, create a directory: .github/workflows/.

  2. Inside this directory, create a file named deploy.yml.

  3. Fill in the following content:

    name: Deploy Astro Blog
    
    # Trigger condition: Triggers when pushing to the main branch (change this if using 'master')
    on:
      push:
        branches:
          - main
    
    jobs:
      deploy:
        runs-on: ubuntu-latest
    
        steps:
          - name: Execute Server Deployment Script
            uses: appleboy/ssh-action@v1.0.3
            with:
              host: ${{ secrets.HOST }}
              username: ${{ secrets.USERNAME }}
              key: ${{ secrets.SSH_KEY }}
              script: |
                /var/www/deploy.sh
  4. Commit and push to GitHub:

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

Testing and Verification

After completing the steps above, the automated workflow will trigger every time you push local code to GitHub:

  1. Visit your GitHub repository homepage.
  2. Click the Actions tab at the top.
  3. You will see a workflow named “Deploy Astro Blog” running. Click on it to view real-time logs.
  4. Upon successful deployment, the newly compiled Astro static files will appear in the /var/www/blog directory on your server. You can configure your Nginx or Apache web root to point to /var/www/blog to serve your site.

PS: What if Outgoing Port 22 is Blocked on the Server?

It is a very common situation for outgoing port 22 on a server to be blocked (often seen in default security group settings of some cloud providers or company intranets). Because the default Git SSH protocol (git@github.com:...) operates over port 22, it will stay stuck until it times out.

Here are three solutions. I highly recommend Solution 3 (it not only resolves the port issue but is also the industry-standard modern frontend deployment method).


Solution 1: Route SSH over Port 443 (Fastest and Most Direct Fix)

GitHub officially supports transmitting SSH traffic via HTTPS over port 443. You only need to slightly modify the SSH configuration file on your server.

  1. Terminate the stuck clone process and delete the residual directory:
    Ctrl + C  # Terminate the current stuck command
    sudo rm -rf /var/www/source
  2. Edit the server’s SSH configuration file:
    nano ~/.ssh/config
  3. Modify the previous configuration to add Hostname and Port 443:
    Host github.com
        Hostname ssh.github.com
        Port 443
        IdentityFile ~/.ssh/github_deploy_key
        StrictHostKeyChecking no
  4. Test the connection:
    ssh -T git@github.com
    If the output is Hi username/repo! You've successfully authenticated..., it means SSH over port 443 is connected!
  5. Re-execute the clone command:
    git clone git@github.com:your_username/your_repository.git /var/www/source

Solution 2: Switch to HTTPS Clone + Personal Access Token (PAT)

If your server blocks even SSH traffic on port 443 (for instance, due to strict deep packet inspection firewalls), you can completely abandon SSH and switch to pure HTTPS for pulling code.

  1. Generate a Token (Personal Access Token) on GitHub: Go to GitHub webpage -> Profile in the top right -> Settings -> Developer settings (bottom left) -> Personal access tokens -> Tokens (classic). Click Generate new token, check the repo scope, generate, and copy this Token string (e.g., ghp_xxxxxx).
  2. Clean up the previously failed directory:
    sudo rm -rf /var/www/source
  3. Clone using the HTTPS link with your Token:
    # Format: https://your_github_username:your_token@github.com/your_username/your_repository.git
    git clone https://your_username:ghp_xxxxxx@github.com/your_username/your_repository.git /var/www/source
    (Note: The git pull origin main in subsequent scripts will also automatically use this authorized HTTPS link, without needing to modify the scripts)

If outgoing code pulls are restricted, we actually do not need to pull code and build on the server at all!

A better approach is: Let GitHub’s free servers (GitHub Actions) handle npm install and npm run build. Once compiled, GitHub generates the final dist static folder. Then, GitHub Actions can use SSH (inbound traffic, given your server has an SSH port open for external access) to directly push the finished web page files from dist to the /var/www/blog directory on your server.

Why recommend this solution?

  • Bypass Outgoing Limitations: Your server doesn’t need to access GitHub; GitHub proactively sends the compiled files to it.
  • Save Server Resources: The server doesn’t need to install Node.js, nor does it consume CPU processing power to compile Astro.
  • More Secure: The server doesn’t need to store a GitHub Deploy Key or the source code.

If you’d like to use Solution 3, follow these steps:

1. Server-side cleanup: You no longer need /var/www/source, nor the deployment script. Just ensure the target folder exists and permissions are correct:

sudo mkdir -p /var/www/blog
sudo chown -R $USER:$USER /var/www/blog

2. Modify deploy.yml on your local computer (replaces Step 5 from the previous tutorial): Modify the content of .github/workflows/deploy.yml in your local Astro project as follows:

name: Deploy Astro Blog

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      # 1. Checkout Code
      - name: Checkout Code
        uses: actions/checkout@v4

      # 2. Setup Node.js Environment
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      # 3. Install dependencies & Build Astro
      - name: Install dependencies & Build
        run: |
          npm ci
          npm run build

      # 4. Push the compiled dist folder to Debian Server
      - name: Deploy to Server via rsync
        uses: easingthemes/ssh-deploy@v5.1.0
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
          REMOTE_HOST: ${{ secrets.HOST }}
          REMOTE_USER: ${{ secrets.USERNAME }}
          # Source directory is the dist folder on Github Actions
          SOURCE: "dist/"
          # Target directory is the blog folder on the server
          TARGET: "/var/www/blog/"
          # Automatically clean up old files on the server that were deleted in dist
          ARGS: "-avzr --delete"

3. Push to GitHub: Push this newly updated .yml file to GitHub, and GitHub Actions will automatically use its powerful computing resources to bundle and deploy pure static files to your /var/www/blog directory.

(Note: If you adopt Solution 3, make sure you have already configured HOST, USERNAME, and SSH_KEY in GitHub Secrets, as seen in Step 4 of the previous response.)

Deploy Astro Blog via GitHub

Author

Shayne Wong

Publish Date

02 - 20 - 2026

Last Modified

02 - 21 - 2026

License

Shayne Wong

Avatar
Shayne Wong

All time is no time when it is past.

Friend Links
Blog Statistics

Total Posts

36

Category

5

Tag

20

Total Words

35,512

Reading Time

182 mins