跳到正文
SL Blog 技术探索 · 工程实践 · AI 时代思考
返回

从零部署 AstroPaper 博客:环境、构建与 Nginx 上线

文章目录
  1. 读完本文,你能完成什么
  2. 技术栈总览
  3. 项目目录结构
  4. 一、环境准备
  5. 1. 检查 Node.js
  6. 2. 安装 pnpm
  7. 二、获取源码并安装依赖
  8. 三、站点配置
  9. 四、中文本地化
  10. 4.1 新建中文 UI 翻译
  11. 4.2 注册 locale
  12. 五、字体适配(国内网络)
  13. 六、暗色主题定制(Paper Dark)
  14. 6.1 换暗色配色
  15. 6.2 让站点默认暗色
  16. 七、本地构建
  17. 八、Nginx 静态托管
  18. 九、一键部署脚本
  19. 十、日常发文章
  20. 十一、常见问题
  21. 结语

读完本文,你能完成什么

本文是一份可复现的部署记录,照着做,你能够:

  • 在一台 Linux 服务器上,从零搭建一个 AstroPaper 静态博客;
  • 完成中文界面本地化(导航、搜索、分页等全部中文);
  • 把主题改成暗色系(Paper Dark 青色主题),并让站点默认以暗色打开;
  • 用 Nginx 托管静态站点,配好缓存、gzip 与安全响应头;
  • 建立一键部署脚本,此后发文章、改文章只需一条命令;

技术栈总览

项选型
博客框架AstroPaper v6.1.0(基于 Astro 6)
运行时Node.js >= 22.12.0、pnpm 11.x
Web 服务器Nginx(静态托管)
访问方式公网 IP + 独立端口(无域名、无 HTTPS)

项目目录结构

/opt/astropaper/
├── astro.config.ts          # Astro 配置(i18n、字体)
├── astro-paper.config.ts    # 站点配置(标题、作者、社交等)
├── pnpm-workspace.yaml      # pnpm 构建脚本白名单
├── src/
│   ├── content/posts/       # 文章(一篇一目录:<slug>/index.md + 配图)
│   ├── i18n/lang/zh-CN.ts   # 中文 UI 翻译
│   └── styles/theme.css     # 主题配色
└── dist/                    # 构建产物

一、环境准备

1. 检查 Node.js

AstroPaper v6 要求 Node >= 22.12.0:

node -v

若版本不足,先升级到 Node 22+(本文环境为 v22.16.0)。

2. 安装 pnpm

npm install -g pnpm@11
pnpm -v   # 11.22.0

提示:官方脚本 curl -fsSL https://get.pnpm.io/install.sh | sh - 在某些网络环境下会中途失败,直接 npm install -g 更稳。

二、获取源码并安装依赖

git clone https://github.com/satnaing/astro-paper.git /opt/astropaper
cd /opt/astropaper
git checkout v6.1.0
pnpm install --frozen-lockfile

三、站点配置

编辑 astro-paper.config.ts,重点改 site 段:

site: {
  url: "http://43.139.41.82:8081/",  // 你的访问地址
  title: "我的技术博客",
  description: "Java、AI Agent 与工程实践",
  author: "Blog Owner",
  profile: undefined,
  lang: "zh-CN",
  timezone: "Asia/Shanghai",
},

同时建议关闭主题作者的 editPost(没有 GitHub 仓库时),并清空默认社交链接:

features: {
  editPost: { enabled: false },
  // ...
},
socials: [],

四、中文本地化

4.1 新建中文 UI 翻译

