Axi's Blog
为 Astro 博客添加多部署站点Blur image

前言#

最近还是在折腾博客,之前一直用的是 Vercel 部署,本身还是很优雅的,但是还是想要玩一些别的。具体来说,使用 Vercel 部署,我使用的就是 Vercel 的 Pages 功能,使用的自然是 Vercel 自己的服务器。同时,网络上几大其他的赛博菩萨,比如说 Cloudflare Pages 以及 GitHub Pages 等,都支持免费的 Pages 功能,多几个服务器来跑我的网页,而且不是同一个服务器,这样子可以避免单点故障。

Astro 本身其实支持了不同的 adapter,也可以很便捷的部署到不同的站点,所以就简单配置了一下,然后记录一下这个过程。

编辑配置文件#

首先,编辑 astro.config.mjs 文件,添加不同的 adapter 配置。

const platform = process.env.DEPLOYMENT_PLATFORM || 'vercel'
const isCloudflare = platform === 'cloudflare'
const isGithubPages = platform === 'github'

export default defineConfig({
  site: isGithubPages ? 'https://axi404.github.io/' : (isCloudflare ? 'https://axi-blog.pages.dev/' : 'https://axi404.top/'),
  trailingSlash: 'never',
  adapter: isGithubPages ? undefined : (isCloudflare ? cloudflare() : vercel()),
  output: isGithubPages ? 'static' : (isCloudflare ? 'static' : 'server'),
})
js

整体的思路就是根据环境变量来判断当前的部署平台,然后根据不同的平台来选择不同的 adapter,然后默认的是使用 Vercel。在这里因为 Github 和 Cloudflare 都是在薅羊毛,没有进行氪金,所以说都是使用的静态站点,服务端渲染这种特性毕竟本来也不是必须得。

关于如何使用 Vercel 部署站点在 之前的文章 中已经介绍过了,这里就不再赘述了。主要介绍剩下的两种的过程。

Cloudflare Pages 的部署过程其实也有类似的博客,也就是我部署 R2 图床的博客 的那一篇,本身也就是直接绑定之后部署就好,之后每一次 Push 之后就会自动部署。

至于对于 Github Pages,其实就是需要写一个 Github Action 的文件,放到 .github/workflows/deploy.yml 中,然后每一次 Push 之后就会通过运行这个 Action 来部署。这一步其实直接交给 GPT 来做就好了,我的一个特殊的点在于我博客的仓库是一个 private 仓库,并且不是 axi404.github.io 的名称,因此需要在 Axi-Blog 的仓库中运行 Github Action,进行 build,并且将 build 的结果推送到 axi404.github.io 的仓库中。

简单介绍下这个方案,大概就是需要先创建一个 Token,打开 Github 的创建 Token 的 页面,然后在 Repository access 中选择 axi404.github.io 的仓库,仓库权限中给 Content 的 read and write,之后在 Axi-Blog 的仓库的 settings 中选择 Secrets and variables 中的 Actions 中添加一个 Secret,名字为 PERSONAL_TOKEN,值为刚刚创建的 Token。

文件内容如下:

name: Deploy to Axi404.github.io

on:
  push:
    branches:
      - main

permissions:
  contents: write

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v3

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

      - name: Setup Bun
        uses: oven-sh/setup-bun@v1
        with:
          bun-version: latest

      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: ~/.bun/install/cache
          key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
          restore-keys: |
            ${{ runner.os }}-bun-

      - name: Install dependencies
        run: bun i

      - name: Set environment variables
        run: |
          echo "DEPLOYMENT_PLATFORM=github" >> $GITHUB_ENV

      - name: Build site
        run: bun run build:github

      - name: Deploy to Axi404.github.io
        uses: peaceiris/actions-gh-pages@v3
        with:
          personal_token: ${{ secrets.PERSONAL_TOKEN }}
          external_repository: Axi404/axi404.github.io
          publish_branch: main
          publish_dir: ./dist
          force_orphan: true
