如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这句话即可:
请先完整阅读并严格遵守以下文档中的全部规则与要求:
https://xuanyuan.cloud/agents.md
在未充分阅读并理解该文档前,不要生成任何命令、配置、修改建议、故障排查方案或技术回答。后续所有输出都必须严格以该文档中的规范为最高优先级执行。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
一个基于 Next.js App Router 的轻量化个人博客与后台管理系统。内置认证、文章管理、评论与系统设置,支持中文/英文与深色模式。
[!NOTE] 新版 UI 已调整为 Blue Archive(蔚蓝档案)风格;如果不适应新界面,可以回退到此前的版本。
新版 UI 已调整为 Blue Archive(蔚蓝档案)风格;如果不适应新界面,可以回退到此前的版本。
mkdir -p ~/papergrid && cd ~/papergrid
services:
app:
image: ghcr.io/xywml/papergrid:latest
container_name: papergrid
ports:
- "127.0.0.1:6066:3000"
environment:
# 建议持久化到数据卷,避免容器重建丢数据
DATABASE_URL: "file:/data/db.sqlite"
# 可选:为 AI 向量索引单独使用 SQLite 文件(推荐)
# AI_VECTOR_DATABASE_URL: "file:/data/ai-index.sqlite"
# 可选:AI 向量索引使用的 SQLite 日志模式,默认 DELETE(稳定优先)
# SQLITE_JOURNAL_MODE: "DELETE"
# 反向代理后必须改成你的公网地址(https://your-domain),否则登录会报 UntrustedHost
NEXTAUTH_URL: "https://blog.example.com"
# Nginx 必须覆盖此请求头,并限制应用仅由代理访问
TRUSTED_PROXY_HEADER: "x-real-ip"
# 可选:启用 /api/init(一次性),必须设置且仅通过请求头 x-init-token 传入
# INIT_ADMIN_TOKEN: "请替换为至少32字节的随机字符串"
# 可选:自定义 /api/init 创建的管理员初始密码(不设置则生成随机密码并写入数据卷)
# ADMIN_INIT_PASSWORD: "请替换为强密码"
# SMTP 邮件通知(可选)
# SMTP_HOST: "smtp.example.com"
# SMTP_PORT: "465"
# SMTP_SECURE: "true"
# SMTP_USER: "noreply@example.com"
# SMTP_PASS: "your-smtp-password-or-app-token"
# EMAIL_TO: "owner@example.com,ops@example.com"
# EMAIL_REPLY_DENYLIST: "deny1@example.com,deny2@example.com"
# EMAIL_UNSUBSCRIBE_SECRET: "change-this-secret"
# EMAIL_REPLY_UNSUBSCRIBE_EXPIRE_DAYS: "365"
# 自定义 Head 注入 – CSP 放行域名(可选)
# 在管理后台添加外部脚本后,需将脚本域名加到此处,否则会被 CSP 拦截
# HEAD_INJECT_SCRIPT_ORIGINS: "https://stats.example.com,https://www.googletagmanager.com"
# 可选:关闭 script-src 'unsafe-inline'(默认保留以兼容旧部署)
# CSP_ALLOW_UNSAFE_INLINE_SCRIPT: "false"
NEXT_CACHE_DIR: "/data/.next-cache"
MEDIA_ROOT: "/data/uploads"
volumes:
- papergrid_data:/data
logging:
driver: "local"
options:
max-size: "10m"
max-file: "5"
restart: unless-stopped
volumes:
papergrid_data:
docker compose pull && docker compose up -d
cd ~/papergrid && docker compose pull && docker compose up -d
初始管理员***默认为 admin@example.com。首次启动生成随机密码,保存在数据卷 /data/initial-admin.txt;本地开发保存在 .local/initial-admin.txt。也可通过 ADMIN_INIT_PASSWORD 提供 12–72 字节的初始密码。
admin@example.com``/data/initial-admin.txt``.local/initial-admin.txt``ADMIN_INIT_PASSWORD
pnpm install
安装完成后会自动执行数据库准备,见下方「数据库自动初始化」。
pnpm dev
如需示例文章数据,执行 tsx prisma/seed-posts.ts。
tsx prisma/seed-posts.ts
复制 .env.example 到 .env 并按需修改:
DATABASE_URL="file:./dev.db"
# 可选:为 AI 向量索引单独使用 SQLite 文件(推荐生产启用)
# AI_VECTOR_DATABASE_URL="file:/data/ai-index.sqlite"
# 可选:AI 向量索引使用的 SQLite 日志模式;默认 DELETE(稳定优先)
# SQLITE_JOURNAL_MODE="DELETE"
NEXTAUTH_URL="http://localhost:6066"
NEXTAUTH_SECRET="your-secret-key-change-this-in-production"
# Local media storage
MEDIA_ROOT="/data/uploads"
MEDIA_MAX_UPLOAD_MB="10"
MEDIA_MAX_INPUT_PIXELS="12000000"
MEDIA_RESOLVE_CACHE_TTL_MS="30000" # 媒体元数据缓存(ms)
INIT_ADMIN_TOKEN=""
ADMIN_INIT_PASSWORD=""
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
CLOUDINARY_CLOUD_NAME=""
CLOUDINARY_API_KEY=""
CLOUDINARY_API_SECRET=""
SMTP_HOST=""
SMTP_PORT="465"
SMTP_SECURE="true"
SMTP_USER=""
SMTP_PASS=""
# 可选:多个收件人用逗号分隔;留空则自动发给所有管理员邮箱
EMAIL_TO=""
# 可选:回复通知邮件拒收名单(逗号/换行分隔)
EMAIL_REPLY_DENYLIST=""
# 可选:退订链接签名密钥(不填则回退到 NEXTAUTH_SECRET)
EMAIL_UNSUBSCRIBE_SECRET=""
# 可选:退订链接有效期(天)
EMAIL_REPLY_UNSUBSCRIBE_EXPIRE_DAYS="365"
GOTIFY_URL=""
GOTIFY_TOKEN=""
NEXT_PUBLIC_APP_URL="http://localhost:6066"
NEXT_PUBLIC_DEFAULT_LOCALE="zh"
# 可选:日志级别(fatal/error/warn/info/debug/trace/silent)
# LOG_LEVEL="info"
# 自定义 Head 注入 – CSP 放行域名
# 在管理后台「样式 → 自定义 Head 注入」添加外部脚本后,需将脚本域名加到此处,否则浏览器会因 CSP 拦截
# HEAD_INJECT_SCRIPT_ORIGINS="https://stats.example.com,https://www.googletagmanager.com"
# 可选:关闭 script-src 'unsafe-inline'(默认保留以兼容旧部署,确认无内联脚本后可设为 false)
# CSP_ALLOW_UNSAFE_INLINE_SCRIPT="false"
OAuth 回调填写(GitHub/Google):
https://blog.miyako.space)
Homepage URL:https://blog.miyako.space{站点地址}/api/auth/callback/github
Authorization callback URL:{站点地址}/api/auth/callback/github{站点地址}/api/auth/callback/google
Authorized redirect URI:{站点地址}/api/auth/callback/googlehttp://localhost:6066/api/auth/callback/github Google 回调:http://localhost:6066/api/auth/callback/googlehttp://localhost:6066/api/auth/callback/github
http://localhost:6066/api/auth/callback/githubhttp://localhost:6066/api/auth/callback/google
http://localhost:6066/api/auth/callback/googleNEXTAUTH_URL 必须与 OAuth 平台里配置的站点地址一致(协议、域名、端口都要一致)
NEXTAUTH_URLSMTP 邮件通知说明:
邮件通知开启SMTP_USER
SMTP_USERemail.from 仅作为邮件显示名
email.fromEMAIL_TO,未配置时自动发送到管理员账号***
EMAIL_TO/api/comments/unsubscribe)
/api/comments/unsubscribe后台新增「文件管理」子目录,支持:
jpg/jpeg/png/webp/avif)
jpg/jpeg/png/webp/avif默认限制:
10MB
10MB平衡图片访问路径:
GET /api/files/:id
GET /api/files/:id后台文章编辑页已升级为 Markdown 所见即所得编辑器:
默认上传规则:
jpg/jpeg/png/webp/avif
jpg/jpeg/png/webp/avifMEDIA_MAX_UPLOAD_MB 控制(默认 10MB)
MEDIA_MAX_UPLOAD_MB:10MBBALANCED(平衡)
BALANCED可在反向代理中对 /api/files/ 增加防盗链:
location ^~ /api/files/ {
valid_referers none blocked server_names *.your-domain.com your-domain.com;
if ($invalid_referer) {
return 403;
}
proxy_pass http://127.0.0.1:6066;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
另外建议在 Nginx 设置上传大小限制:
client_max_body_size 10m;
适用于外部插件/自动化脚本管理文章,入口为:
GET /api/plugin/posts
GET /api/plugin/postsPOST /api/plugin/posts
POST /api/plugin/postsGET /api/plugin/posts/:id
GET /api/plugin/posts/:idPATCH /api/plugin/posts/:id
PATCH /api/plugin/posts/:idDELETE /api/plugin/posts/:id
DELETE /api/plugin/posts/:id登录管理员后台后,进入「管理后台 -> 接口密钥」:
管理后台 -> 接口密钥
POST_READ / POST_CREATE / POST_UPDATE / POST_DELETE
POST_READ、POST_CREATE、POST_UPDATE、POST_DELETE支持二选一:
# 方式一:x-api-key
-H "x-api-key: eak_xxxxx"
# 方式二:Authorization Bearer
-H "Authorization: Bearer eak_xxxxx"
# 列表
curl -X GET "http://localhost:6066/api/plugin/posts?page=1&limit=10" \
-H "x-api-key: eak_your_key"
为了让克隆后开箱即用,本项目在以下时机会自动执行数据库准备:
postinstallpredev执行内容等同于:
pnpm prisma generate
pnpm prisma migrate deploy
pnpm prisma db seed
如果你想跳过自动准备,可设置:
SKIP_DB_PREPARE=1 pnpm install
# 或
SKIP_DB_PREPARE=1 pnpm dev
仅跳过种子数据:
SKIP_DB_SEED=1 pnpm dev
prisma/seed.ts 会创建:
pnpm dev # 开发模式(含自动数据库准备)
pnpm build # 构建
node --env-file=.env .next/standalone/server.js # 启动独立生产包
pnpm lint # 代码检查
pnpm db:prepare # 手动执行数据库准备
pnpm db:seed # 仅执行种子数据
本项目提供开箱即用的 Docker Compose 配置,首次启动与更新建议如下:
docker compose pull && docker compose up -d
首次启动自动迁移数据库、生成管理员随机密码并保存在 /data/initial-admin.txt。
/data/initial-admin.txt
更新时建议执行:
docker compose pull && docker compose up -d
如果你希望在本地编译镜像:
docker compose -f docker-compose.build.yml up -d --build
[!IMPORTANT] 反向代理部署时必须将 NEXTAUTH_URL 改为你的公网 [***]域名。本地开发可临时设置 AUTH_TRUST_HOST=1。
NEXTAUTH_URLhttps://域名AUTH_TRUST_HOST=1
docker/ # 容器入口脚本
messages/ # i18n 文案
prisma/ # 数据库 schema 与迁移
public/ # 静态资源
scripts/ # 数据库准备脚本
src/
├── app/ # App Router
│ ├── actions/ # Server Actions
│ ├── admin/ # 管理后台页面
│ ├── api/ # API 路由
│ ├── auth/ # 认证页面
│ ├── categories/ # 分类页面
│ ├── posts/ # 文章页面
│ ├── tags/ # 标签页面
│ ├── about/ # 关于页
│ └── yaji/ # 项目/作品页
├── components/ # 组件
├── hooks/ # 自定义 Hooks
├── i18n/ # 国际化
├── lib/ # 工具与业务逻辑
├── proxy.ts # 代理/适配
└── types/ # 类型定义
docker-compose.yml # 一键运行
Dockerfile # 镜像构建
next.config.ts
package.json
更新前备份数据卷,保留原数据库、上传目录和 NEXTAUTH_SECRET。启动时自动执行数据库迁移;回退时同时恢复旧镜像和升级前的数据卷。
NEXTAUTH_SECRET
将 NEXTAUTH_URL 设为公网地址,TRUSTED_PROXY_HEADER 设为 x-real-ip,应用端口绑定 127.0.0.1。
NEXTAUTH_URL TRUSTED_PROXY_HEADER x-real-ip 127.0.0.1
location / {
proxy_pass http://127.0.0.1:6066;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 130s;
client_max_body_size 51m;
}
Homepage URL 填你的站点地址(例如 https://blog.miyako.space)Authorization callback URL 固定为:{站点地址}/api/auth/callback/githubAuthorized redirect URI 固定为:{站点地址}/api/auth/callback/googlehttp://localhost:6066/api/auth/callback/githubhttp://localhost:6066/api/auth/callback/googleNEXTAUTH_URL 必须与 OAuth 平台里配置的站点地址一致(协议、域名、端口都要一致)邮件通知开启SMTP_USERemail.from 仅作为邮件显示名EMAIL_TO,未配置时自动发送到管理员账号***/api/comments/unsubscribe)后台新增“文件管理”子目录,支持:
jpg/jpeg/png/webp/avif)默认限制:
10MB平衡图片访问路径:
GET /api/files/:id后台文章编辑页已升级为 Markdown 所见即所得编辑器:
默认上传规则:
jpg/jpeg/png/webp/avifMEDIA_MAX_UPLOAD_MB 控制(默认 10MB)BALANCED(平衡)可在反向代理中对 /api/files/ 增加防盗链:
location ^~ /api/files/ {
valid_referers none blocked server_names *.your-domain.com your-domain.com;
if ($invalid_referer) {
return 403;
}
proxy_pass http://127.0.0.1:6066;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
另外建议在 Nginx 设置上传大小限制:
client_max_body_size 10m;
适用于外部插件/自动化脚本管理文章,入口为:
GET /api/plugin/postsPOST /api/plugin/postsGET /api/plugin/posts/:idPATCH /api/plugin/posts/:idDELETE /api/plugin/posts/:id登录管理员后台后,进入 管理后台 -> 接口密钥:
POST_READ / POST_CREATE / POST_UPDATE / POST_DELETE支持二选一:
# 方式一:x-api-key
-H "x-api-key: eak_xxxxx"
# 方式二:Authorization Bearer
-H "Authorization: Bearer eak_xxxxx"
# 列表
curl -X GET "http://localhost:6066/api/plugin/posts?page=1&limit=10" \
-H "x-api-key: eak_your_key"
# 创建
curl -X POST "http://localhost:6066/api/plugin/posts" \
-H "Content-Type: application/json" \
-H "x-api-key: eak_your_key" \
-d '{
"title": "来自插件的文章",
"content": "# Hello\\n插件发布成功",
"status": "PUBLISHED",
"locale": "zh",
"isProtected": true,
"password": "123456",
"createdAt": "2026-02-09T12:00:00.000Z"
}'
# 更新(替换 :id)
curl -X PATCH "http://localhost:6066/api/plugin/posts/:id" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eak_your_key" \
-d '{
"title": "插件更新后的标题",
"status": "DRAFT",
"isProtected": false
}'
# 删除(替换 :id)
curl -X DELETE "http://localhost:6066/api/plugin/posts/:id" \
-H "x-api-key: eak_your_key"
401401403429X-RateLimit-*、Retry-After为了让克隆后开箱即用,本项目在以下时机会自动执行数据库准备:
postinstall:安装依赖后自动执行predev:启动开发服务器前自动执行执行内容等同于:
pnpm prisma generate
pnpm prisma migrate deploy
pnpm prisma db seed
如果你想跳过自动准备,可设置:
SKIP_DB_PREPARE=1 pnpm install
# 或
SKIP_DB_PREPARE=1 pnpm dev
仅跳过种子数据:
SKIP_DB_SEED=1 pnpm dev
prisma/seed.ts 会创建:
pnpm dev # 开发模式(含自动数据库准备)
pnpm build # 构建
node --env-file=.env .next/standalone/server.js # 启动独立生产包
pnpm lint # 代码检查
pnpm db:prepare # 手动执行数据库准备
pnpm db:seed # 仅执行种子数据
本项目提供开箱即用的 Docker Compose 配置,首次启动与更新建议如下:
docker compose pull && docker compose up -d
首次启动自动迁移数据库、生成管理员随机密码并保存在 /data/initial-admin.txt。
更新时建议执行:
docker compose pull && docker compose up -d
如果你希望在本地编译镜像:
docker compose -f docker-compose.build.yml up -d --build
[!NOTE] 反向代理部署时必须将
NEXTAUTH_URL改为你的公网https://域名。 本地开发可临时设置AUTH_TRUST_HOST=1。
docker/ # 容器入口脚本
messages/ # i18n 文案
prisma/ # 数据库 schema 与迁移
public/ # 静态资源
scripts/ # 数据库准备脚本
src/
├── app/ # App Router
│ ├── actions/ # Server Actions
│ ├── admin/ # 管理后台页面
│ ├── api/ # API 路由
│ ├── auth/ # 认证页面
│ ├── categories/ # 分类页面
│ ├── posts/ # 文章页面
│ ├── tags/ # 标签页面
│ ├── about/ # 关于页
│ └── yaji/ # 项目/作品页
├── components/ # 组件
├── hooks/ # 自定义 Hooks
├── i18n/ # 国际化
├── lib/ # 工具与业务逻辑
├── proxy.ts # 代理/适配
└── types/ # 类型定义
docker-compose.yml # 一键运行
Dockerfile # 镜像构建
next.config.ts
package.json
更新前备份数据卷,保留原数据库、上传目录和 NEXTAUTH_SECRET。启动时自动执行数据库迁移;回退时同时恢复旧镜像和升级前的数据卷。
将 NEXTAUTH_URL 设为公网地址,TRUSTED_PROXY_HEADER 设为 x-real-ip,应用端口绑定 127.0.0.1。
location / {
proxy_pass http://127.0.0.1:6066;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 130s;
client_max_body_size 51m;
}
来自真实用户的反馈,见证轩辕镜像的优质服务