从 0 开始:在阿里云 ECS 上部署 Astro 博客,并用 GitHub Actions 自动发布

3043 字
15 分钟
从 0 开始:在阿里云 ECS 上部署 Astro 博客,并用 GitHub Actions 自动发布

最近把个人博客从本地开发环境迁移到了阿里云 ECS。服务器是全新实例,系统为 Ubuntu 24.04.4 LTS。这篇文章完整记录了从一台空白 ECS 开始,到博客可通过域名访问、启用 HTTPS,并且支持 GitHub Actions 自动部署的整个过程。

这篇文章适合以下场景:

  • 你有一台全新的阿里云 ECS
  • 你想部署的是 Astro 静态博客
  • 你已经有自己的域名
  • 你希望博客支持 HTTPS
  • 你希望以后写完文章后,执行 git push 就能自动上线

本文最终实现的架构如下:

  • 本地电脑负责写博客和提交代码
  • GitHub Actions 自动安装依赖、构建 Astro 项目
  • 构建产物 dist/ 自动上传到 ECS
  • ECS 上的 Nginx 直接托管静态文件
  • 域名解析到 ECS 公网 IP
  • 网站通过 HTTPS 对外提供服务

一、为什么选择这种部署方式#

Astro 博客本质上非常适合静态部署。对于个人博客来说,没有必要在服务器上长期运行 Node 服务,更没必要把 ECS 当构建机。

更稳妥的做法是:

  • 本地或 GitHub Actions 负责构建
  • 服务器只负责托管静态文件
  • Nginx 负责访问入口和 HTTPS
  • GitHub Actions 负责自动发布

这种方式有几个明显优点:

第一,服务器压力小。 第二,架构简单,出问题时容易排查。 第三,CI/CD 清晰,后续维护成本很低。 第四,适合 Astro、Vite 一类静态站点项目。


二、准备工作#

开始之前,需要准备好以下几样东西:

  • 一台阿里云 ECS,系统为 Ubuntu 24.04
  • ECS 拥有公网 IP
  • 一个已经注册好的域名
  • GitHub 仓库
  • 本地已经有 Astro 项目,或者准备新建一个
  • 一个可用的 SSL 证书(本文采用手动部署证书,而不是 Certbot)

如果你的 ECS 在中国大陆节点,网站正式上线前还需要关注备案要求。


三、服务器基础初始化#

先通过 SSH 登录 ECS。

Terminal window
ssh root@你的ECS公网IP

登录后先更新系统,并安装基础软件:

Terminal window
apt update && apt upgrade -y
apt install -y nginx git curl unzip ufw

如果你希望启用 Ubuntu 防火墙,可以继续执行:

Terminal window
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status

此外,在阿里云 ECS 控制台里,还需要确认安全组已开放以下端口:

  • 22(SSH)
  • 80(HTTP)
  • 443(HTTPS)

如果安全组没有开放 80/443,即便 Nginx 配好了,外部也无法访问网站。


四、配置域名解析#

进入域名的 DNS 管理后台,添加两条 A 记录:

主域名解析:

  • 记录类型:A
  • 主机记录:@
  • 记录值:ECS 公网 IP

www 子域名解析:

  • 记录类型:A
  • 主机记录:www
  • 记录值:ECS 公网 IP

完成后可以在本地简单验证一下:

Terminal window
ping yourdomain.com
ping www.yourdomain.com

如果解析结果已经指向 ECS 公网 IP,就说明域名已经生效。


五、准备博客部署目录#

在服务器上创建博客目录:

Terminal window
mkdir -p /var/www/astro-blog
chown -R www-data:www-data /var/www/astro-blog
chmod -R 755 /var/www/astro-blog

为了便于确认 Nginx 配置是否成功,可以先放一个临时测试页面:

Terminal window
cat > /var/www/astro-blog/index.html <<'EOF'
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Astro Blog Ready</title>
</head>
<body>
<h1>Astro Blog 部署目录已就绪</h1>
</body>
</html>
EOF

