- Rust 65.4%
- TypeScript 19.7%
- Shell 6.9%
- JavaScript 4.6%
- Dockerfile 1.8%
- Other 1.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| backend | ||
| containers | ||
| deploy | ||
| docs | ||
| gateway | ||
| integration | ||
| patches/git-pages | ||
| scripts | ||
| web | ||
| .dockerignore | ||
| .envrc | ||
| .gitignore | ||
| .muxrun.toml | ||
| compose.yml | ||
| CONTEXT.md | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| justfile | ||
| README.md | ||
Pages 平台
静态 Pages 平台:用户用 Forgejo 账号登录、领到形如 someone.gjz010.page 的域名,把 CI 构建产物发布上去,并用 https://pages.gjz010.com 管理。一期只做「CI 上传产物」,不做服务端构建。
当前部署契约:双节点高可用 + 访问网关
本仓库的部署契约是双节点高可用(HA)加本机访问网关(已批准设计见 docs/design/pages-ha.md 与 docs/design/pages-site-access.md):两台服务器各自运行 git-pages、pages-gateway(下称 gateway)与 cloudflared,接入同一个 Cloudflare Tunnel。公开站点请求经 Tunnel 进入本机 gateway(http://gateway:8081),由 gateway 完成 OIDC 登录、受保护 cookie 会话与按站点可见性的授权后,再以同一份固定站点快照代理到本机 git-pages 的私有读取接口 :3000(仅 GET / HEAD,保留 Host)。git-pages 的公开监听 :3003 保留但不再作为 Tunnel 目标;cloudflared 不再加入 origin 网络,因此无法绕过 gateway 直连 git-pages。manager(Rust / Axum)不代理公开读取,只在 management host 上提供管理网页、管理 API、OIDC 登录与发布入口 /deploy/{owner}/{repo}/,站点 Host 打到 manager 一律 404。
- 站点内容与生效配置都放在与单机故障域无关的共享 S3 上(按前缀隔离)。
manager是 S3 快照的唯一写者:<S3_PREFIX>/managed/gateway.json是路由与站点可见性的完整权威快照(旧格式<S3_PREFIX>/managed/routes.json保持兼容),管理员同步的 Forgejo 公钥发布到<S3_PREFIX>/managed/auth/forgejo-jwks.json。SQLite 保存权限审批与期望绑定,S3 是数据面消费的发布结果。 - 站点可见性分三档(public / internal / private),站点以
repo_id标识,全部绑定域名共享一份策略;默认可见性在首次创建或显式同步时确定,不实时跟随源仓库。 - 路由 / 策略快照最多缓存 30 秒;有效期过后 S3 刷新失败返回 503,不无限沿用旧策略;S3 缺快照或 Host 未知返回 404。
- 两台机器必须使用同一个 Tunnel token;
manager只在其中一台启动(Compose 的controlprofile),另一台不启动 manager。gateway 是节点自足的(只依赖本机 git-pages 与共享 S3),与 connector 一起可逐台滚动更新。 - S3 配置放在仓库外、被忽略的
.harness/deployment/s3.env(权限 0600,文档不记录取值)。不要把 S3 放在 A 或 B 单机充当高可用方案,它是独立于 A/B 的故障域。 manager停机不影响既有站点读取与登录(gateway 不连 manager);Forgejo 故障时,未过期的授权快照继续放行,快照到期后返回 503,不离线延长许可。
本节描述本仓库的部署契约,不代表线上已完成入口切换或真实 HA / 访问保护已通过验收。访问控制的实现契约见
docs/design/pages-site-access-contract.md,面向运维的逐步操作与安全迁移顺序见docs/deployment.md。改造前的单机拓扑与调研背景见docs/research/git-pages-ha.md,该文描述的是改造前状态,不是当前部署。
域名申请与接入
普通已登录用户在「我的域名」页填写申请域名与申请理由并提交,提交后可在同一页查看自己申请的状态:待审批、已批准或已拒绝。两类域名采用不同规则:
- 池内子域名(形如
blog.gjz010.page,须为已登记域名池后缀下的单层子域名)继续由管理员审批:管理员在「域名管理(管理员)」页看到全部申请,含申请人、域名与理由,并对「待审批」的申请选择批准或拒绝。 - 用户自有外域(域名池范围之外的精确域名)走账号授权自助验证:提交后系统生成一个与该账号和域名绑定的 TXT 挑战,申请人在「我的域名」页按提示在自己的 DNS 添加 TXT 记录后点击「检查并接入」。平台通过 Cloudflare DoH(
cloudflare-dns.com)查询该记录,只有与当前申请账号关联的验证值精确匹配时才分配域名;验证值 24 小时有效,可随时「重新生成验证值」。
分配会为该域名指定申请人为持有人,但不等同于完成仓库绑定或 DNS 配置。绑定仍由持有人走既有绑定流程,在「我的域名」里选择自己至少拥有 push 权限的仓库;Cloudflare 接入与证书也仍按原有方式处理。TXT 只用于账号授权验证,不检查 CNAME,也不代表接入激活、HTTPS 就绪或公网可访问;这些状态在域名卡片里分别展示。
仓库结构
| 路径 | 说明 |
|---|---|
backend/ |
manager:Rust / Axum / SQLx / SQLite,管理 API、OIDC 登录、发布入口,并作为 S3 路由 / 策略 / 公钥快照的唯一写者 |
gateway/ |
站点访问网关:Rust / Axum(binary pages-gateway),OIDC 登录、受保护 cookie 会话、S3 快照授权与内容代理 |
web/ |
管理网页:SolidJS(CSR)+ TypeScript + Vite |
patches/ |
针对固定上游提交的 git-pages 受管模式补丁 |
containers/ |
manager、gateway、patched git-pages 与 cloudflared 本地就绪门(Alpine + 固定 cloudflared)镜像的 Dockerfile |
integration/ |
本地端到端联调环境(真实容器 + 官方 CLI + Forgejo 替身 + 真实授权 S3) |
deploy/ |
部署契约:compose.env.example、git-pages.toml、gateway.toml |
compose.yml |
双节点部署契约:每台的 git-pages / gateway / cloudflared,以及仅在控制节点由 control profile 启动的 manager |
justfile |
检查、测试、镜像构建与联调命令入口 |
docs/ |
设计、实现、部署与验收文档 |
开发环境
所有命令假定运行在 devenv shell 内(rustfmt / clippy / cargo-nextest / node / yarn / just 由 devenv.nix 提供):
direnv allow # 首次进入时由宿主人工作业;当前也可用 `devenv shell -- <命令>`
devenv shell
just --list
direnv allow需要宿主人工授权;未授权时用devenv shell -- <命令>即可运行下面全部检查。
常用命令
| 命令 | 作用 |
|---|---|
just fmt |
Rust 格式化检查(backend 与 gateway) |
just clippy |
Rust Clippy(backend 与 gateway,警告即失败) |
just test |
后端与访问网关测试(cargo-nextest) |
just web-lint |
前端 Biome 检查 |
just web-typecheck |
前端 TypeScript 类型检查 |
just web-test |
前端单元测试(Vitest) |
just web-build |
构建前端生产包 |
just openapi-export |
导出 manager 的 OpenAPI(JSON 到 stdout) |
just images |
构建 git-pages-managed:local、git-pages-cloudflared:local、pages-manager:local、pages-gateway:local 四个本地镜像 |
just gateway-image |
只构建 pages-gateway:local |
just script-tests |
运行 healthgate 与 entrypoint 两个确定性脚本测试 |
just compose-config |
静态校验 compose.yml |
just e2e-local |
本地端到端联调(需先 just images) |
manager只在控制节点以--profile control运行;管理域名必须单独指向一个可达 manager 的入口(见docs/deployment.md第 9.2 节)。
怎么读文档
docs/design/pages-ha.md:已批准的双节点高可用设计约定。docs/design/pages-site-access.md:站点访问控制实现路线图(可见性、会话、缓存、迁移与回滚)。docs/design/pages-site-access-contract.md:站点访问控制接口契约(管理 API、S3 快照、公钥分发、会话与代理边界)。docs/deployment.md:双节点 HA + 访问网关运维部署教程(S3 快照、secret、入口、安全迁移顺序与验收清单)。docs/implementation/pages-manager.md:实现细节与「已核查 / 待验证」对照(其中的部署模板记录的是 HA 改造前的单机形态)。docs/implementation/mvp-checklist.md:验收账本,区分单元 / fixture、本地端到端联调、真实外部服务三类证据。docs/research/git-pages-ha.md:HA 调研报告,描述改造前状态与结论。docs/design/pages-manager.md:已确认的产品边界与技术栈。
想先在本机跑一遍主链路,见 integration/README.md。