主题的界面文案由 src/i18n/lang/*.ts 提供,默认只有英文。新建 src/i18n/lang/zh-CN.ts:

import type { UIStrings } from "../types";

export default {
  nav: {
    home: "首页",
    posts: "文章",
    tags: "标签",
    about: "关于",
    archives: "归档",
    search: "搜索",
  },
  // ... 其余字段与英文版一一对应(post/pagination/home/footer/pages/a11y/notFound)
} satisfies UIStrings;

完整字段以 src/i18n/types.ts 里的 UIStrings 接口为准,逐条翻译即可。

4.2 注册 locale

修改 astro.config.ts:

i18n: {
  locales: ["zh-CN"],
  defaultLocale: "zh-CN",
  routing: { prefixDefaultLocale: false },
},

⚠️ 关键点:site.lang 必须与 i18n.locales 一致。若只改 lang: "zh-CN" 而不注册 locale,构建 /rss.xml 时会报 MissingLocaleError。

五、字体适配(国内网络)

Google Fonts 在大陆不可达,会导致构建失败(动态 OG 图拿不到字体)。改用 Bunny Fonts:

// astro.config.ts
import { fontProviders } from "astro/config";

export default defineConfig({
  // ...
  fonts: [
    {
      name: "Google Sans Code",
      cssVariable: "--font-google-sans-code",
      provider: fontProviders.bunny(),   // 原来是 fontProviders.google()
      fallbacks: ["monospace"],
      weights: [300, 400, 500, 600, 700],
    },
  ],
});

六、暗色主题定制(Paper Dark)

6.1 换暗色配色

编辑 src/styles/theme.css,把 [data-theme="dark"] 换成 Paper Dark(青色):

[data-theme="dark"] {
  --background: #2f3741;
  --foreground: #e6e6e6;
  --accent: #1ad9d9;
  --accent-foreground: #0d2b2b;
  --muted: #596b81;
  --muted-foreground: #8faabb;
  --border: #3b4655;
}

6.2 让站点默认暗色

两处都要改。src/layouts/Layout.astro 里的防闪烁内联脚本:

const stored = localStorage.getItem("theme");
const theme = stored ?? "dark";   // 默认暗色

src/scripts/theme.ts 里的默认主题函数:

function getPreferredTheme(): string {
  const stored = localStorage.getItem(THEME_KEY);
  if (stored) return stored;
  return DARK;   // 默认 Paper Dark
}

建议同时删掉 theme.ts 末尾「跟随系统深浅色」的监听,否则系统切浅色时会把博客翻回浅色。

七、本地构建

pnpm build

该命令依次执行:astro check(类型检查)→ astro build(构建)→ pagefind(搜索索引)。产物在 dist/。

八、Nginx 静态托管

假设站点监听 8081(端口可按需调整),写入 /etc/nginx/sites-available/astropaper:

server {
    listen 8081;
    listen [::]:8081;
    server_name _;

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

    charset utf-8;

    access_log /var/log/nginx/astropaper-access.log;
    error_log  /var/log/nginx/astropaper-error.log;

    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml application/json
        application/javascript application/xml application/rss+xml image/svg+xml;

    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    location /_astro/ {
        expires 1y;
        add_header Cache-Control "public, max-age=31536000, immutable";
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;
        try_files $uri =404;
    }

    location /pagefind/ {
        expires 1h;
        add_header Cache-Control "public, max-age=3600";
        add_header X-Content-Type-Options "nosniff" always;
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;
        try_files $uri =404;
    }

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
}

启用并重载:

sudo ln -s /etc/nginx/sites-available/astropaper /etc/nginx/sites-enabled/astropaper
sudo nginx -t
sudo systemctl reload nginx

九、一键部署脚本

把「构建 → 备份 → 发布 → 重载」封装成一个脚本,之后每次发布只需一条命令:

#!/usr/bin/env bash
set -Eeuo pipefail

APP_DIR="/opt/astropaper"
WEB_DIR="/var/www/astropaper"
BACKUP_ROOT="/var/backups/astropaper"
LOG_FILE="/var/log/astropaper/deploy.log"

TIMESTAMP="$(date '+%Y%m%d-%H%M%S')"
exec > >(tee -a "$LOG_FILE") 2>&1

cd "$APP_DIR"
pnpm install --frozen-lockfile
pnpm build

sudo nginx -t

sudo mkdir -p "$BACKUP_ROOT/$TIMESTAMP"
sudo rsync -a "$WEB_DIR/" "$BACKUP_ROOT/$TIMESTAMP/"

sudo rsync -a --delete "$APP_DIR/dist/" "$WEB_DIR/"
sudo chown -R www-data:www-data "$WEB_DIR"

sudo nginx -t
sudo systemctl reload nginx
echo "==> Deployment completed"

安装为系统命令:

sudo install -m 755 /path/to/deploy-astropaper /usr/local/bin/deploy-astropaper

十、日常发文章

文章是 src/content/posts/<slug>/index.md(一篇一目录,slug 即 URL 最后一段),配图与正文放在同一个目录里,用相对路径引用:

![图示](./post-image.png)

图片会在构建期被 Astro 转成 WebP 并落到带内容哈希的 /_astro/ 下(自动带 width/height 与懒加载),因此不需要手工压缩或往 public/assets/ 里放文章图。格式如下:

---
title: "文章标题"
description: "摘要"
pubDatetime: 2026-08-18T10:00:00+08:00
tags:
  - 标签1
  - 标签2
draft: false
---

正文……

写好(或改好)后运行:

deploy-astropaper

draft: true 表示草稿,不会发布到线上。

⚠️ 注意:pubDatetime 不能是未来时间。主题会把「发布时间在未来」的文章当作定时发布(scheduled post),在到达该时间前不会出现在站点上(这正是本文踩过的坑)。

十一、常见问题

  1. 构建失败:Cannot find the font path / ConnectTimeoutError
    Google Fonts 被墙,改用 fontProviders.bunny()。

  2. 构建失败:MissingLocaleError: zh-CN
    site.lang 与 i18n.locales 不一致,注册 locale 即可。

  3. Nginx 报 invalid parameter
    Nginx 不支持 \ 行续写,add_header 的值要写在同一行。

结语

至此,一个带中文界面、暗色主题、可一键发布的 AstroPaper 博客就部署完成了。后续接入域名和 HTTPS,都能在现有基础上增量完成。


RAG 智能问答

针对本文继续提问:《从零部署 AstroPaper 博客:环境、构建与 Nginx 上线》