Automate Astro Deployment to a Personal Server via GitHub Actions

· Chinese version

For independent developers, “mental friction” during the deployment process should be as close to zero as possible.

This website is built using the Astro framework. To efficiently deliver local code to a personal server, utilizing GitHub Actions in combination with rsync/SSH is currently the most standard and frictionless industry-grade practice.

Once this closed-loop system is established, you only need to focus on local content creation. A minimalist git push takes over all subsequent tasks: it triggers the cloud-based automated build (npm run build) and securely, precisely synchronizes the compiled dist/ directory to the server.

Below is a minimum viable configuration guide, stripped of redundancy, covering the core steps from server configuration to automated deployment.


I. Server Side: Configure Dedicated Keys and Harden Permissions

To enable GitHub Actions to automatically push to your server, we need to establish a passwordless trust mechanism based on RSA keys. Please execute the following commands sequentially in your server terminal:

1. Generate a Dedicated Deployment Key Pair

Generate an exclusive key (do not set a passphrase, simply press Enter all the way through):

ssh-keygen -m PEM -t rsa -b 4096 -C "github-actions-deploy" -f ~/.ssh/github_actions

2. Inject Public Key into Whitelist

Append the generated public key (.pub) to the server’s SSH authorization list:

cat ~/.ssh/github_actions.pub >> ~/.ssh/authorized_keys

3. Harden Directory Permissions (High-Frequency Error Point)

The Linux sshd daemon maintains a strict security baseline. If file permissions are overly exposed, it will silently reject all key-based connections. You must strictly execute the following overwrite commands:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

4. Extract Private Key Credentials

Print and copy the entire contents of the private key in the terminal (ensure you include the -----BEGIN... and -----END... headers and footers). Prepare to inject this into GitHub:

cat ~/.ssh/github_actions

II. GitHub Side: Configure Secret Environment Variables (Secrets)

Server login credentials must never be hardcoded into your repository. Navigate to your GitHub repository’s main page and go to: Settings -> Secrets and variables -> Actions -> New repository secret

Create the following 3 secret variables sequentially:

  • SERVER_HOST: Your server’s public IP address.
  • SERVER_USER: The login username for your server (e.g., root, ubuntu).
  • SERVER_SSH_KEY: The complete private key content you just copied.

III. Codebase: Orchestrate the Automation Workflow

In the root directory of your Astro project, create the file .github/workflows/deploy.yml. This script will intercept every push request to the main branch and automatically execute the deployment task.

name: 🚀 Build and Deploy Astro

on:
  push:
    branches:
      - main

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

    steps:
      - name: 🛎️ Checkout Code
        uses: actions/checkout@v4

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

      - name: 📦 Install Dependencies
        run: npm ci

      - name: 🛠️ Build Astro Site
        run: npm run build

      - name: ☁️ Deploy to Server
        uses: easingthemes/ssh-deploy@main
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
          # Enable --delete to ensure remote obsolete
          # files are automatically cleaned up
          ARGS: "-rlgoDzvc -i --delete"
          # Astro's default compiled output directory
          SOURCE: "dist/"
          REMOTE_HOST: ${{ secrets.SERVER_HOST }}
          REMOTE_USER: ${{ secrets.SERVER_USER }}
          # ⚠️ Replace with the actual absolute path
          # of the website on your server
          TARGET: "/var/www/your-site"

Once all configurations are complete, push your code to the main branch. Check the Actions panel on GitHub; if the build task displays a green checkmark, it signifies that the entire automated deployment pipeline has been successfully closed.