六、配置 Nginx 托管站点#

/etc/nginx/sites-available/ 下创建站点配置文件:

Terminal window
cat > /etc/nginx/sites-available/astro-blog <<'EOF'
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/astro-blog;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
EOF

启用站点,并关闭默认站点:

Terminal window
ln -s /etc/nginx/sites-available/astro-blog /etc/nginx/sites-enabled/astro-blog
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl reload nginx

如果 nginx -t 输出 syntax is oktest is successful,说明配置语法没有问题。

此时访问:

  • http://yourdomain.com
  • http://www.yourdomain.com

如果能看到测试页,说明:

  • 域名解析正常
  • 80 端口正常
  • Nginx 配置正常
  • 站点目录可访问

七、创建或准备 Astro 项目#

如果你还没有 Astro 项目,可以在本地创建:

Terminal window
npm create astro@latest

如果你使用的是现成主题,比如 AstroPaper,也可以直接基于主题模板初始化。

进入项目目录后,安装依赖并本地运行:

Terminal window
npm install
npm run dev

本地确认页面正常后,执行生产构建:

Terminal window
npm run build

构建成功后,静态文件会输出到 dist/ 目录。

如果你的项目使用的是 pnpm,而不是 npm,那么命令应该改成:

Terminal window
pnpm install
pnpm build

八、Astro 项目的关键配置#

部署到正式域名后,建议确认 astro.config.mjs 或主题配置文件里已经写入正确的生产环境地址。

例如:

import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://yourdomain.com'
});

如果你使用 AstroPaper 之类的主题,还要修改主题自己的站点配置,例如:

  • 网站标题
  • 作者名
  • 站点描述
  • 正式域名
  • 社交链接
  • 时区
  • 文章编辑地址

以 AstroPaper 为例,重点文件通常是:

  • src/config.ts
  • src/constants.ts

尤其要注意把正式域名填进去,否则 canonical URL、社交分享链接、SEO 信息可能都会不正确。


九、第一次手动部署 Astro 构建产物#

在启用自动化部署前,建议先手动部署一次,确保服务器侧配置没问题。

本地构建:

Terminal window
npm run build

或者:

Terminal window
pnpm build

然后通过 rsyncscpdist/ 上传到 ECS。

例如:

Terminal window
rsync -avz --delete dist/ root@你的ECS公网IP:/var/www/astro-blog/

上传完成后,再次访问域名。 如果已经能看到 Astro 首页,而不是之前的测试页,说明静态文件部署路径是正确的。


十、手动部署 SSL 证书#

本文使用的是手动申请的 SSL 证书,所以不使用 Certbot,而是手动把证书部署到 Nginx。

通常证书包里会有:

  • 证书文件,例如 fullchain.pemyourdomain.pem
  • 私钥文件,例如 yourdomain.key

先在 ECS 上创建证书目录:

Terminal window
mkdir -p /etc/nginx/ssl
chmod 700 /etc/nginx/ssl

把证书文件上传到这个目录中,例如:

  • /etc/nginx/ssl/fullchain.pem
  • /etc/nginx/ssl/yourdomain.key

然后收紧权限:

Terminal window
chmod 600 /etc/nginx/ssl/yourdomain.key
chmod 644 /etc/nginx/ssl/fullchain.pem

接着修改 Nginx 配置,让 80 跳转到 443,并配置 HTTPS。

Terminal window
cat > /etc/nginx/sites-available/astro-blog <<'EOF'
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name yourdomain.com www.yourdomain.com;
root /var/www/astro-blog;
index index.html;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
location / {
try_files $uri $uri/ /index.html;
}
}
EOF

然后测试并重载 Nginx:

Terminal window
nginx -t
systemctl reload nginx

此时访问:

  • https://yourdomain.com
  • https://www.yourdomain.com

如果能正常打开,说明 HTTPS 部署完成。


十一、为 GitHub Actions 准备部署账号#

为了安全起见,不建议让 GitHub Actions 直接使用 root 用户登录 ECS。更合理的做法是创建一个专门的部署用户,比如 deploy