yml

即可。

服务器部署#

因为折腾了服务器,所以说也搞了个服务器部署,包括设置 Hook,以及设置反向代理。

首先基础配置 Git 跳过,之后安装 nginx 并且开放防火墙:

sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
sudo ufw allow 80
sudo ufw allow 443
sudo ufw reload
bash

然后 git clone 你的仓库,并且安装相关依赖。

之后是关键,首先配置反向代理:

server {
    listen 80;
    server_name blog.axi404.top;

    root /var/www/blog;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
nginx

在 Cloudflare 添加一个 A,内容是 blog,指向服务器 IP,关闭代理。

之后获得 https 证书:

sudo certbot --nginx -d blog.axi404.top --non-interactive --agree-tos -m [email protected]
bash

之后配置 Hook,在服务器上创建一个文件 deploy.sh,并且创建 log 文件夹,mkdir -p /var/log/blog,脚本内容如下:

deploy.sh
#!/bin/bash
LOG_DIR="/var/log/blog"
LOG_FILE="$LOG_DIR/deploy_$(date '+%Y-%m-%d_%H-%M-%S').log"

echo "$(date '+%Y-%m-%d %H:%M:%S') - deploy.sh started" | tee -a "$LOG_FILE"

cd /root/Axi-Blog || {
  echo "Failed to cd to /root/Axi-Blog" | tee -a "$LOG_FILE"
  exit 1
}

echo "git pull origin main ..." | tee -a "$LOG_FILE"
git pull origin main >> "$LOG_FILE" 2>&1

echo "Start build (try 1) ..." | tee -a "$LOG_FILE"
if ! bun run build >> "$LOG_FILE" 2>&1; then
  echo "Build failed, retrying (try 2) ..." | tee -a "$LOG_FILE"
  if ! bun run build >> "$LOG_FILE" 2>&1; then
    echo "Build failed twice, aborting." | tee -a "$LOG_FILE"
    exit 1
  fi
fi

echo "Copying files ..." | tee -a "$LOG_FILE"
rm -rf /var/www/blog/* >> "$LOG_FILE" 2>&1
cp -r dist/* /var/www/blog/ >> "$LOG_FILE" 2>&1
chown -R www-data:www-data /var/www/blog >> "$LOG_FILE" 2>&1

echo "$(date '+%Y-%m-%d %H:%M:%S') - deploy.sh finished" | tee -a "$LOG_FILE"
bash

之后写一个 hook,效果是每次 push 之后,只要 fetch,就执行部署。

首先创建:

mkdir ~/deploy-hook
cd ~/deploy-hook
npm init -y
npm install express
bash

之后创建 Hook:

hook.js
// hook.js
const express = require('express');
const { exec } = require('child_process');
const app = express();

app.post('/hook', (req, res) => {
    res.send('Deploying...');

    exec('bash /root/deploy.sh', (err, stdout, stderr) => {
        if (err) {
            console.error('❌ Error:', stderr);
        } else {
            console.log('✅ Output:\n', stdout);
        }
    });
});

app.listen(XXXX, () => {
    console.log('🚀 Webhook listening on http://localhost:XXXX/hook');
});
js

将上述 XXXX 替换为你的端口,然后运行 node hook.js & 即可。别忘了开放这个端口的防火墙。

接下来在 github 的 workflows 里面加一行,curl -X POST http://XXX.XXX.XXX.XXX:XXXX/hook,即可。

结语#

内容反正大概就是这样,也不是很难,最后喜提两个新域名,一个是 axi-blog.pages.dev,一个是 axi404.github.io,前者是 Cloudflare Pages 的,后者是 Github Pages 的。

最后加了一个服务器,可以用 blog.axi404.top 访问。

为 Astro 博客添加多部署站点
https://axi404.top/en/blog/astro-multi-pages
Author 阿汐
Published at July 7, 2025
Comment seems to stuck. Try to refresh?✨