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).
- Log in to your Debian server.
- 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 - Create directories and assign permissions (Assuming you are using a standard user, such as
rootorubuntu. 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.
- 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 - 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 - Retrieve the public key:
Copy the long string of characters outputted here.cat ~/.ssh/github_deploy_key.pub - 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”. - 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.
- Create the script file:
nano /var/www/deploy.sh - Paste the following content (Using
rsyncinstead 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! ===" - Save and exit (In nano, press
Ctrl+O,Enter, thenCtrl+X). - 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.
- Generate an SSH key for GitHub Actions on the server:
ssh-keygen -t ed25519 -C "github-actions" -f ~/.ssh/gh_actions_key - Add the public key to the server’s authorized list (allowing login via this key):
cat ~/.ssh/gh_actions_key.pub >> ~/.ssh/authorized_keys - View and copy the private key (Important: Keep this secret!):
Copy the entire output (includingcat ~/.ssh/gh_actions_key-----BEGIN...and-----END...). - 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.,rootordebian).SSH_KEY: The private key content you just copied (fromgh_actions_key).
Step 5: Write the GitHub Actions Workflow File
-
In the Astro project source code on your local computer, create a directory:
.github/workflows/. -
Inside this directory, create a file named
deploy.yml. -
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 -
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:
- Visit your GitHub repository homepage.
- Click the Actions tab at the top.
- You will see a workflow named “Deploy Astro Blog” running. Click on it to view real-time logs.
- Upon successful deployment, the newly compiled Astro static files will appear in the
/var/www/blogdirectory on your server. You can configure your Nginx or Apache web root to point to/var/www/blogto 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.
- Terminate the stuck clone process and delete the residual directory:
Ctrl + C # Terminate the current stuck command sudo rm -rf /var/www/source - Edit the server’s SSH configuration file:
nano ~/.ssh/config - Modify the previous configuration to add
HostnameandPort 443:Host github.com Hostname ssh.github.com Port 443 IdentityFile ~/.ssh/github_deploy_key StrictHostKeyChecking no - Test the connection:
If the output isssh -T git@github.comHi username/repo! You've successfully authenticated..., it means SSH over port 443 is connected! - 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.
- 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
reposcope, generate, and copy this Token string (e.g.,ghp_xxxxxx). - Clean up the previously failed directory:
sudo rm -rf /var/www/source - Clone using the HTTPS link with your Token:
(Note: The# 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/sourcegit pull origin mainin subsequent scripts will also automatically use this authorized HTTPS link, without needing to modify the scripts)
🌟 Solution 3: Delegate the Build Process to GitHub Actions (Strongly Recommended Architectural Optimization)
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.)
All time is no time when it is past.
Total Posts
36
Category
5
Tag
20
Total Words
35,512
Reading Time
182 mins