Terminal window
adduser deploy
usermod -aG www-data deploy
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chown -R deploy:deploy /home/deploy/.ssh

然后需要给这个用户配置 SSH 公钥登录。


十二、生成 GitHub Actions 专用 SSH 密钥#

在本地 Windows 电脑上,可以使用如下命令生成一对密钥。

Terminal window
mkdir %USERPROFILE%\.ssh
ssh-keygen -t ed25519 -C "github-actions-deploy" -f "%USERPROFILE%\.ssh\github_actions_astro"

会生成两个文件:

  • 私钥:C:\Users\你的用户名\.ssh\github_actions_astro
  • 公钥:C:\Users\你的用户名\.ssh\github_actions_astro.pub

查看公钥内容:

Terminal window
type %USERPROFILE%\.ssh\github_actions_astro.pub

会输出类似这样的一整行:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... github-actions-deploy

把这一整行写入服务器上的:

Terminal window
/home/deploy/.ssh/authorized_keys

可以用 nano 打开:

Terminal window
nano /home/deploy/.ssh/authorized_keys

粘贴公钥后保存,再执行:

Terminal window
chmod 600 /home/deploy/.ssh/authorized_keys
chown deploy:deploy /home/deploy/.ssh/authorized_keys

一定要注意,authorized_keys 中写入的是:

  • github_actions_astro.pub 的内容

不是私钥文件内容。

另外,公钥开头必须是:

ssh-ed25519

如果写成了 sh-ed25519 之类的错误格式,SSH 会直接认证失败。


十三、先在本地测试 SSH 是否打通#

在正式跑 GitHub Actions 之前,建议本地先测试一次 SSH 登录。

Terminal window
ssh -i "%USERPROFILE%\.ssh\github_actions_astro" deploy@你的ECS公网IP

如果能成功登录,说明:

  • 本地私钥没问题
  • 服务器上的公钥没问题
  • 用户名正确
  • 权限正确

只有这一步先打通,GitHub Actions 的远程上传才有成功的基础。


十四、配置 GitHub 仓库 Secrets#

进入 GitHub 仓库:

Settings -> Secrets and variables -> Actions

添加以下几个 Secrets:

  • ECS_HOST:你的 ECS 公网 IP
  • ECS_PORT22
  • ECS_USERdeploy
  • ECS_SSH_KEY:私钥文件 github_actions_astro 的完整内容

注意,ECS_SSH_KEY 填的是私钥全文,内容会包含:

-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----

不能把 .pub 文件内容填进这个 Secret。


十五、编写 GitHub Actions 自动部署 workflow#

如果你的 Astro 项目使用的是 pnpm,推荐使用下面这份 workflow。

创建文件:

.github/workflows/deploy.yml

内容如下:

name: Deploy Astro to ECS
on:
push:
branches:
- main
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.14.4
- name: Setup Node
uses: actions/setup-node@v5
with:
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build Astro
run: pnpm build
- name: Upload dist to ECS
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.ECS_HOST }}
username: ${{ secrets.ECS_USER }}
key: ${{ secrets.ECS_SSH_KEY }}
port: ${{ secrets.ECS_PORT }}
source: "dist/*"
target: /var/www/astro-blog
strip_components: 1
overwrite: true
- name: Fix permissions
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.ECS_HOST }}
username: ${{ secrets.ECS_USER }}
key: ${{ secrets.ECS_SSH_KEY }}
port: ${{ secrets.ECS_PORT }}
script: |
chown -R deploy:www-data /var/www/astro-blog
find /var/www/astro-blog -type d -exec chmod 775 {} \;
find /var/www/astro-blog -type f -exec chmod 664 {} \;

如果你项目使用的是 npm,就把 pnpm 相关命令替换成 npm 即可。


十六、pnpm 项目常见问题#

如果你使用的是 pnpm 项目,仓库根目录里必须提交:

pnpm-lock.yaml

否则 GitHub Actions 安装依赖时会失败。

