实测环境:2026-08-16 · Ubuntu 26.04 · Docker 29 · Compose 5 · 1Panel 2.2.5 · OpenResty · Mix Space Core v14 · PostgreSQL 16 · Node.js 22 · Yohaku / Next.js 16
写在前面
折腾过自建博客的人大概都懂那种感觉:教程一篇接一篇,版本一茬接一茬,等你照着某篇 2024 年的文章敲完命令,才发现 API 早从 v2 换成了 v3,反向代理少写一行 WebSocket 配置,后台管理页面直接白屏。
这篇文章记录的是我在 1Panel 上从零部署 Mix Space(后端 Core)+ Yohaku(官方前端主题)的完整过程——包括踩过的坑、和坑对应的固定解法。和市面上大多数"跟我做"的教程不同,我把它写成了一份结构化到可以直接喂给 AI Agent 执行的文档:如果你在用 Codex、Claude Code 之类支持长上下文和命令行操作的工具,理论上只需要把这篇文章整篇喂给它,再填好服务器 IP、域名这些基本信息,它就能按部就班地帮你把博客立起来。
如果你只是想读懂部署逻辑、自己动手操作,跳过"执行协议"那部分,直接看架构和分阶段步骤即可;如果你打算交给 AI 全自动完成,请看下一节的说明。
这篇文章怎么用
这篇文章有两种读法:
当作阅读材料:从「整体架构」开始往下看,了解 Mix Space + Yohaku + 1Panel 这套组合是怎么跑起来的,每一步在解决什么问题、踩过什么坑。文中所有命令、配置文件都是实测可用的,你可以照着手动执行。
当作 Codex 的执行脚本:如果你希望让 AI Agent 帮你全自动部署,把整篇文章连同下面这份参数表一起发给它(密码等敏感信息在对话中临时提供,不要写进任何会被提交到仓库的文件):
文末的「一次性提示词模板」是我实际用来触发 Codex 执行的完整指令,复制、填好参数、发送即可。
安全声明:本文不保存也不应写入服务器密码、1Panel 密码、GitHub PAT、数据库密码、Cookie 或 Webhook 密钥,文中所有敏感字段均为占位符。
整体架构:一个域名,两个服务
Mix Space 是前后端分离架构:Core 负责数据、API、鉴权、Webhook 这些"看不见"的部分;Yohaku 是官方出的 Next.js 前端主题,负责渲染页面。两者独立部署、独立更新,靠反向代理拼成同一个域名对外服务——访客感知不到背后其实是两个进程在配合。
这套设计里有几个刻意的取舍,值得先说清楚:
- Core 用 Docker Compose 管理,Yohaku 不用。Core 是有状态服务(数据库、缓存),Compose 更适合;Yohaku 是无状态的 Next.js 应用,交给 1Panel 的 Node.js Runtime 管理更轻量,也不需要在服务器上装 Node 编译环境。
- Yohaku 的源码编译放在 GitHub Actions,服务器只负责接收产物。这样服务器不需要装 pnpm、不需要跑长时间的构建任务,发布也天然带上了版本号(
releases/<run_number>),方便回滚。 - 数据库和缓存不暴露公网端口,只在 Docker 内部网络里被 Core 访问。
- 两个服务的本机端口固定:后端
127.0.0.1:2333,前端127.0.0.1:2323,所有对外流量都经 OpenResty 反向代理进来。
固定目录结构长这样:
路由规则也很直白——除了几个明确的后端路径,其余全部交给前端:
| 路径 | 上游 | 说明 |
|---|---|---|
/ 及其他普通路径 | 127.0.0.1:2323 | Yohaku 前端 |
/api/v3 | 127.0.0.1:2333 | Core API |
/ws/ | 127.0.0.1:2333 | 当前 Core WebSocket |
/socket.io | 127.0.0.1:2333 | 兼容旧客户端 |
/render | 127.0.0.1:2333 | Core 渲染接口 |
/proxy | 127.0.0.1:2333 | Core 管理后台静态代理 |
/qaqdmin | 127.0.0.1:2333/proxy/qaqdmin | 管理后台短路径 |
开始之前:先核对上游资料
Mix Space 和 Yohaku 都在持续更新,教程最怕的就是"当时对、现在错"。所以无论是自己动手还是交给 AI,第一步都不是敲命令,而是先确认以下资料没有过时:
https://mx-space.js.org/llms.txthttps://mx-space.js.org/llms-full.txthttps://mx-space.js.org/docs/deploy/dockerhttps://mx-space.js.org/docs/deploy/reverse-proxyhttps://mx-space.js.org/docs/deploy/sslhttps://mx-space.js.org/agent-skills/mix-space-expert.mdhttps://github.com/innei-dev/yohaku-deploy-actionhttps://github.com/innei-dev/Yohaku(可能为私有仓库,需要GH_PAT)
具体要核对哪些点:
- 官方
docker-compose.yml的服务名、迁移命令和环境变量有没有变。 - 健康检查接口是否仍是
/api/v3/ping。 - Yohaku 的构建命令是否仍为
pnpm --filter @yohaku/web build:ci。 - standalone 子目录是否仍为
apps/web/.next/standalone/apps/web。 - 1Panel 当前生成的 Node runtime 文件结构有没有变化。
任何一项对不上,先更新执行记录再继续——这也是为什么这篇文章更适合当"活文档"用,而不是一次性截图收藏。
如果你在用 AI Agent:这几条是安全底线
这一节是专门写给 Codex(或其他自动化 Agent)看的强约束,人类操作者也建议照做:
- 默认全新安装:本流程默认是
fresh全新部署,不迁移旧站数据。 - 先审计,后修改:发现同名容器、已有
/opt/mix-space数据、已有/opt/yohaku发布目录或端口被占用时,不得直接删除,先判断是否属于本次未完成部署;无法确认时暂停并询问。 - 不动无关资源:不删除、不停止、不改写与本任务无关的容器、网站、证书、端口、目录或 1Panel 数据。
- 凭据零暴露:不在聊天、命令输出、Git 提交、部署文档中打印任何密码、Cookie、PAT 或生成的密钥。
- 临时文件安全:所有临时密钥文件使用
600权限;部署完成后删除本机临时.env、Cookie、API 请求体和 1Panel 数据库副本。 - Nginx 改动流程:所有 OpenResty 修改必须先备份原文件,再执行
nginx -t;只有测试成功才能reload。 - 数据库改动是最后手段:修改 1Panel 数据库前必须创建 SQLite 在线备份并核对表结构;字段不匹配时立即停止。
- 端口固定:后端固定监听
127.0.0.1:2333,前端固定监听127.0.0.1:2323;PostgreSQL 和 Redis 不暴露公网端口。 - 镜像固定:后端使用官方镜像
innei/mx-server:latest,不得使用mx-server-upload-100m或其他自制镜像。 - API 版本固定:当前 Core API 使用
/api/v3,不得沿用旧教程中的/api/v2。 - 源码来源固定:Yohaku 构建源码使用官方
innei-dev/Yohaku;部署仓库可以是用户 fork 的yohaku-deploy-action,但不能把旧的自定义主题仓库当作源码。 - 分阶段验收:每个阶段必须通过验收门后才能进入下一阶段,最终结论必须基于当次新运行的验证命令。
- 留痕:执行期间创建一份不含密钥的进度记录
docs/deployments/YYYY-MM-DD-<domain>.md,按本文阶段更新状态,便于中断后续接。
阶段 A:服务器、DNS、1Panel 与 GitHub 审计
动手之前,先把地基摸清楚——这一步的原则是只看不改。
确认 SSH 主机身份
不要无条件使用 StrictHostKeyChecking=no 连接服务器。先扫描并展示指纹供核对:
ssh-keyscan -p "$SSH_PORT" "$SERVER_IP" >"$KNOWN_HOSTS"
ssh-keygen -lf "$KNOWN_HOSTS"
之后所有 SSH/SCP 使用:
-o UserKnownHostsFile=<KNOWN_HOSTS> -o StrictHostKeyChecking=yes
无修改审计
确认这几件事:目标确实是新服务器或未完成的新部署;2323、2333 没有被无关服务占用;磁盘至少预留 10 GB;识别 OpenResty 容器名(1Panel 通常叫 openresty)。
检查 DNS
dig @1.1.1.1 +short A "$DOMAIN"
dig @1.1.1.1 +short AAAA "$DOMAIN"
dig +short NS "${DOMAIN#*.}"
如果用了 Cloudflare,A/AAAA 记录可能返回 Cloudflare 的地址,这是正常的。确认源站配置指向目标服务器即可;HTTPS 配置完成前,访问可能会先看到
525,别慌。
装 Docker(如果还没装)
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker --version
docker compose version
确认 GitHub 访问权限
gh auth status
gh repo view "$GITHUB_DEPLOY_REPO"
gh api repos/innei-dev/yohaku --jq '.full_name'
确认当前身份能访问部署 fork 和官方 Yohaku 源码——GH_PAT 至少需要读取官方源码的权限,部署 fork 的 Actions 还需要能正常写入 build_hash。
阶段 B:部署 Mix Space Core
生成密钥
在本机临时目录生成,不打印值:
后端 .env:
DOMAIN=<BLOG_DOMAIN>
POSTGRES_PASSWORD=<RANDOM_48_HEX>
JWT_SECRET=<RANDOM_64_HEX>
ENCRYPT_KEY=<RANDOM_64_HEX>
Compose 配置
把 <BLOG_DOMAIN> 替换成实际域名,密钥不要直接写进 Compose 文件,靠 .env 注入:
上传与启动
验收
期望:三个长期容器为 healthy,mx-migrate 为 Exited (0),ping 返回 pong。mx-migrate 是官方的一次性迁移服务,看到它退出是正常的——不是站点迁移任务,也不需要持续运行。
阶段 C:1Panel 网站、证书与 OpenResty
在 1Panel 创建网站
网站 -> 网站 -> 创建 -> 反向代理:
主域名: <BLOG_DOMAIN>
代理地址: http://127.0.0.1:2323
IPv6: 根据服务器启用
先创建网站记录,再用完整配置文件覆盖 OpenResty 配置。不要把单个 location 片段粘贴到只接受指令片段的输入框里——完整的 server { ... } 块要放进网站配置文件或 1Panel 的"配置文件"编辑器。
证书:正常路径
网站 -> 证书确认证书状态为ready,SAN 覆盖<BLOG_DOMAIN>或*.<ROOT_DOMAIN>。- 在网站 HTTPS 配置中选择该证书。
- 开启 HTTPS 和 HTTP 跳转 HTTPS。
- 开启自动续期。
证书:如果下拉框"无数据"
依次尝试:
- 刷新证书列表,确认域名/SAN 和状态。
- 先创建 HTTP 网站,再进入该网站的 HTTPS 配置绑定证书。
- 刷新 1Panel 页面或重启 1Panel 服务后重试。
- 仍无数据,才动数据库。
动数据库前,先确认 1Panel 2.x 使用的 SQLite 表结构与下面查询匹配:
先查询,不猜 ID:
确认唯一的 WEBSITE_ID 和 SSL_ID 后:
UPDATE websites
SET protocol = 'HTTPS', website_ssl_id = <SSL_ID>
WHERE id = <WEBSITE_ID> AND primary_domain = '<BLOG_DOMAIN>';
若 1Panel 没有自动写出证书文件,可从同一条记录导出,不要在终端打印内容:
数据库字段不匹配、查询结果不唯一,或证书私钥校验失败——这三种情况必须停下,不能硬着头皮继续改。
OpenResty 完整配置
这份配置做了一件挺关键的事:把前端(2323)和后端(2333)的路由写进同一个 server 块,用同一个域名对外服务。访客看到的是一个干净的域名,前后端在背后各司其职。
把所有 <BLOG_DOMAIN> 替换为实际域名;Cloudflare IP 段建议每次部署前从官方来源重新核对;不要用普通 envsubst 处理整个文件,否则 $host、$scheme 这些 Nginx 变量会被误替换。
安装配置:
这一步做完,即便后端还没初始化,也应该满足:
根路径此时可能是
502,因为 Yohaku 还没启动——这是阶段性的正常状态,不代表 Core 出了问题。
阶段 D:初始化 Mix Space
这一步有个容易踩的坑:/api/v3/init/* 系列接口只在创建 owner 之前可用,一旦 owner 建好就会被禁用。所以顺序必须是"先配置,后建号"。
URL、SEO 和上传限制
有个小细节:URL 路径里的配置 key 是内部名
fileUploadOptions,不是下划线写法的file_upload_options;但请求体字段用的仍是 API 原本的video_max_size。
创建 owner
登录并保留临时 Cookie
Yohaku 配置片段与初始公开笔记
创建公开、启用的 JSON snippet:
全新空站点在 Yohaku 聚合查询里可能返回 404。如果 /api/v3/aggregate?theme=yohaku%7Cshiro 是 404,创建一条公开笔记就能解决:
验收:
阶段 E:用 GitHub Actions 构建官方 Yohaku
前面说过,Yohaku 的源码不在服务器上编译,全部交给 GitHub Actions。这一节配置的是"上游更新 → CI 构建 → 发布到服务器"这条流水线。
运行时环境文件
/opt/yohaku/.env:
install -d -m 700 /opt/yohaku
install -d /opt/yohaku/releases /opt/yohaku/.cache
chmod 600 /opt/yohaku/.env
部署仓库需要满足的约定
env:
SOURCE_REPO: innei-dev/Yohaku
BUILD_COMMAND: pnpm --filter @yohaku/web build:ci
STANDALONE_SUBPATH: standalone/apps/web
DEPLOY_BASE_DIR: /opt/yohaku
工作流需要做到:
- 支持
workflow_dispatch手动触发。 - 用有权限读取官方 Yohaku 的
GH_PATcheckout 源码和 submodule/LFS。 - 用官方 build 命令生成 Next standalone 产物。
- 上传构建 artifact,再从部署 job 发送到服务器。
- 每次发布到
/opt/yohaku/releases/<run_number>。 - 创建相对软链接,保证
/opt/yohaku挂载到容器/app后仍能解析。 - 保留最近 5 个 release,方便回滚。
- 发布完成后重启 1Panel 的
yohaku容器。
有个小补丁值得一提:官方 Yohaku 的 adminUrlAtom 默认是 null,聚合公开数据也可能不返回 admin_url,导致后台入口点不进去。构建前需要打个小补丁,让它读取环境变量:
如果上游后来原生支持了这个环境变量,补丁会匹配不到——这时候先去看源码确认,别不管三七二十一硬套或者重复打补丁。
GitHub Actions Secrets
| Secret | 值 |
|---|---|
HOST | 服务器 IP |
USER | SSH 用户 |
PORT | SSH 端口 |
PASSWORD | SSH 密码;用密钥登录时要改造 workflow |
GH_PAT | 可读取 innei-dev/Yohaku 的 PAT |
BASE_URL | https://<BLOG_DOMAIN> |
NEXT_PUBLIC_API_URL | https://<BLOG_DOMAIN>/api/v3 |
NEXT_PUBLIC_GATEWAY_URL | https://<BLOG_DOMAIN> |
NEXT_PUBLIC_ADMIN_URL | https://<BLOG_DOMAIN>/qaqdmin |
AFTER_DEPLOY_SCRIPT | 通过 SSH 执行 docker restart yohaku >/dev/null 的完整命令 |
用 stdin 设置 secret,避免值出现在命令输出里:
printf '%s' "$VALUE" | gh secret set SECRET_NAME --repo "$GITHUB_DEPLOY_REPO"
触发并等待结果:
验收标准是 Prepare、Check、Build、Deploy、Store 全部 success,且服务器上出现:
/opt/yohaku/current -> releases/<run_number>/standalone/apps/web
/opt/yohaku/server.js -> current/server.js
阶段 F:1Panel Node 运行环境(这里有个大坑)
这是整个部署过程中最容易卡壳的一步,值得单独展开说。
创建 Node 运行环境
网站 -> 运行环境 -> Node.js -> 创建:
坑在哪:环境变量没有真正导出
1Panel 2.2.5 生成的 /opt/1panel/runtime/node/yohaku/run.sh 只执行了一行:
source /.env
这行代码会在 shell 里创建变量,但不会把它们导出给后面启动的 node 子进程。表现出来的症状是:Yohaku 容器状态是 running,日志显示实际监听的是默认端口 3000,而 1Panel 映射的是 2323 -> 2323,本机访问 127.0.0.1:2323 直接 connection reset。
修复很简单,加两行 set -a / set +a 把变量导出:
set -a
source /.env
set +a
同时把 /opt/yohaku/.env 里的应用变量合并进 1Panel runtime 的 .env,权限改成 600。合并时要先去重,避免同一个 key 出现两次:
这里有个反直觉的地方:Yohaku release 里那个
.env软链接本身解决不了问题,Next standalone 不会自动把它变成已导出的进程环境变量。而且每次在 1Panel 面板里编辑这个 runtime,1Panel 可能会重新生成run.sh和.env,把你的补丁冲掉——所以每次编辑后都要重新核对一遍。
验收
日志必须显示 Next 监听在 2323,本机 HTTP 返回 200,这一步才算真正过关。
阶段 G:Yohaku Webhook 与缓存
Yohaku 会缓存页面数据,改了头像、站点名之后页面不会立刻刷新,需要靠 Webhook 主动通知它失效缓存。
用 /opt/yohaku/.env 里同一个 WEBHOOK_SECRET,不要重新生成:
当前 Core 创建 webhook 成功时可能只返回 204 空响应,别以为失败了,接着查一下:
curl -fsS -b cookie.txt -H "Origin: $BASE" -H 'User-Agent: Mozilla/5.0' \
"$BASE/api/v3/webhooks" | jq .
健康检查事件应该满足:
event: health_check
status: 200
success: true
如果头像、站点名或主题配置在前端一直不更新,按这个顺序排查:
/api/v3/aggregate?theme=yohaku%7Cshiro是否已经返回新值。- webhook 是否启用、endpoint 是否为
/api/webhook、最近事件是否200。 /opt/yohaku/.env与 Core 里的 webhook secret 是否一致。- 重启
yohaku容器,再检查页面。 - 实在不行才清理
/opt/yohaku/.cache——别先清空 Redis 或数据库,这两个跟缓存刷新没关系。
最终验收:六个维度逐一过一遍
部署跑完不代表就结束了,下面这套验收清单是我踩坑之后总结出来的——很多"看起来正常"的部署,其实是漏了某一项。
1. 服务与端口
期望:mx-server、mx-postgres、mx-redis 为 healthy;mx-migrate 退出码为 0;yohaku 和 openresty 为 running;只暴露 127.0.0.1:2323 和 127.0.0.1:2333,不该出现 0.0.0.0:2323/2333;80/443 由 OpenResty 监听。
2. 公网 HTTP
| URL | 预期 |
|---|---|
http://<domain>/ | 301 到 HTTPS |
https://<domain>/ | 200,包含站点名 |
https://<domain>/api/v3/ping | 200,pong |
https://<domain>/api/v3/aggregate?theme=yohaku%7Cshiro | 200 |
https://<domain>/qaqdmin | 200 |
https://<domain>/qaqdmin/ | 301 到 /qaqdmin |
/friends、/projects、/says、/thinking、/timeline | 200 |
/notes/1 | 可能 308 到日期/slug 正规地址,跟随后为 200 |
光看管理后台 HTML 返回 200 还不够保险,最好再抽取一个 JS 资源验证也是 200,避免看到的其实是空壳页面。
3. WebSocket
命令超时是因为连接已经升级并保持打开状态,属于正常现象;真正的判断依据是有没有出现
101 Switching Protocols。
4. 证书与上传限制
再通过登录后的 API 验证:
期望是 600。上传限制这里要注意,OpenResty 的 600m 和 Core 的 600 MB 两层必须同时满足,只改一层照样会上传失败。
5. 账号与 GitHub Actions
- 用新 Cookie 登录返回
200。 - session 里的 username、name、role 分别与输入一致,role 为
owner。 - webhook 数量为 1,health check 是
200/success=true。 - GitHub Actions 最新一次部署的 jobs 全部
success。 /opt/yohaku/current、server.js、release.env和.next/cache链接在容器挂载路径里都能正常解析。
6. 用浏览器再走一遍
用已登录的 Chrome:打开首页确认昵称和初始笔记出现;打开"更多"里的友链、项目、一言页面;打开 /qaqdmin 确认后台资源能加载;控制台不应该有持续的 404/500 或静态资源加载失败。
(小提示:Yohaku 左上角头像单击一般返回首页,owner 已登录时要双击头像才进后台——但更稳妥的入口始终是直接访问 /qaqdmin。)
常见问题
部署过程中遇到的坑,整理成 FAQ 更方便查——遇到类似症状直接搜关键词就行。
Q:API 到底该用 /api/v2 还是 /api/v3?
旧教程或旧 Agent Skill 里的信息可能已经过时了。以官方 Compose 的健康检查和实际跑起来的 Core 为准——当前版本用的是 /api/v3。
Q:日志里出现 mxspace-new-migrate,是要迁移旧站数据吗?
不是。这是把一次性数据库迁移服务误认成了站点迁移任务。全新部署只会用到官方 mx-migrate,它跑完退出码是 0 就是正常状态。
Q:为什么之前的方案要自制 mx-server-upload-100m 镜像?
那是老方案为了绕过上传限制才自制的镜像,不推荐。改回官方 innei/mx-server:latest,上传限制通过 Core 的配置项 + Nginx 的 client_max_body_size 两边一起设置就够了。
Q:Nginx 报 location directive is not allowed here?
大概率是把 location 片段粘进了另一个 location 里,或者粘进了错误的 1Panel 配置输入框。解决办法是直接编辑完整的网站配置文件,确保 location 只出现在 server 块里。
Q:Cloudflare 返回 525 怎么办?
说明源站网站没绑定证书、证书文件缺失,或者 OpenResty 没加载成功。先在 1Panel 里修好 HTTPS 记录和证书文件,nginx -t 通过之后再 reload。
Q:1Panel 建站时证书下拉框显示"无数据"? 证书记录其实存在,只是建站对话框没加载出来。先建一个 HTTP 站点,再进去绑定证书;还是不行的话,走前面「证书:如果下拉框无数据」那套数据库修复流程。
Q:Yohaku 容器状态是 running,但访问 127.0.0.1:2323 却 connection reset?
这就是前面「阶段 F」里讲的那个大坑——Next 实际监听在默认的 3000 端口,因为 1Panel 的 source /.env 没有真正导出变量。按阶段 F 的修复方法合并环境变量、给 run.sh 加上 set -a/source/set +a,然后重建容器。
Q:根路径访问是 502,但 API 是正常的?
说明前端 release 或者 Node runtime 还没启动。等 GitHub Actions 和 1Panel runtime 都跑完了,再来验收根路径。
Q:页面提示 error.api_fetchError 或 Not found?
可能是 API URL 还在用 v2、反向代理漏掉了 /api/v3,或者空站点的 aggregate 接口返回了 404。分别检查并改成 v3、修正路由、创建一条公开的初始笔记就能解决。
Q:改了头像或站点名,前端页面一直不刷新?
Yohaku 有缓存机制,没被 Webhook 通知失效就不会更新。配置好同一个 secret 的 /api/webhook,确认 health check 是 200,然后重启前端。
Q:点击头像进不了后台?
Yohaku 的单击/双击行为和 admin URL 的注入方式共同决定了这个交互。构建时注入 NEXT_PUBLIC_ADMIN_URL,并且始终用稳定地址 /qaqdmin 作为后台入口就不会有问题。
Q:友链、项目这类页面打不开? 通常是这些普通页面被错误转发去了 Core,或者前端根本没启动。检查路由配置,确保只有明确列出的后端路径转发到 2333,其余统一转发到 2323,然后逐页验证是不是 200。
Q:/notes/1 返回 308?
这是正常行为,Yohaku 会把它重定向到带日期和 slug 的正规地址。用 curl -L 跟着跳转验证最终是不是 200 就行。
Q:GitHub Actions push 之后没有立即触发构建?
可能是 build_hash 和上游相同,或者更新提交被 workflow 的判断逻辑跳过了。用 workflow_dispatch 手动触发一次,顺便检查 Check job 有没有被 canceled。
Q:Actions 已经发布成功,前端却还是旧版本?
说明只切换了 release 软链接,没有重启常驻的 Node 进程。给 workflow 配上 AFTER_DEPLOY_SCRIPT,让它在发布后执行 docker restart yohaku。
Q:为什么修好之后过几天又复发了?
大概率是又在 1Panel 面板里编辑过这个 runtime,1Panel 重新生成了 run.sh 或 .env,把之前的补丁覆盖掉了。养成习惯:每次编辑 runtime 之后,重新检查一遍导出补丁、环境变量、文件权限,以及 2323 端口有没有正常监听。
备份与回滚
后端
重大更新前先备份:
千万别执行
docker compose down -v,那会把数据卷里的持久数据一起删掉。
OpenResty 与 1Panel
- 每次替换网站配置前先复制一份备份。
- 修改 1Panel 数据库前用 SQLite 的
.backup,别只复制主 DB 而漏掉 WAL 文件。 - 回滚之后先
nginx -t,测试通过再 reload。
Yohaku
发布流水线会保留最近 5 个 release,回滚只需要切换软链接、重启容器:
清理清单
部署成功之后,记得删掉这些临时文件:本机临时的后端 .env、本机临时的 Yohaku .env、登录 Cookie 文件、包含 owner 密码的 JSON、包含 webhook secret 的 JSON、临时下载的 1Panel 数据库/WAL/SHM、/tmp/yohaku-upload-* 发布分片、临时的证书私钥副本。
服务器上则要保留下面这几个文件,并且权限设为 600:
/opt/mix-space/.env
/opt/yohaku/.env
/opt/1panel/runtime/node/yohaku/.env
/opt/1panel/www/sites/<domain>/ssl/privkey.pem
交付内容
部署收尾时,建议至少确认并记录这些信息:博客首页和后台 URL、owner 用户名和昵称(密码只需要确认"已按要求设置",不要写出来)、后端和前端的安装目录、1Panel runtime 名称和 Node 版本、上传限制两层的验证结果、容器健康状态、迁移退出码、Nginx 检查结果、HTTPS/SAN/自动续期状态、WebSocket 101 和 webhook health check 200 的证据、GitHub Actions run 的 URL 和结论、是否创建了初始公开笔记,以及任何还没完成的事项和潜在风险。
一次性提示词模板
这是我实际发给 Codex 用来触发整个流程的指令,复制、填好第二节的 YAML 参数、发送即可:
自动化边界
在这些外部前提都满足的情况下,Codex 理论上可以按本文自动完成部署:DNS 已指向源站、SSH 可连接、1Panel 可访问、证书已签发或 ACME 可用、GitHub 身份能访问官方 Yohaku、服务器资源充足。
但它没法在这些情况下保证继续下去:未知的 1Panel 数据库结构、Mix Space / Yohaku 上游出现重大改版、DNS / Cloudflare 配置有误、GitHub 权限失效、证书签发失败。这些情况下,我更希望 Codex 停在明确的验收门,把现场保留下来,报告实际卡在哪一步——比起盲目往下覆盖,这样更适合一份需要反复执行的部署手册。