另外,如果 package.json 中写了:

"packageManager": "pnpm@9.14.4"

那么 pnpm/action-setup 里也要保持同样版本,不能写成 10,否则会报版本冲突错误。

换句话说,workflow 里的 pnpm 版本必须和项目自己声明的版本一致。


十七、触发自动部署#

把 workflow 提交到仓库后,执行:

Terminal window
git add .
git commit -m "add deploy workflow"
git push

之后进入 GitHub 仓库的 Actions 页面,就能看到自动部署任务开始执行。

成功后,流程会是:

  • 拉取仓库代码
  • 安装 Node 和 pnpm
  • 安装依赖
  • 构建 Astro
  • dist/ 上传到 ECS
  • 修复目录权限
  • 网站自动更新

以后每次写完文章,只需要:

Terminal window
git add .
git commit -m "publish new post"
git push

新的内容就会自动部署上线。


十八、常见问题排查#

整个部署过程中,最容易踩到的坑主要有以下几类。

1. GitHub Actions 无法通过 SSH 认证#

典型报错是:

ssh: unable to authenticate, attempted methods [none publickey]

这通常说明:

  • ECS_SSH_KEY 不是正确私钥
  • 服务器上的 authorized_keys 没写对
  • 公钥格式写错
  • 用户名不匹配
  • .sshauthorized_keys 权限不正确

正确的排查顺序应该是:

先本地测试:

Terminal window
ssh -i "%USERPROFILE%\.ssh\github_actions_astro" deploy@你的ECS公网IP

只有本地这条能通,GitHub Actions 才有机会成功。

2. authorized_keys 公钥格式错误#

这是一个很隐蔽但常见的问题。 比如原本应当是:

ssh-ed25519 AAAA...

如果误写成:

sh-ed25519 AAAA...

那么 SSH 会直接把这行视为无效公钥,导致始终认证失败。

3. pnpm 版本冲突#

如果 workflow 里写的是:

version: 10

package.json 里写的是:

"packageManager": "pnpm@9.14.4"

则会报多版本冲突错误。

解决方法很简单:保持两边完全一致。

4. 找不到 lock file#

如果项目是 pnpm 项目,却使用了 npm 的 workflow,可能会报找不到 package-lock.json

解决思路是:

  • 使用 cache: pnpm
  • 使用 pnpm install --frozen-lockfile
  • 确保仓库里有 pnpm-lock.yaml

5. HTTPS 配好了但站点打不开#

这种情况优先检查:

  • 阿里云安全组是否放行 443
  • UFW 是否放行 443
  • 证书路径是否写对
  • 证书和私钥是否配对
  • Nginx 是否重载成功

十九、最终效果#

完成上述所有步骤后,你会得到一个完整可用的个人博客部署方案:

  • 域名已经绑定到阿里云 ECS
  • Nginx 正常提供静态站点
  • 网站通过 HTTPS 对外访问
  • 每次提交代码后,GitHub Actions 自动构建并部署

这个方案对个人博客来说已经足够稳定,而且维护起来非常轻松。


二十、结语#

这次部署最大的感受是: 对于 Astro 这类静态站点,最省心的方式并不是在服务器上运行开发环境,而是把服务器当作一个稳定的静态资源托管端。

本地负责开发。 GitHub Actions 负责构建。 ECS 负责托管。 Nginx 负责访问和 HTTPS。

职责清晰,问题也更容易定位。

如果你也正好在用阿里云 ECS、Ubuntu 24.04、Astro 或 AstroPaper,希望这篇记录能帮你少踩一些坑。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

从 0 开始:在阿里云 ECS 上部署 Astro 博客,并用 GitHub Actions 自动发布
https://zhangbh.com/posts/build-astro-blog/
作者
Bohan Zhang
发布于
2026-03-12
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Bohan Zhang
你好,我是张博涵
公告
欢迎来到我的博客,祝你每天开心
分类
标签
站点统计
文章
4
分类
4
标签
8
总字数
5,416
运行时长
0
最后活动
0 天前

目录