From 600a7acdfbd5f196bca30af5f6e548c614beec42 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 16 Aug 2026 17:49:57 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=A0=B8=E6=9F=A5=E5=B9=B6=E6=B6=A6?= =?UTF-8?q?=E8=89=B2=E6=96=87=E6=A1=A3=EF=BC=8C=E5=AF=B9=E9=BD=90=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=AE=9E=E9=99=85=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除未经验证的环境要求(Docker 版本号、浏览器条目)与括号废话 - 故障排查改为真实处理路径(升级→重新发布→强制同步→重建 Agent→提交 issue),删除仅开发时用的排障章节 - 删除设计文档中的测试与验收、实现检查清单、贡献者阅读建议等开发内容 - 修正与代码不符的事实:reset-passwd 命令名、证书续签窗口 7 天、Pages 检查间隔 1440 分钟、Relay vhost 端口 8080、SSO 仅支持 OIDC 等 - 去除口语化表述与无意义括号,改写「不是…而是…」句式 - 同步修正文档站链接锚点,构建验证通过 --- .gitignore | 1 + docs/deployment/agent.md | 12 +-- docs/deployment/deployment.md | 4 +- docs/deployment/openflared.md | 14 ++-- docs/deployment/relay.md | 6 +- docs/deployment/server.md | 20 +++-- docs/deployment/upgrade.md | 2 +- docs/design/agent-design.md | 12 +-- docs/design/architecture.md | 16 ---- docs/design/cloudflare-pointing.md | 14 +--- docs/design/edge-cache-design.md | 30 +------- docs/design/kuma-design.md | 4 +- docs/design/login-captcha.md | 16 ++-- docs/design/logstore.md | 9 +-- docs/design/observability-data-model.md | 22 ++---- docs/design/observability-design.md | 55 +++----------- docs/design/observability-transport-model.md | 27 ++++--- docs/design/origin-error-page.md | 71 +++++------------- docs/design/pages-design.md | 10 +-- docs/design/tunnel-design.md | 4 +- docs/design/waf-design.md | 2 +- docs/design/waf-orchestration-design.md | 14 +--- docs/design/zone-design.md | 9 +-- docs/guide/certificates.md | 34 ++++----- docs/guide/credits.md | 6 +- docs/guide/first-site.md | 12 +-- docs/guide/index.md | 8 +- docs/guide/pages-usage.md | 4 +- docs/guide/proxy-config.md | 20 ++--- docs/guide/quick-start.md | 34 ++++----- docs/guide/sso.md | 67 ++++++----------- docs/guide/troubleshooting.md | 74 ++----------------- docs/guide/tunnel-usage.md | 78 ++++++++++---------- docs/guide/uptime-kuma.md | 28 +++---- docs/guide/waf-ip-group-expr.md | 2 +- docs/reference/cli.md | 15 ++-- docs/reference/configuration.md | 36 ++++----- 37 files changed, 275 insertions(+), 517 deletions(-) diff --git a/.gitignore b/.gitignore index 3be52cd5..a13fec7a 100644 --- a/.gitignore +++ b/.gitignore @@ -82,3 +82,4 @@ profile.cov /.superpowers/ /.worktrees/ +/.pi-subagents/ diff --git a/docs/deployment/agent.md b/docs/deployment/agent.md index b30de243..fc1ace69 100644 --- a/docs/deployment/agent.md +++ b/docs/deployment/agent.md @@ -20,7 +20,7 @@ OpenFlare Agent 运行在代理节点侧。它不会接收远程 shell 指令, ## 一键安装 -### 交互式安装 (推荐) +### 交互式安装(推荐) 如果在不传递任何参数的情况下运行安装脚本,脚本将进入交互模式。您将可以通过向导选择安装方式(本地运行 / Docker 容器运行),并配置 Server 地址与认证 Token(若选择 Docker 方式且本地没有 Docker,脚本还会询问并智能安装 Docker): @@ -28,7 +28,7 @@ OpenFlare Agent 运行在代理节点侧。它不会接收远程 shell 指令, curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash ``` -### 自动化 (非交互式) 安装 +### 自动化(非交互式)安装 如果在执行脚本时附加了任何参数,脚本将进入自动化安装模式,不需要任何交互。 @@ -115,7 +115,7 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/inst } ``` -如果不配置 `openresty_path`,Agent 默认调用 `openresty`。完整字段见 [配置项参考](../reference/configuration.md#agent-配置字段)。 +如果不配置 `openresty_path`,Agent 默认调用 `openresty`。完整字段见 [配置项参考](../reference/configuration.md#agent-命令行参数与配置字段)。 ## Docker 运行 @@ -138,7 +138,7 @@ docker run -d --name openflare-agent --restart unless-stopped \ ## 卸载 -### 交互式卸载 (推荐) +### 交互式卸载(推荐) 如果在不传递任何参数的情况下运行卸载脚本,脚本将进入交互模式。您可以通过提示菜单选择卸载方式(本地卸载 / Docker 容器卸载): @@ -146,7 +146,7 @@ docker run -d --name openflare-agent --restart unless-stopped \ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash ``` -### 卸载 +### Docker 容器卸载 停止并删除 `openflare-agent` 容器即可 @@ -156,4 +156,4 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/unin | --- |---------------------------------------------------------------------------------------------------------| | `agent_token 和 discovery_token 不能同时为空` | 检查 `agent.json` 至少配置了一个 Token | | 节点一直离线 | 在 Agent 节点执行 `curl -I http://your-server:3000`,确认 Server 地址可达 | -| 发布后重复失败 | Agent 会阻断同一 `version + checksum` 的重复应用;在节点尝试强制同步,或者重新发布版本 | +| 发布后重复失败 | Agent 会阻断同一 `version + checksum` 的重复应用;在节点详情页点击「强制同步」,或重新发布新版本 | diff --git a/docs/deployment/deployment.md b/docs/deployment/deployment.md index d6187a90..b1e37e88 100644 --- a/docs/deployment/deployment.md +++ b/docs/deployment/deployment.md @@ -2,7 +2,7 @@ 你会学到:OpenFlare 的推荐部署方式、Server 与 Agent 的运行要求、源码启动方式、联调步骤、升级与卸载入口。 -生产环境建议使用 PostgreSQL 作为 Server 数据库,并通过 `config.yaml` 或环境变量配置 `APP_SESSION_SECRET` 等参数。完整 Docker Compose 部署需要 Redis;ClickHouse 可选,用于海量访问日志与观测时序(见仓库根目录 `docker-compose.yaml`)。Agent 部署方式推荐为 Docker 部署(即直接使用内置 OpenResty 的 Agent 镜像);亦支持通过安装脚本或手动本地运行。日志库判定与切换见 [日志存储解耦](../design/logstore.md)。 +生产环境建议使用 PostgreSQL 作为 Server 数据库,并通过 `config.yaml` 或环境变量配置 `APP_SESSION_SECRET` 等参数。完整 Docker Compose 部署需要 Redis;ClickHouse 可选,用于海量访问日志与观测时序(见仓库根目录 `docker-compose.yaml`)。Agent 支持 Docker 部署与本地安装脚本两种方式,Docker 镜像已内置 OpenResty 二进制。日志库判定与切换见 [日志存储解耦](../design/logstore.md)。 ## 部署拓扑 @@ -49,7 +49,7 @@ Internal Service (192.168.x.x) ### 硬件配置推荐 -| 组件 | 最低硬件配额 | 推荐硬件配额 | 说明 | +| 组件 | 参考配置(入门) | 参考配置(生产) | 说明 | | --- |-------------------------------| --- | --- | | **Server 控制面** | 1 核 CPU / 2 GB 内存 / 20 GB 磁盘 | 2 核 CPU / 4 GB 内存 / 50 GB+ 磁盘 | 磁盘用量需根据访问日志留存时长与并发流量合理扩容 | | **Agent 数据面** | 1 核 CPU / 512 MB 内存 / 2 GB 磁盘 | 2 核 CPU / 2 GB 内存 / 10 GB+ 磁盘 | 根据 OpenResty 的并发代理连接量与 WAF 拦截处理扩容 | diff --git a/docs/deployment/openflared.md b/docs/deployment/openflared.md index 66d0a933..d2c6d510 100644 --- a/docs/deployment/openflared.md +++ b/docs/deployment/openflared.md @@ -8,10 +8,10 @@ ## 前置条件 -1. **获取 Tunnel Token**:在 OpenFlare 管理端的「内网穿透」或「隧道管理」页面中,创建一个新的隧道实例,系统会自动生成唯一的 `tunnel_id` 与 `tunnel_token`(形如 `tun-<32hex>`)。 +1. **获取 Tunnel Token**:在管理端「节点管理」中新增一个类型为 **Tunnel** 的节点,保存后进入节点详情页即可查看该节点专属的接入 Token。 2. **网络出方向权限**:内网服务器无需任何公网入方向 IP 或端口映射,但必须能够通过网络访问公网上的 **OpenFlare Server 地址** 以及对应的 **TunnelRelay 节点中继端口 (默认 7000)**。 3. **软件依赖**(仅限宿主机直接部署): - - 本地需有可执行的 `frpc` 二进制文件(建议版本为 `v0.61.0+` 或最新稳定版 `v0.69.0`),或通过参数显式指定路径。 + - 本地需有可执行的 `frpc` 二进制文件,或通过参数显式指定路径。 --- @@ -58,8 +58,8 @@ docker run -d --name openflared --restart unless-stopped \ 启动成功后,OpenFlared 将执行以下工作流: - **心跳与配置获取**:周期性向 Server 的 `/api/v1/tunnel/heartbeat` 和 `/api/v1/tunnel/config/active` 接口发起同步,验证 Token 并检测配置版本。 - **文件渲染**:当检测到配置版本(或校验和 Checksum)变化时,会自动拉取该隧道的完整路由规则。如果绑定了多个中继 Relay,将为每个 Relay 分别在 `data_dir` 下渲染出 `frpc_{relayNodeID}.toml`。 -- **热重载或重启**:拉起对应的 `frpc` 子进程,或在配置文件发生改变时执行 `frpc reload` / 重启动作,以确保流量映射保持最新。 -- **异常自恢复**:如果本地 `frpc` 隧道进程异常退出,主控程序会在 5 秒的退避惩罚后自动尝试重新启动。 +- **配置变更重启**:当配置或校验和变化时,重新拉起对应的 `frpc` 子进程,以确保流量映射保持最新。 +- **异常自恢复**:如果本地 `frpc` 隧道进程异常退出,主控程序会按指数退避(初始 1 秒,上限 60 秒)自动重启。 ### 2. 查看日志与连接状态 @@ -79,6 +79,6 @@ frpc process missing, starting {"relay_id": "..."} ### 3. 管理端确认 -打开管理后台的 **「内网穿透」** 页面: -- 查看对应隧道的在线状态,此时应当绿灯显示 **「在线」**。 -- 您可以清晰地看到该隧道目前连接了哪些中继节点,以及各内网服务的穿透路由详情。 +打开管理后台的 **「节点管理」**,进入对应 Tunnel 节点的详情页: +- 查看节点在线状态与 flared 运行状态(WebSocket 已连接 / 运行中 / 离线)。 +- 查看当前应用版本与最近一次应用记录。 diff --git a/docs/deployment/relay.md b/docs/deployment/relay.md index f4befcb0..7c0cebdb 100644 --- a/docs/deployment/relay.md +++ b/docs/deployment/relay.md @@ -1,4 +1,4 @@ -# 部署 Relay (Tunnel 中继) +# 部署 Relay(Tunnel 中继) 你会学到:TunnelRelay 节点的职责、`openflare-relay` 的配置项与环境变量、使用 Docker 运行 Relay 的方法,以及如何通过源码手动构建并部署 Relay。 @@ -40,7 +40,7 @@ --- -## Docker 运行) +## Docker 运行 Docker 运行是 TunnelRelay 节点最便捷的部署方案。官方镜像内置了 `openflare-relay` 控制器与 `frps` 运行时,开箱即用。 @@ -84,7 +84,7 @@ docker logs -f openflare-relay - 从控制面获取最新的 frps 基础配置(包括 `bindPort`、`vhostHTTPPort` 与自动生成的隧道认证凭证 `auth_token`)。 - 在本地自动渲染出 `data/frps.toml` 配置文件。 - 自动拉起子进程 `frps -c data/frps.toml`。 -- 如果进程意外崩溃,Relay 将在 2 秒后自动拉起它。 +- 如果进程意外退出,Relay 会按指数退避(初始 1 秒,上限 60 秒)自动重启 frps。 ### 3. 管理端确认 diff --git a/docs/deployment/server.md b/docs/deployment/server.md index 935e2e30..9a7d7206 100644 --- a/docs/deployment/server.md +++ b/docs/deployment/server.md @@ -7,7 +7,7 @@ OpenFlare Server 是 Gin + GORM 单体控制面,负责管理端 UI、管理 AP > [!IMPORTANT] > **关于外部依赖**: > OpenFlare 系统内建了对后台异步任务(Asynq 框架)的支持。因此,**无论采用何种部署模式,系统都必须依赖 Redis(或 Valkey)**。各个部署方案的主要差异在于主关系型数据库的选择(SQLite vs PostgreSQL)以及是否启用链路追踪服务(Jaeger)。 -> 若业务流量过大, 建议使用 ClickHouse 存储日志。 +> 若业务流量过大,建议使用 ClickHouse 存储日志。 > [!TIP] > **ClickHouse 服务端性能配置(推荐挂载)** @@ -34,11 +34,11 @@ volumes: --- -## 方式一:Docker 部署 (推荐) +## 方式一:Docker 部署(推荐) 使用 Docker 部署可以免去本地配置 Go 与 Node.js 前端构建环境的麻烦。根据你的服务器硬件配置及业务需求,你可以选择以下三种方案之一: -### 1. 快速启动 (SQLite + Redis) +### 1. 快速启动(SQLite + Redis) > **适用场景**:测试体验、轻量化单机部署。 > @@ -66,8 +66,6 @@ services: SQLITE_PATH: "/data/openflare.db" REDIS_ENABLED: "true" REDIS_ADDR: "redis:6379" - CLICKHOUSE_ENABLED: "true" - CLICKHOUSE_HOST: "clickhouse:9000" depends_on: redis: condition: service_healthy @@ -87,9 +85,9 @@ services: --- -### 2. 小流量业务场景 (PostgreSQL + Redis) +### 2. 小流量业务场景(PostgreSQL + Redis) -> **适用场景**:生产环境、业务流量中小, PostgreSQL 不会成为日志记录的瓶颈。 +> **适用场景**:生产环境、业务流量中小,PostgreSQL 不会成为日志记录的瓶颈。 创建 `docker-compose.yaml` 文件: @@ -157,11 +155,11 @@ docker compose up -d --- -### 3. 进阶版 (含 Jaeger 链路追踪的完整编排) +### 3. 进阶版(含 Jaeger 链路追踪的完整编排) -> **适用场景**:大流量场景, 需要进行链路性能指标追踪。 +> **适用场景**:大流量场景,需要进行链路性能指标追踪。 > -> **特点**:在“生产推荐”全家桶的基础上,使用 ClickHouse 存储日志, 联动 Jaeger 作为 OpenTelemetry (OTel) 链路追踪的后端。 +> **特点**:在“生产推荐”全家桶的基础上,使用 ClickHouse 存储日志,联动 Jaeger 作为 OpenTelemetry (OTel) 链路追踪的后端。 创建 `docker-compose.yaml` 文件: @@ -177,7 +175,7 @@ services: TZ: ${TZ:-Asia/Shanghai} OTEL_EXPORTER_OTLP_ENDPOINT: "http://jaeger:4317" OTEL_EXPORTER_OTLP_INSECURE: "true" - OTEL_SAMPLING_RATE: "1.0" # 本地调试建议设为 1.0 以采样所有 Trace + OTEL_SAMPLING_RATE: "1.0" # 采样率,1.0 表示采样全部 Trace ports: - "3000:3000" volumes: diff --git a/docs/deployment/upgrade.md b/docs/deployment/upgrade.md index 68a83c24..b1122f3f 100644 --- a/docs/deployment/upgrade.md +++ b/docs/deployment/upgrade.md @@ -17,4 +17,4 @@ docker compose up ## Agent 升级 -Agent 是完全无状态的,升级时直接拉取最新镜像重建容器即可。具体部署命令与安装方式请参考 **[接入 Agent](./agent.md)**。 +Agent 本地仅缓存运行配置与状态文件,不保存业务数据;升级时直接拉取最新镜像重建容器即可。具体部署命令与安装方式请参考 **[接入 Agent](./agent.md)**。 diff --git a/docs/design/agent-design.md b/docs/design/agent-design.md index d42bdd4d..ce111616 100644 --- a/docs/design/agent-design.md +++ b/docs/design/agent-design.md @@ -92,12 +92,12 @@ sequenceDiagram Agent 对数据面 OpenResty 的管控实现了端到端的闭环,包含配置落地、语法验证、平滑重载和异常状态捕获: ### 1. 配置文件的落地组织 -同步成功后,Agent 会将配置按照特定的物理结构写入到本地 `/etc/nginx/openflare-lua/` 目录下(或配置指定的 `LuaDir`): +同步成功后,Agent 将配置写入 `data_dir` 下(默认相对路径 `etc/nginx/`、`etc/openflare/`、`var/lib/openflare/`,具体以 `agent.json` 中 `main_config_path`、`route_config_path`、`cert_dir`、`lua_dir`、`runtime_config_dir`、`pages_dir` 等字段为准): * `nginx.conf`:主配置文件(替换相关占位符,配置性能参数、Shared Dictionaries 及全局 Server)。 -* `routes.conf`:路由配置文件(由 Agent 生成,包含所有代理网站的 Server 块、证书路径、缓存及速率限制指令)。 +* `conf.d/openflare_routes.conf`:路由配置文件(由 Agent 生成,包含所有代理网站的 Server 块、证书路径、缓存及速率限制指令)。 * `certs/`:证书存放目录(文件命名为 `{cert_id}.crt` 和 `{cert_id}.key`)。 -* `waf/` 与 `pow/`:WAF 及防 CC 挑战所需的专用 Lua 运行时脚本。 -* `waf_config.json` 与 `waf_ip_groups.json`:WAF 过滤引擎所需的结构化规则配置文件。 +* `lua/waf/` 与 `lua/pow/`:WAF 及防 CC 挑战所需的专用 Lua 运行时脚本。 +* `etc/openflare/waf_config.json` 与 `waf_ip_groups.json`:WAF 过滤引擎所需的结构化规则配置文件。 * `pages_dir`:Pages 静态站点部署目录,默认位于 `data_dir/var/lib/openflare/pages`。当激活配置引用 Pages **项目**时,Agent 按 `project_id` 请求控制面「最新激活包」(hash + package),以流式方式写入临时文件并执行实际响应上限与 SHA-256 校验,再安全解压到 `projects/{project_id}/releases/{hash}`。解压后会复核文件数与总字节,绝对防御上限为 2 GiB 包、1,000 个文件、单文件及总量 8 GiB;随后原子切换 `current` 并**立即删除同项目其它历史 release**(仅保留最新)。项目内切换激活无需重发主配置;多项目对账时单项目失败不阻塞其它项目。 ### 2. 精细化的重载动作 @@ -105,13 +105,13 @@ Agent 对数据面 OpenResty 的管控实现了端到端的闭环,包含配置 2. **写入并替换占位符**:将最新拉取的模板写入,自动将模板中的绝对路径占位符(如 `__OPENFLARE_LUA_DIR__`、`__OPENFLARE_PAGES_DIR__`)替换为本地实际运行路径。 3. **语法校验**:调用 `openresty -t -c ` 进行严格的语法测试。 4. **平滑重载**:若校验通过,将新配置移至正式路径,执行 `openresty -s reload`。若 OpenResty 处于未启动状态,则使用当前配置拉起进程。 -5. **捕获异常**:校验或重载失败时,Agent 会截获标准错误输出(stderr),提取前 2000 个字符的详细报错信息。 +5. **捕获异常**:校验或重载失败时,Agent 截获命令标准输出(stderr/stdout)作为失败详情上报。 --- ## 发布与配置应用模型 -OpenFlare 摒弃了动态 Patch 节点配置的落后方式,采用 **不可变配置版本发布模型**。 +OpenFlare 采用 **不可变配置版本发布模型**,而非对节点配置进行在线动态 Patch。 ```text 修改规则 -> 预览 / 查看 diff -> 发布 -> 生成完整配置版本 -> 激活版本 -> Agent 拉取 -> 本地应用 -> 上报结果 diff --git a/docs/design/architecture.md b/docs/design/architecture.md index d8cb502b..c63c5e0a 100644 --- a/docs/design/architecture.md +++ b/docs/design/architecture.md @@ -206,19 +206,3 @@ OpenResty 健康与连接数 --> 边缘健康(瞬时,不作 24h 业务总量 | Pages artifact 与仓库构建分离 | 现有来源只导入预构建产物;未来 checkout/build 由 Server 隔离 executor 完成并复用 artifact pipeline,Agent 不执行第三方构建 | --- - -## 贡献者阅读建议 - -修改系统架构或开发新功能前,请按以下顺序阅读: - -1. **[产品边界](./index.md)**:了解 OpenFlare 核心定位与不允许逾越的设计边界。 -2. **[Agent 与发布模型](./agent-design.md)**:理解版本快照同步及失败回滚的安全兜底逻辑。 -3. **细分领域设计**: - * Zone 与域名相关开发:阅读 [Zone 与域名资源设计](./zone-design.md)。 - * Cloudflare DNS 指向开发:阅读 [Cloudflare DNS 指向设计](./cloudflare-pointing.md)。 - * 穿透相关开发:阅读 [内网穿透隧道设计](./tunnel-design.md)。 - * WAF 相关开发:阅读 [WAF 设计](./waf-design.md) 与 [WAF 可编排规则设计](./waf-orchestration-design.md)。 - * Pages 托管开发:阅读 [Pages 静态托管设计](./pages-design.md)。 - * 监控同步开发:阅读 [Uptime Kuma 监控同步设计](./kuma-design.md)。 - * 看板/访问日志/节点指标开发:阅读 [观测数据传输模型](./observability-transport-model.md) 与 [边缘可观测与业务流量统计](./observability-design.md)。 -4. **[仓库结构](./index.md#仓库结构)**:明确各个物理目录分层职责,避免堆砌和重复开发。 diff --git a/docs/design/cloudflare-pointing.md b/docs/design/cloudflare-pointing.md index 4a2f96e1..e70a15dd 100644 --- a/docs/design/cloudflare-pointing.md +++ b/docs/design/cloudflare-pointing.md @@ -187,8 +187,7 @@ OpenFlare 库表为 Source of Truth。每个成员期望: | 可选域名 | `GET /domains/available` | * 成功 `response.OK`;失败 `response.Abort*`;**永不**在 JSON 中返回 Token。 -* Handler 与 `logics.go` 分离;CF 客户端可 mock 接口。 -* 变更后维护 Swagger(`make swagger`)。 +* Handler 与 `logics.go` 分离;CF 客户端以接口抽象便于替换。 ## 前端 @@ -207,18 +206,9 @@ OpenFlare 库表为 Source of Truth。每个成员期望: * 典型:未配置 Token、Token 无效、节点无 IP、CF 无 Zone、同名多 A、限流。 * Token 仅服务端解密使用;响应与日志禁止明文 Token。 -## 数据迁移与测试 +## 数据迁移 * goose 双方言(PG/SQLite)新建三张表;默认值与 Go 零值一致。 -* 单测:Token 解析、reconcile 0/1/多条、橙云只初始化新成员、移出删远端(mock)、节点 IP 变更入队。 -* 禁止单测打真实 Cloudflare。 - -## 文档与边界同步 - -* 更新 [Zone 与域名资源设计](./zone-design.md):Zone 仍不内建权威 DNS;可选本模块负责 CF A 指向。 -* 更新 [系统架构](./architecture.md) 核心对象与阅读建议。 -* 更新 [产品边界](./index.md) 能力表。 -* 实现完成后写入 `docs/changelog/index.md` 的 `[Unreleased]`(纯设计文档变更不写 changelog)。 ## 关键决策摘要 diff --git a/docs/design/edge-cache-design.md b/docs/design/edge-cache-design.md index a57639b7..b95dc1a3 100644 --- a/docs/design/edge-cache-design.md +++ b/docs/design/edge-cache-design.md @@ -204,7 +204,6 @@ access.log cache_status=$upstream_cache_status | 模型/默认 | 创建路由默认 `cache_policy=static`;读写时 `url`→`all` | | 快照 | `config_version` 快照规范化 | | UI | `proxy-routes/detail/components/cache-section.tsx` | -| 测试 | `pkg/render/openresty/render_test.go` 等 | --- @@ -235,21 +234,7 @@ access.log cache_status=$upstream_cache_status --- -## 7. 验证要点 - -* 渲染:无 Cookie/Auth/请求 Cache-Control 旁路;含 `proxy_cache_valid` 三行;`proxy_no_cache` 含 `$upstream_http_set_cookie`。 -* 单测:内置表含 `css`/`js`/`map`/`mjs`,**不含** `html`/`json`。 -* 手动: - * 带 session Cookie 请求 `/a.js` → 第二次 `HIT`; - * `/index.html` + `static` → 未缓存; - * 源站对 eligible 路径返回 `Set-Cookie` → 不入库(持续 MISS/不 HIT); - * 源站 `Cache-Control: private` → 不入库。 -* 观测:access log 三态与原始 `cache_status` 一致。 -* 生效:配置版本发布并节点应用后验证。 - ---- - -## 8. 决策矩阵(防漏判) +## 7. 决策矩阵(防漏判) | 场景 | CF | OpenFlare(本设计) | | --- | --- | --- | @@ -264,18 +249,7 @@ access.log cache_status=$upstream_cache_status --- -## 9. 后续路线图 - -1. Auth 完整 RFC/CF 条件缓存(Lua) -2. 强制 Edge TTL / `proxy_ignore_headers`(Cache Rules 级) -3. Purge API -4. Cache Rules(有序规则 + 动作) -5. 全局默认可缓存扩展名可配置;可选对齐 CF 更长扩展名表 -6. HEAD→GET - ---- - -## 10. 决策记录 +## 8. 决策记录 | 决策 | 选择 | 原因 | | --- | --- | --- | diff --git a/docs/design/kuma-design.md b/docs/design/kuma-design.md index 0f18a90c..82b52971 100644 --- a/docs/design/kuma-design.md +++ b/docs/design/kuma-design.md @@ -9,7 +9,7 @@ 在多节点的网关架构中,监控系统的状态与反向代理路由的状态通常是相互脱节的: 1. **录入开销大**:每当网关控制面新增或下线一个站点,管理员都必须在监控系统(如 Uptime Kuma)中重复配置对应的探测地址与告警策略。 2. **数据不一致**:当代理路由域名发生变更或切换 HTTPS 时,容易遗漏修改监控参数,导致监控系统误报或漏报。 -3. **环境污染隐患**:如果简单的在监控中执行全量“删除-重建”同步,不仅会清空监控系统中的历史统计指标和 SLA 曲线,还会影响到用户在此监控实例上自行配置的、与网关无关的其他监控任务。 +3. **环境污染隐患**:若在监控中执行全量“删除-重建”同步,会清空监控系统中的历史统计指标与 SLA 曲线,还会影响用户在此监控实例上自行配置的、与网关无关的其他监控任务。 为了解决这些痛点,OpenFlare 引入了基于客户端/服务器模式的 **Uptime Kuma 自动监控同步机制**,实现网关站点路由定义与可用性监测系统的强一致、低开销以及零污染同步。 @@ -106,4 +106,4 @@ stateDiagram-v2 * Server 周期性(每 1 分钟)通过后台的 Cron Job 探测是否达到配置的同步间隔(`UptimeKumaSyncInterval`)。 * 任务内部设计了互斥锁(Mutex Locking)。如果前一次同步请求因为网络延迟等原因尚未结束,下一次调度将自动跳过,防止并发多个 Socket.IO 连接对 Uptime Kuma 实例造成 DDOS 冲击。 2. **WebSocket 状态监听**: - * 同步程序利用 Socket.IO 的事件监听机制,在连接建立后,必须等到监听到 `monitorList` 事件的完整列表推送后,才允许向下执行差分算法,以规避因为数据加载不完整导致误删监控项的边界情况。 + * 同步程序利用 Socket.IO 的事件监听机制,在连接建立后,必须等到监听到 `monitorList` 事件的完整列表推送后,才允许向下执行差分算法,避免因数据加载不完整导致误删监控项。 diff --git a/docs/design/login-captcha.md b/docs/design/login-captcha.md index 3d39a676..3eef1d99 100644 --- a/docs/design/login-captcha.md +++ b/docs/design/login-captcha.md @@ -7,14 +7,14 @@ ## 1. 业务背景与产品范围 ### 背景与痛点 -根据我们的系统安全分析,OpenFlare 的登录端点 `/api/user/login` 虽然配置了基于 IP 的限流限制,但由于缺少用户维度的防护机制,攻击者可使用代理池绕过 IP 限制对高权限账户(如 `root`)实施撞库和暴力破解。同时,对于系统登录页面,标准的视觉验证码对用户体验和无障碍不够友好。 +OpenFlare 的登录端点 `/api/v1/user/login` 缺少用户维度的防护机制,攻击者可使用代理池对高权限账户(如 `root`)实施撞库和暴力破解。同时,标准的视觉验证码对登录页用户体验和无障碍不够友好。 ### 产品范围与技术选型 * **技术选型**:Cap (Proof-of-Work 驱动的无感无图像验证码解决方案)。 - **核心原理**:客户端(Widget/网页)从服务器获取工作量证明 (PoW) 的难题,使用浏览器后台计算求解并将答案回传。服务器验证答案的正确性,完成人机识别。 - **优势**:无感、无图像验证、不依赖任何外部第三方 API 节点(私密)、包极小。 -* **接入范围**:控制面 Server 登录 API(`/api/user/login`)以及前端登录页面。 -* **配置粒度**:支持管理员通过控制台 Option 表随时开启/关闭验证码(`CapLoginEnabled`)。 +* **接入范围**:控制面 Server 登录 API(`/api/v1/user/login`)以及前端登录页面。 +* **配置粒度**:支持管理员通过控制台 Option 表随时开启/关闭验证码(`cap_login_enabled`)。 --- @@ -28,7 +28,7 @@ * 暴露 `POST /api/cap/challenge` 接口,为客户端分发 PoW 难题和签名的 JWT Token。 * 暴露 `POST /api/cap/redeem` 接口,校验客户端提交的 PoW 解答并核发带有失效时间的登录凭证(Redeem Token)。 * 将 Redeem Token 与对应过期时间保存在内存缓存/Redis 缓存中。 - * 在 `POST /api/user/login` 接口中,若启用了验证码保护,先校验并消耗(单次失效)对应的 `cap-token`。 + * 在 `POST /api/v1/user/login` 接口中,若启用了验证码保护,先校验并消耗(单次失效)对应的 `cap-token`。 ### 2.2 验证流时序图 ```mermaid @@ -51,7 +51,7 @@ sequenceDiagram Server->>Browser: 返回 {success: false, reason} end User->>Browser: 输入账号密码,点击登录 - Browser->>Server: POST /api/user/login (在 HTTP 请求头中携带 X-Cap-Token) + Browser->>Server: POST /api/v1/user/login (在 HTTP 请求头中携带 X-Cap-Token) alt CapLoginEnabled = true Server->>Server: Middleware (CapAuth) 校验并消费 X-Cap-Token alt token 合法且未过期且未被消费 @@ -80,7 +80,7 @@ sequenceDiagram "error_msg": "", "data": { "challenge": { - "c": 50, + "c": 1, "s": 32, "d": 4 }, @@ -108,7 +108,7 @@ sequenceDiagram } ``` -#### 3. 登录接口 (POST /api/user/login) +#### 3. 登录接口 (POST /api/v1/user/login) * **请求负载保持不变**: ```json { @@ -124,4 +124,4 @@ sequenceDiagram 1. **JWT 临时状态绑定**:难题在生成时就被签入 JWT payload,包含过期时间限制(10 分钟)。 2. **Replay 拦截(Nonce 消耗)**:当客户端调用 `/redeem` 提交解答时,后端在缓存中标记该 JWT Signature 已使用。重复提交相同的解密包将返回 `already_redeemed`。 3. **Redeem 一次性核销(单次失效)**:当客户端登录并提交 `cap-token` 时,后端在检验到合法性后立即从缓存中删除该 Key,防止黑客提取历史正确的 `cap-token` 进行重放登录。 -4. **验证机制无感化**:通过调整 `c (难题数)=50`,`d (难度)=4`,普通用户在桌面端和移动端只需 0.5 秒至 1.5 秒即可静默解出,极大地兼顾了用户体验和反爬效果。 +4. **验证机制无感化**:通过调整 `c (难题数)`、`d (难度)` 等参数平衡求解耗时与反爬强度,用户在后台静默解出,不打断登录流程。 diff --git a/docs/design/logstore.md b/docs/design/logstore.md index 74fea36e..6f5cfa54 100644 --- a/docs/design/logstore.md +++ b/docs/design/logstore.md @@ -1,6 +1,6 @@ # 日志存储解耦 -你会学到:哪些表属于日志用途、为什么不能绑死 ClickHouse,以及新增一张日志表时必须走哪条代码路径。逐步落地步骤见 `.agents/skills/logstore/SKILL.md`。 +你会学到:哪些表属于日志用途、为什么不能绑死 ClickHouse,以及新增一张日志表时必须走哪条代码路径。 观测字段与上报协议仍以 [观测上报协议与表结构](./observability-data-model.md) 为准;本文只约定**存到哪、怎么切库**。 @@ -70,7 +70,7 @@ ClickHouse 上的小时级物化视图(如 `of_access_log_hourly`)只服务 ## 5. 新增一张日志表 -列名必须在 ClickHouse / PostgreSQL / SQLite 三套 goose 中一致。顺序与禁止项见 `logstore` skill。要点: +列名必须在 ClickHouse / PostgreSQL / SQLite 三套 goose 迁移中一致。要点: * 高频表:CH 用 `MergeTree` + `toYYYYMM`;PG 用 `PARTITION BY RANGE(时间列)`,主键含分区键;SQLite 普通表 + 索引。 * ID 用 snowflake `uint64`,迁移时原样保留。 @@ -83,7 +83,4 @@ ClickHouse 上的小时级物化视图(如 `of_access_log_hourly`)只服务 ## 6. 相关文档 -* 开发步骤:`.agents/skills/logstore/SKILL.md` -* DDL:`.agents/skills/database-migration/SKILL.md` -* 批量写入:`.agents/skills/clickhouse-batchwriter/SKILL.md` -* 实现前设计稿(历史):[日志数据库解耦设计](../superpowers/specs/2026-08-08-log-database-decoupling-design.md) +* 观测字段与上报协议:[观测上报协议与表结构](./observability-data-model.md) diff --git a/docs/design/observability-data-model.md b/docs/design/observability-data-model.md index f9d650b4..e8784b52 100644 --- a/docs/design/observability-data-model.md +++ b/docs/design/observability-data-model.md @@ -264,7 +264,7 @@ Agent:tail access.log → 解析 JSON 行 → 原样字段上报(可截断 p #### 边界 * Pages 静态 / 无 `proxy_cache` 的 location:多为空或 `-` → **未使用缓存**,不得标成「命中」。 -* 第一期只做明细可见;命中率看板、hourly 维度可后续用同一列聚合。 +* 明细详情展示缓存状态;命中率看板与 hourly 维度可基于同一列扩展。 **单次心跳条数建议:** @@ -302,10 +302,10 @@ Agent:tail access.log → 解析 JSON 行 → 原样字段上报(可截断 p 写入关系库健康事件表(现有模型即可),不进访问日志湖。 -### 3.8 Go 协议草图(目标) +### 3.8 Go 协议结构 ```go -// pkg/protocol/agent.go(目标形态,实现时替换旧类型) +// pkg/protocol/agent.go(当前实现) type NodePayload struct { SchemaVersion int `json:"schema_version,omitempty"` @@ -447,7 +447,7 @@ type BufferedFacts struct { --- -## 5. 表结构(目标 DDL) +## 5. 表结构(DDL) > 引擎与 TTL 与现网一致倾向:访问日志 90 天,指标 30 天。 > `id` 使用控制面 Snowflake/唯一 UInt64。 @@ -556,7 +556,6 @@ GROUP BY node_id, hour, host; 2. 即便存每小时 UV,对多小时窗口 **相加会严重高估**(同一 IP 跨小时重复计)。 3. 产品「24h 独立访客」只认整窗 `uniqExact`;趋势图主序列是请求量/错误/字节,分时 UV 非主指标。 -可选未来:若需要分时 UV 曲线,再单独加 `AggregatingMergeTree` 状态表或查询时对明细做 `uniqExact` 按小时 group(成本更高,不阻塞当前看板)。 ### 5.3 L3 事实表:`of_node_metric_snapshots`(保留,语义明确) ```sql @@ -761,18 +760,7 @@ Agent 解析: --- -## 10. 实现检查清单 - -- [x] `pkg/protocol`:仅 v2 字段,无兼容别名 -- [x] Agent:只组 `host_metrics` / `edge_health` / `access_logs` / `buffered` -- [x] Server:无 request_reports / openresty 吞吐;健康当前态 PG、时序 CH -- [x] CH migration:`request_length`、`request_time_ms`、`of_node_edge_health`、`of_access_log_hourly`、hourly 回填 -- [x] 看板/Zone API 统一读 access log 聚合 -- [x] UV:整窗 uniqExact;Zone 曲线标明分桶 UV;小时趋势不绘 UV - ---- - -## 11. 修订记录 +## 10. 修订记录 | 日期 | 说明 | | --- | --- | diff --git a/docs/design/observability-design.md b/docs/design/observability-design.md index 233ff4cf..91cba4bd 100644 --- a/docs/design/observability-design.md +++ b/docs/design/observability-design.md @@ -1,6 +1,6 @@ # 边缘可观测与业务流量统计重构设计 -你会学到:当前观测链路为何出现「看板 OpenResty 出站」与「Zone 已提供数据」不一致、字段与聚合为何冗余,以及目标架构如何让 **Agent 只上报事实、Server 只解释事实**,业务流量以访问日志为唯一真相源。 +你会学到:本次重构要解决的问题(「看板 OpenResty 出站」与「Zone 已提供数据」不一致、字段与聚合冗余),以及目标架构如何让 **Agent 只上报事实、Server 只解释事实**,业务流量以访问日志为唯一真相源。 --- @@ -38,7 +38,7 @@ ### 2.1 产品约束(继承) * 单租户、全局单激活配置;观测不引入多租户计费隔离。 -* ClickHouse 为访问日志与时序观测的强制分析存储。 +* 访问日志与时序观测走可切换日志主库(默认 ClickHouse,可切换 PostgreSQL/SQLite),见 [日志存储解耦](./logstore.md)。 * Agent 无入向控制、Pull 模型;离线期间本地 OpenResty 继续服务,观测可本地缓冲后补传。 ### 2.2 工程约束 @@ -98,9 +98,9 @@ Server = 入库 + 聚合 + 归属 + 趋势 + 对账 --- -## 4. 现状问题(基线) +## 4. 重构前的问题(基线) -### 4.1 当前数据流(冗余) +### 4.1 重构前数据流(冗余) ```text 一次 HTTP 请求 @@ -307,11 +307,10 @@ Agent 职责: ### 7.4 OpenResty 本地观测 -**收敛后建议:** +收敛后的状态: * 保留:健康检查、`stub_status` 当前连接。 -* 删除主路径依赖:`log.lua` 中对 request/status/domain/rx/tx 的 shared dict 业务计数,以及 `/openflare/observability` 作为 TrafficReport 来源。 -* 若短期内保留 endpoint 供调试,不得再写入 Server 权威分析表。 +* 主路径不再依赖 `log.lua` 的 shared dict 业务计数;`/openflare/observability` 只返回健康与连接快照,不作为业务报表来源。 ### 7.5 与 Agent 设计文档的关系 @@ -479,7 +478,7 @@ bytes_sent (= $body_bytes_sent), request_length ### 11.4 健康状态权威 * **当前态**:PG `openresty_status` / `openresty_message`。 -* **时序**:CH `of_node_edge_health`(status + connections;无 message)。 +* **时序**:日志主库 `of_node_edge_health`(status + connections;无 message)。 ### 11.5 UV @@ -497,37 +496,7 @@ bytes_sent (= $body_bytes_sent), request_length --- -## 13. 验证标准 - -### 13.1 对账 - -在仅有单一 Zone 产生流量的环境: - -```text -看板「已提供数据」(24h) ≈ Zone「已提供的数据总计」(24h) -误差仅来自时间窗对齐(整点截断)与未计入 Host -``` - -多 Zone 时: - -```text -sum(各 Zone 已提供) + sum(未归属 Host) = 全局已提供 -``` - -### 13.2 回归 - -* Agent 单测:只解析与 offset,不出现业务 sum 断言为「上报契约」。 -* Server:Zone stats 与 dashboard business traffic 共用聚合测例。 -* 前端:文案快照/测试中不再出现业务含义的「OpenResty 出站」与「已提供数据」双卡片。 - -### 13.3 性能 - -* 24h 看板聚合 P95 可接受(必要时 hourly MV)。 -* 心跳 payload 体积:明细批量有上限;超限拆缓冲,不在 Agent 做摘要替代。 - ---- - -## 14. 风险与权衡 +## 13. 风险与权衡 | 风险 | 缓解 | | --- | --- | @@ -543,7 +512,7 @@ sum(各 Zone 已提供) + sum(未归属 Host) = 全局已提供 --- -## 15. 关键决策摘要 +## 14. 关键决策摘要 | 决策 | 选择 | 否决方案 | | --- | --- | --- | @@ -556,7 +525,7 @@ sum(各 Zone 已提供) + sum(未归属 Host) = 全局已提供 --- -## 16. 文档与代码映射(落地时) +## 15. 文档与代码映射 | 区域 | 主要路径 | | --- | --- | @@ -568,8 +537,6 @@ sum(各 Zone 已提供) + sum(未归属 Host) = 全局已提供 | 看板 | `internal/apps/openflare/dashboard/`、`internal/apps/openflare/observability/analytics.go` | | 前端 | `frontend/app/(main)/page.tsx`、`components/dashboard/*`、`websites/.../zone-overview.tsx` | -实现计划见:`docs/plan/20260717-observability-redesign.md`。 - **推荐阅读顺序:** 1. **[观测数据传输模型](./observability-transport-model.md)**(最新:传什么、从哪采、频率、示例 JSON) @@ -577,7 +544,7 @@ sum(各 Zone 已提供) + sum(未归属 Host) = 全局已提供 --- -## 17. 修订记录 +## 16. 修订记录 | 日期 | 说明 | | --- | --- | diff --git a/docs/design/observability-transport-model.md b/docs/design/observability-transport-model.md index 5de97051..cc0ca7a5 100644 --- a/docs/design/observability-transport-model.md +++ b/docs/design/observability-transport-model.md @@ -6,7 +6,7 @@ --- -## 0. 先记住三层(不要混) +## 0. 先记住三层 | 层 | 回答的问题 | 唯一数据来源 | 产品例子 | | --- | --- | --- | --- | @@ -215,7 +215,7 @@ cache_status ← $upstream_cache_status 【缓存状态;UI 可推导命中/ 落库表:`of_node_access_logs`(可选 Server 侧 `of_access_log_hourly` 加速,**Agent 不写**)。 -### 4.4 频率再强调 +### 4.4 上报频率 ```text 请求发生 ──立即──► 写 access.log @@ -229,9 +229,9 @@ Server ──立即/批量──► CH ## 5. L2 健康:edge_health 与 `/openflare/observability` -### 5.1 本机监测口(合并后目标) +### 5.1 本机监测口 -**只保留一个接口:** +**数据采集接口:** ```http GET http://127.0.0.1:{openresty_observability_port}/openflare/observability @@ -241,7 +241,7 @@ GET http://127.0.0.1:{openresty_observability_port}/openflare/observability **职责:** 回答「OpenResty 此刻怎样」,**不**回答业务已提供多少数据。 -#### 返回示例(目标 JSON) +#### 返回示例 ```json { @@ -263,7 +263,7 @@ GET http://127.0.0.1:{openresty_observability_port}/openflare/observability | `connections.active` | **瞬时** | Nginx 连接状态(原 stub_status Active) | 当前活跃连接 | | `reading` / `writing` / `waiting` | **瞬时** | 同上细分 | 可选但建议带 | -**不返回(已从目标模型删除):** +**不返回(已删除):** | 旧字段 | 原因 | | --- | --- | @@ -272,9 +272,9 @@ GET http://127.0.0.1:{openresty_observability_port}/openflare/observability | `source_countries` | 从未实现;国家走 Server GeoIP | | `server.accepts/handled/requests` | 进程累计 counter,易与业务请求混淆;主路径不收录 | -**`/openflare/stub_status`:** 合并进上述 JSON 后 **删除**(过渡期可双挂,Agent 只打合并口)。 +**`/openflare/stub_status`:** 保留;`/openflare/observability` 内部读取该口组装连接数 JSON,Agent 健康检查也直接探测该口。 -### 5.2 采集机制(读快照,不是「调用才开始统计业务」) +### 5.2 采集机制(读快照) ```text Nginx 在连接建立/释放时维护 Active connections 等 @@ -284,9 +284,8 @@ Agent GET /openflare/observability 只读取「当前值」拼 JSON 返回 ``` -- **不是** GET 一次才去扫 access.log。 -- **不是** 60 秒业务均值。 -- 是 **瞬时 gauge 快照**。 +- 不扫 access.log、不算 60 秒业务均值。 +- 返回 **瞬时 gauge 快照**。 ### 5.3 上报示例(装进 NodePayload) @@ -361,7 +360,7 @@ Agent 读本机(如 `/proc`、磁盘统计等),**每次组包时读一次* --- -## 7. 一次完整上报示例(拼起来) +## 7. 一次完整上报示例 ```json { @@ -466,13 +465,13 @@ t=6s 下一轮… --- -## 10. 旧模型对照(帮助消歧) +## 10. 旧模型对照 | 旧做法 | 新模型 | | --- | --- | | Lua dict 60s 窗 request_count + Agent 10s 拉 + Server sum | **删除**;请求数 = 日志 count | | openresty_tx 当「出站」 | **删除**;已提供数据 = `sum(bytes_sent)` | -| 两个口 observability + stub_status | **合并为一个** observability,只返回连接/探活 | +| 两个口 observability + stub_status | 数据采集统一走 observability;stub_status 保留为探活与内部读取口 | | TrafficReport 预聚合 | **删除**;协议与 API 均无此路径 | | 业务与网卡混称「流量」 | **分文案、分 API、分表** | | 健康 status/message | **PG 最新态权威**;CH 仅 status+连接时序 | diff --git a/docs/design/origin-error-page.md b/docs/design/origin-error-page.md index a977813d..583979c8 100644 --- a/docs/design/origin-error-page.md +++ b/docs/design/origin-error-page.md @@ -15,7 +15,7 @@ * **默认可视**:默认启用,默认状态码标签 `500-599`,默认 OpenFlare 极简错误页。 * **可自定义**:管理员可在线编辑完整 HTML;空 HTML 表示使用内置默认模板。 * **状态码透传**:HTTP 响应 `status` 保持原错误码(如 502、522);页面正文通过 `{{status}}` 展示同一数值。 -* **全局统一**:侧栏「网站管理 → 错误页」单一配置,全站反代路由共用。 +* **全局统一**:侧栏「网站管理 → 响应页面」单一配置,全站反代路由共用。 * **与发布一致**:配置经 Option 持久化,进入配置版本快照后随发布/回滚下发。 ### 1.2 非目标 @@ -35,12 +35,13 @@ | 条件 | 行为 | | --- | --- | | 开关开启,且响应状态码落在展开后的集合内 | 返回自定义/默认 HTML,**status 不变** | +| 开关开启且启用 GET-only,非 GET 请求返回匹配状态码 | 透传源站原始响应,不替换 | | 开关关闭 | 不生成 `error_page` 相关指令,透传 | | 状态码不在集合内 | 不替换 | | Pages 上游路由 | 不应用本功能 | | 源站成功返回 2xx/3xx/4xx(未配置时) | 不替换 | -实现上对反代 `location` 启用 `proxy_intercept_errors on`,因此**源站返回的**匹配 5xx 等也会被拦截,而不仅是网关本地生成的 502。 +全方法模式下对反代 `location` 启用 `proxy_intercept_errors on`,因此**源站返回的**匹配 5xx 等也会被拦截,而不仅是网关本地生成的 502;GET-only 模式改用 Lua header/body 过滤器仅替换 GET 响应正文。 ### 2.2 状态码标签语法 @@ -81,6 +82,7 @@ Tags Input 每条标签: | `origin_error_page_enabled` | bool 字符串 | `true` | 总开关 | | `origin_error_page_status_codes` | JSON 字符串数组 | `["500-599"]` | 原始标签 | | `origin_error_page_html` | 文本 | `""` | 空 = 内置默认;最大 **256 KiB** | +| `origin_error_page_get_only` | bool 字符串 | `false` | 仅对 GET 请求替换错误页,其它方法透传 | API 复用: @@ -106,6 +108,7 @@ API 复用: OriginErrorPageEnabled bool OriginErrorPageStatusCodes []string // 原始标签 OriginErrorPageHTML string // 空则渲染器用内置默认 +OriginErrorPageGetOnly bool ``` 构建快照时从 Option 读取;Agent 只消费快照,不直读控制面 DB。 @@ -121,26 +124,27 @@ OriginErrorPageHTML string // 空则渲染器用内置默认 ```nginx proxy_intercept_errors on; -error_page = /__openflare_origin_error; +error_page @__openflare_origin_error; -location = /__openflare_origin_error { - internal; +location @__openflare_origin_error { default_type text/html; charset utf-8; - # 保持 ngx.status 为原错误码 - # 读取模板,替换 {{status}} / {{host}} 后输出 body + content_by_lua_block { + # 读取模板,替换 {{status}} / {{host}} 后输出 body + # ngx.status 保持原错误码 + } } ``` ### 4.2 运行时替换 -采用 **internal location 内轻量 Lua(或现有 resty 能力)** 读模板并 `string.gsub` 替换占位符,**不**把 status 固化进静态文件(请求间状态码不同)。 +采用 **命名 location 内 `content_by_lua_block`** 读模板并替换占位符,**不**把 status 固化进静态文件(请求间状态码不同)。GET-only 模式在反代 location 内用 `header_filter_by_lua_block` + `body_filter_by_lua_block` 仅替换 GET 响应正文,非 GET 请求透传。 禁止将错误页统一改为 HTTP 200。 ### 4.3 关闭时 -不输出 `proxy_intercept_errors`、`error_page`、内部 location 与对应 SupportFile(或文件可写但不被引用)。 +不输出 `proxy_intercept_errors`、`error_page`、内部 location 与对应 SupportFile(或文件可写但不被引用)。GET-only 模式同时不输出 Lua 过滤器。 ### 4.4 与缓存 / stale @@ -152,8 +156,7 @@ location = /__openflare_origin_error { ### 5.1 入口 -* 侧栏「网站管理」新增:**错误页** → `/error-pages` -* 更新 `openflareWebsiteNavGroup`、`openflareWebsiteSubNav`(若使用)、全局搜索关键词 +* 侧栏「网站管理 → 响应页面」:错误页 Tab(`/responses`),编辑页 `/responses/error-page/edit`、预览页 `/responses/error-page/preview`。 ### 5.2 页面结构 @@ -165,14 +168,14 @@ location = /__openflare_origin_error { ### 5.3 组件依赖 -若仓库尚无 Tags Input,按项目 shadcn 流程添加;样式与现有 UI 一致。 +Tags Input 与 HTML 编辑器复用现有 shadcn/ui 组件,样式与现有 UI 一致。 --- ## 6. 数据流 ```text -管理员 /error-pages +管理员 /responses(错误页 Tab) → Option update-batch(校验标签与 HTML) → w_system_configs @@ -183,50 +186,13 @@ location = /__openflare_origin_error { 访客请求反代域名 → 源站/网关产生匹配状态码 - → error_page → internal location + → error_page → 命名 location → 替换占位符,status 保持原码,返回 HTML ``` --- -## 7. 测试与验收 - -### 7.1 自动化 - -* 状态码解析:单码、区间、去重、越界、反序、默认 `500-599` -* 渲染:enabled/disabled conf 片段;空 HTML 用默认;自定义进 SupportFile -* Option 校验:非法标签 / 超大 HTML → 4xx - -### 7.2 手动 - -1. 默认配置:源站不可达 → CF 风格页,真实 502/504,页内数字一致 -2. 源站返回 503 → 替换页,status 503 -3. 仅标签 `522` → 仅 522 替换 -4. 关闭开关并发布 → 透传恢复 -5. 自定义 HTML 占位符预览与线上一致 -6. Pages 路由不受影响 - -### 7.3 文档 - -* 本设计文档;`docs/design/index.md` 能力表;`docs/config.ts` 侧栏 -* changelog `[Unreleased]` 用户可读改进条 - ---- - -## 8. 实现要点清单(供计划拆分) - -1. goose seed 三个 Option key + model 常量 -2. 状态码解析/校验纯函数 + 单测 -3. Option update 路径挂接校验 -4. 快照填充 `ConfigSnapshot` 新字段 -5. `pkg/render/openresty`:error_page 块、SupportFile、默认 HTML、单测 -6. Agent 侧若需 Lua 辅助文件,随现有 nginx lua 目录同步 -7. 前端 Tags Input + `/error-pages` 页 + 导航 -8. changelog 与设计索引 - ---- - -## 9. 决策记录 +## 7. 决策记录 | 决策 | 选择 | 原因 | | --- | --- | --- | @@ -236,4 +202,3 @@ location = /__openflare_origin_error { | 响应 status | 保持原码 | 监控/SEO/客户端语义正确 | | 运行时替换 | internal + 轻量模板替换 | 每请求 status 不同 | | 自定义方式 | 在线 HTML | 灵活且无需文件上传链路 | -`} \ No newline at end of file diff --git a/docs/design/pages-design.md b/docs/design/pages-design.md index 6adf2a64..a9b81100 100644 --- a/docs/design/pages-design.md +++ b/docs/design/pages-design.md @@ -27,15 +27,13 @@ Pages 静态托管子系统包含以下核心能力: * **安全包校验与解压缩**:内置路径逃逸防御、防软链接劫持、文件大小/数量上限与可配置上传包体积控制,保障节点物理安全。 * **可配置限额**:管理员可在运维设置中调整「部署包大小上限」与「历史部署保留数」。 -### 部署源与未来构建边界 +### 部署源 项目当前支持 manual、Remote URL、GitHub Release 三种来源视图。无 source 记录即 manual;切换或删除 source 不删除历史 deployment,也不改变当前 active deployment。Remote URL 只允许手动“同步并发布”;GitHub Release 支持 latest/tag 手动检查与同步,只有 latest 可选择定时检查和自动更新。 -source 是可变配置,deployment 是不可变事实。source 配置与运行态游标、状态、租约分别存储;deployment 只保存创建时的安全 provenance 快照。所有产物都复用“下载或接收产物 → 真实字节与入口校验 → `upload.Ingest` → deployment”的 artifact pipeline:manual 上传停在 candidate,等待管理员显式激活;持久来源 sync 才在同一业务事务中 create-or-load 并原子激活。Agent 只消费 active deployment,不感知来源类型。 +source 是可变配置,deployment 是不可变事实。source 配置与运行态游标、状态、租约分别存储;deployment 只保存创建时的安全 provenance 快照。所有产物都复用“下载或接收产物 → 真实字节与入口校验 → `upload.Ingest` → deployment”的 artifact pipeline:manual 上传停在 candidate,等待管理员显式激活;持久来源 sync 才在同一业务事务中 create-or-load 并原子激活。 -后续从 Git 仓库拉取源码并自动构建时,将新增独立 `git_repository` provider 与隔离的 build executor。它输出受限的预构建产物后继续复用上述导入管线;不得把 clone、依赖安装或任意构建命令下发给 Agent,也不得把 branch/build/env 字段塞入现有 `github_release` source。当前 V2 不增加这些未来字段或空任务,只稳定 provider 输出、source discriminated view 与 deployment provenance 三个扩展边界。 - -管理端信息架构参考 Cloudflare Pages 当前把 [Git integration](https://developers.cloudflare.com/pages/configuration/git-integration/) 与 [Direct Upload](https://developers.cloudflare.com/pages/get-started/direct-upload/) 分离、并统一展示生产状态与历史部署的方式:OpenFlare 项目详情按“当前生产部署 → 部署源 → 部署历史”组织。OpenFlare 仍允许切换来源并保留历史部署,不采用 Cloudflare 项目创建后来源不可切换的限制。 +管理端项目详情按“当前生产部署 → 部署源 → 部署历史”组织。 --- @@ -67,7 +65,7 @@ graph TD ``` * **控制面(Control Plane)**:Server 接收本地上传,或通过受限 Provider 获取 Remote/GitHub 预构建产物;action task 与内部 scanner 负责检查、同步和自动更新。所有产物经统一 inspect 与 `upload.Ingest` 写入平台存储后端;manual 上传创建新的 candidate,持久来源 sync 则 create-or-load deployment 并原子激活。配置发布时只编译稳定的项目锚点与静态服务元数据。 -* **数据面(Data Plane)**:Agent 在心跳/WS 对账中发现配置引用的 Pages 项目,通过专属 API 拉取该项目当前激活包并执行校验解压缩。OpenResty 在本地提供静态文件服务;Agent 不感知产物来自上传、Remote、GitHub 或未来 build executor。 +* **数据面(Data Plane)**:Agent 在心跳/WS 对账中发现配置引用的 Pages 项目,通过专属 API 拉取该项目当前激活包并执行校验解压缩。OpenResty 在本地提供静态文件服务;Agent 不感知产物来自上传、Remote 或 GitHub。 --- diff --git a/docs/design/tunnel-design.md b/docs/design/tunnel-design.md index d4c42e8b..6510008f 100644 --- a/docs/design/tunnel-design.md +++ b/docs/design/tunnel-design.md @@ -116,14 +116,14 @@ Kill 并重新拉起 frps 进程 server_name intranet.example.com; # ... TLS 证书与 WAF 过滤逻辑 ... location / { - proxy_pass http://127.0.0.1:18080; # 指向本地 frps 的虚拟主机端口 + proxy_pass http://127.0.0.1:8080; # 指向本地 frps 的虚拟主机端口 proxy_set_header Host $host; # 必须保留原 Host,因为 frps 依靠 Host 进行内部路由分发 proxy_set_header X-Real-IP $remote_addr; } } ``` 2. **中继节点 (frps)**: - `frps` 监听到 `18080` 端口有 HTTP 请求进来,读取 HTTP 请求头中的 `Host: intranet.example.com`,在其已注册的活跃隧道表中检索该域名对应的加密 TCP 连接(由内网 frpc 建立)。 + `frps` 在虚拟主机端口(默认 `8080`)收到 HTTP 请求,读取 HTTP 请求头中的 `Host: intranet.example.com`,在其已注册的活跃隧道表中检索该域名对应的加密 TCP 连接(由内网 frpc 建立)。 3. **加密隧道传输 (TCP)**: `frps` 将 HTTP 请求封装进内部 TCP 隧道协议,发送给内网的 `frpc` 客户端。 4. **内网客户端分发 (frpc)**: diff --git a/docs/design/waf-design.md b/docs/design/waf-design.md index b187c0e7..9b4263e4 100644 --- a/docs/design/waf-design.md +++ b/docs/design/waf-design.md @@ -8,7 +8,7 @@ Server 保存带坐标和修订号的编辑图,发布时再次校验并编译 IP 组独立于规则拓扑更新。手动、订阅和自动 IP 组由控制面维护,Agent 先原子替换 JSON、最后更新 checksum。协调 Worker 每 5 秒检查 checksum,仅变化时读取完整快照并分发给其它 Worker;失败时保留上一份有效数据。完整运行时快照上限为 20 MiB,Server 发布/同步与 Agent 落盘使用同一序列化校验;OpenResty 使用独立的 64 MiB 共享字典和非淘汰写入,容量不足时拒绝新版本而不破坏已提交快照。 -地域节点使用 Country 与 City MMDB。Agent 首次启动时从程序内嵌数据库初始化缺失文件,后续按配置周期下载更新,请求处理始终读取 OpenResty 已加载的数据库。数据库不可用时地域匹配返回 `false` 并限频告警,不允许因数据损坏意外放行其它执行错误。 +地域节点使用 Country 与 City MMDB。Docker 镜像内置数据库文件,裸二进制安装由 Agent 首次启动时下载缺失文件,后续按配置周期更新,请求处理始终读取 OpenResty 已加载的数据库。数据库不可用时地域匹配返回 `false` 并限频告警,不允许因数据损坏意外放行其它执行错误。 ## 安全顺序 diff --git a/docs/design/waf-orchestration-design.md b/docs/design/waf-orchestration-design.md index 5292f215..8699b42e 100644 --- a/docs/design/waf-orchestration-design.md +++ b/docs/design/waf-orchestration-design.md @@ -6,7 +6,7 @@ 用户新增 WAF 规则时只输入名称。Server 随即创建一张合法的默认图 `开始 → 通过`,前端进入基于 React Flow 的独立编排页面。用户通过添加处理单元、配置节点并连接分支构建策略,不再填写固定顺序的黑白名单与 PoW 表单。 -第一阶段支持以下节点: +支持的节点: | 节点 | 数量约束 | 输入 | 输出 | 配置 | | --- | --- | --- | --- | --- | @@ -21,7 +21,7 @@ IP 匹配、地域匹配、UA 检查与安全防护不区分黑名单或白名单。`true` 只表示请求通过该节点判定,`false` 只表示未通过;放行或阻止的业务含义完全由连线决定。UA 检查的求值顺序为:要求携带 UA → 屏蔽爬虫/非正常 UA → 白名单匹配。安全防护在请求 Path/Query/Header/Cookie/Body(有限)上做特征匹配。PoW 验证完成后沿 `next` 继续,未完成时由挑战页面接管当前请求,不产生 `false` 分支。 -不在第一阶段实现循环、脚本节点、任意表达式节点、子图调用和跨规则跳转。 +不实现循环、脚本节点、任意表达式节点、子图调用和跨规则跳转。 ## 控制面架构 @@ -116,13 +116,3 @@ WAF 列表展示规则名称、启用状态、节点数量、应用路由数量 新 Worker 只接受完整且可解析的规则运行态配置。旧 Worker 在 OpenResty 优雅 reload 期间继续使用旧内存图,新 Worker 使用新图,因此请求不会观察到半更新状态。 地域数据库不可用时,地域匹配返回 `false` 并限频告警,保持现有行为。IP 组刷新失败时保留旧内存快照。PoW 未完成由挑战模块接管请求,不视为执行错误;PoW 节点配置先以短期键写入 OpenResty 共享内存,再通过 `ngx.exec` 的显式参数传给内部挑战处理器,不能依赖内部重定向保留 `ngx.ctx` 或隐式继承请求参数。发布快照中的空规则绑定必须编码为 JSON 空数组;运行时将旧快照中的 `null` 可选数组按空数组处理,禁止因 `cjson` 的 `ngx.null` userdata 中断请求。 - -## 测试与验收 - -* Go 单元测试覆盖图结构、端口、可达性、终止性、节点配置、体积限制、编译结果、修订冲突和绑定顺序。 -* 数据库测试覆盖 PostgreSQL/SQLite 迁移、默认图、旧绑定稳定排序和回滚。 -* Lua 测试覆盖所有节点出口、多规则顺序、全局规则前置、多个阻止响应、PoW 接管和损坏运行时图保护。 -* Agent/OpenResty 测试覆盖发布 reload、加载一次、失败回滚、IP 组五秒 checksum 刷新和旧快照保留。 -* 前端测试覆盖创建后导航、特殊节点唯一性、连线限制、属性编辑、即时校验、未保存提示和并发冲突。 -* 集成测试从控制面创建并编排规则,发布后用真实请求验证放行、阻止、PoW 和 IP 组热刷新。 -* API 变更后运行 `make swagger`;完成实现后运行前端检查与构建以及 `make code-check`。 diff --git a/docs/design/zone-design.md b/docs/design/zone-design.md index 5caeb5e7..ef5ad1bb 100644 --- a/docs/design/zone-design.md +++ b/docs/design/zone-design.md @@ -54,7 +54,7 @@ erDiagram * `GET/POST /api/v1/d/zones` * `GET/POST /api/v1/d/zones/:id/update` * `POST /api/v1/d/zones/:id/delete` -* `GET/POST /api/v1/d/zones/:id/domains` +* `POST /api/v1/d/zones/:id/domains`(列表经 overview 返回) * `POST /api/v1/d/zones/:id/domains/:domainID/update` * `POST /api/v1/d/zones/:id/domains/:domainID/delete` * `GET /api/v1/d/zones/:id/overview` @@ -91,10 +91,3 @@ WAF、Pages、上游与发布版本仍属于 `proxy_routes`。Zone 概览只聚 * 持久化:域名与证书只存在于 `of_zone_domains`;`of_proxy_routes` 仅保存路由策略(上游、缓存、限流、WAF 绑定键等)。 * 渲染:配置快照在内存中组装临时 `Domains` / `DomainCertIDs` 供 OpenResty 渲染,不写回数据库。 * 结构迁移仅使用 `internal/infra/persistence/migrator/goose/{postgres,sqlite}/*.sql`;启动时自动导入历史域名,第二阶段后旧列不存在则为空操作。 - -## 验证 - -* 单元测试:Public Suffix List 分组、FQDN / 通配符拒绝、跨 Zone 路由、证书 SAN 覆盖、删除保护及迁移幂等性;清理后断言旧列/旧表不存在。 -* 集成测试:Zone、Zone 域名与路由 API 的成功与失败响应;现有路由迁移后生成相同 OpenResty 域名与证书配置。 -* 前端测试:Zone 列表、ID 路由、详情加载 / 错误 / 空状态、域名选择器与 API 负载。 -* 手动验证:迁移前后比较激活配置快照中的 `server_name` 和证书路径,发布后使用根域及各子域请求验证路由。 diff --git a/docs/guide/certificates.md b/docs/guide/certificates.md index 015645cf..675129c1 100644 --- a/docs/guide/certificates.md +++ b/docs/guide/certificates.md @@ -12,35 +12,35 @@ 2. 点击右上角的 **「导入证书」**。 3. 填写配置信息: * **证书名称**:输入一个易于识别的别名(如 `my-domain-cert`)。 - * **证书内容 (PEM)**:复制并粘贴 PEM 格式 of 证书公钥内容(通常以 `-----BEGIN CERTIFICATE-----` 开头)。 - * **证书私钥 (KEY)**:复制并粘贴证书的私钥内容(通常以 `-----BEGIN PRIVATE KEY-----` 或 `-----BEGIN RSA PRIVATE KEY-----` 开头)。 + * **证书内容(PEM)**:复制并粘贴 PEM 格式的证书公钥内容(通常以 `-----BEGIN CERTIFICATE-----` 开头)。 + * **证书私钥(KEY)**:复制并粘贴证书的私钥内容(通常以 `-----BEGIN PRIVATE KEY-----` 或 `-----BEGIN RSA PRIVATE KEY-----` 开头)。 4. 点击 **「保存」**。导入成功后,该证书即可在配置域名时直接绑定使用。 --- -## 方式二:自动申请与到期自动续签 (ACME) +## 方式二:自动申请与到期自动续签(ACME) -OpenFlare 内置了 ACME 客户端并对接了 **Asynq 异步任务队列**。通过配合云解析服务商的 DNS API,系统能自动完成 DNS-01 挑战(Challenge)校验,并向 CA(默认 Let's Encrypt)申请通配符/单域名证书,并在**到期前 30 天自动触发后台秒级续签**。 +OpenFlare 内置了 ACME 客户端并对接了 **Asynq 异步任务队列**。通过配合云解析服务商的 DNS API,系统能自动完成 DNS-01 挑战(Challenge)校验,并向 CA(默认 Let's Encrypt)申请通配符/单域名证书,并在**到期前 7 天自动触发续签**。 ### 第一步:在 Cloudflare 申请 DNS API Token 为了使 OpenFlare 能够自动在你的域名下添加 TXT 记录以完成 DNS 校验,你需要准备一个具有特定权限的 Cloudflare API Token。 > [!IMPORTANT] -> 安全起见,**强烈建议使用限定权限的 API Token**,而非全局 API Key (Global API Key)。 +> 安全起见,**强烈建议使用限定权限的 API Token**,而非全局 API Key(Global API Key)。 1. 登录 [Cloudflare 控制台](https://dash.cloudflare.com/)。 -2. 点击右上角的用户头像,选择 **「我的个人资料 (My Profile)」**。 -3. 在左侧菜单中选择 **「API 令牌 (API Tokens)」**,然后点击 **「创建令牌 (Create Token)」**。 -4. 找到 **「编辑区域 DNS (Edit Zone DNS)」** 模板,点击 **「使用模板 (Use template)」**。 +2. 点击右上角的用户头像,选择 **「我的个人资料(My Profile)」**。 +3. 在左侧菜单中选择 **「API 令牌(API Tokens)」**,然后点击 **「创建令牌(Create Token)」**。 +4. 找到 **「编辑区域 DNS(Edit Zone DNS)」** 模板,点击 **「使用模板(Use template)」**。 5. 配置令牌权限与范围(保持默认或根据实际情况限定): - * **权限 (Permissions)**: - * `区域 (Zone)` - `DNS` - `编辑 (Edit)` (必须,ACME 写入 TXT 记录用) - * `区域 (Zone)` - `区域 (Zone)` - `读取 (Read)` (必须,用于列出和检索区域 ID) - * **区域资源 (Zone Resources)**: - * 选择 **「包括 (Include)」** -> **「所有区域 (All zones)」**,或者选择 **「特定区域 (Specific zone)」** 并指向你托管的特定域名。 -6. 点击 **「继续以转到摘要 (Continue to summary)」**,确认无误后点击 **「创建令牌 (Create Token)」**。 -7. 复制生成的 **API 令牌 (Token)** 字符串。*注意:该令牌仅展示一次,请妥善保存*。 + * **权限(Permissions)**: + * `区域(Zone)` - `DNS` - `编辑(Edit)`(必须,ACME 写入 TXT 记录用) + * `区域(Zone)` - `区域(Zone)` - `读取(Read)`(必须,用于列出和检索区域 ID) + * **区域资源(Zone Resources)**: + * 选择 **「包括(Include)」** -> **「所有区域(All zones)」**,或者选择 **「特定区域(Specific zone)」** 并指向你托管的特定域名。 +6. 点击 **「继续以转到摘要(Continue to summary)」**,确认无误后点击 **「创建令牌(Create Token)」**。 +7. 复制生成的 **API 令牌(Token)** 字符串。该令牌仅展示一次,请妥善保存。 ### 第二步:在控制端添加 DNS 账号 @@ -49,7 +49,7 @@ OpenFlare 内置了 ACME 客户端并对接了 **Asynq 异步任务队列**。 3. 填写配置信息: * **账号名称**:如 `cloudflare-main`。 * **DNS 服务商**:选择 `Cloudflare`。 - * **API Token**:填入刚刚在 Cloudflare 复制的 API 令牌(该值在入库时会自动加密存储,保障安全)。 + * **API Token**:填入刚刚在 Cloudflare 复制的 API 令牌(该值在入库时会自动加密存储)。 4. 点击 **「保存」**。 ### 第三步:提交证书申请任务 @@ -65,4 +65,4 @@ OpenFlare 内置了 ACME 客户端并对接了 **Asynq 异步任务队列**。 ### 第四步:查看申请进度与续期状态 - **查看实时进度**:保存后,系统会向 Asynq 队列投递单证书续期/申请任务(`of_ssl_single_renew`)。你可以进入管理后台的任务或节点日志页面,实时查看每一步(添加 TXT 记录、DNS 记录全球生效探测、ACME 验证、证书颁发落地等)的详细日志。 -- **自动续期**:所有通过 ACME 申请的证书都会被系统自动托管。后台的 Scheduler 每日会自动扫描证书有效期,在到期前 30 天自动通过异步任务触发续签,无需任何手动维护。 +- **自动续期**:所有通过 ACME 申请的证书都会被系统自动托管。后台的 Scheduler 每日会自动扫描证书有效期,在到期前 7 天自动通过异步任务触发续签,无需任何手动维护。 diff --git a/docs/guide/credits.md b/docs/guide/credits.md index 602f362a..d72073b3 100644 --- a/docs/guide/credits.md +++ b/docs/guide/credits.md @@ -1,6 +1,6 @@ # 引用与致谢 -OpenFlare 本质上是一个方案整合项目, 在设计与实现过程中借鉴了众多开源项目的优秀理念、架构设计和技术实现。以下是 OpenFlare 在核心底层引擎、安全防护机制以及前后端系统框架等方面所引用的关键开源项目,以及对这些项目及其社区的感谢。 +OpenFlare 在设计与实现过程中借鉴了众多开源项目的优秀理念、架构设计和技术实现。以下是 OpenFlare 在核心底层引擎、安全防护机制以及前后端系统框架等方面所引用的关键开源项目,在此对这些项目及其社区表示感谢。 --- @@ -9,14 +9,14 @@ OpenFlare 本质上是一个方案整合项目, 在设计与实现过程中借 * **在 OpenFlare 中的作用**:作为全局数据面(Data Plane)的边缘网关。所有的公网 Web 流量均首先由 OpenResty 接收,在此处进行高并发的 HTTPS 握手、WAF 安全规则比对、防 CC 人机验证,并最终执行反向代理转发。 * **项目链接**:[OpenResty 官网](https://openresty.org/) -### 2. FRP (Fast Reverse Proxy) +### 2. FRP(Fast Reverse Proxy) * **项目定位**:高性能的反向代理应用,专注于内网穿透。 * **在 OpenFlare 中的作用**:作为内网穿透子系统的底层隧道引擎。中继端管理器 `openflare-relay` 负责守护和调度 `frps` 引擎,而内网客户端 `openflared` 则负责在本地自动生成 TOML 配置并守护多路复用 `frpc` 子进程。 * **项目链接**:[fatedier/frp (GitHub)](https://github.com/fatedier/frp) --- -### 3. Anubis (PoW 方案) +### 3. Anubis(PoW 方案) * **项目定位**:基于工作量证明(Proof of Work)的轻量级人机验证防护方案。 * **在 OpenFlare 中的作用**:为网关 WAF 提供了核心的**无感防 CC 人机挑战**能力。 diff --git a/docs/guide/first-site.md b/docs/guide/first-site.md index 6f9394e8..229f0f2f 100644 --- a/docs/guide/first-site.md +++ b/docs/guide/first-site.md @@ -23,15 +23,15 @@ OpenFlare 的发布链路以“不可变配置版本”为核心。你在管理 为了快速验证,我们首先部署一个最基础的 HTTP 反代站点: -1. 登录控制面板,进入左侧导航 **「网站管理」->「域名列表」**,点击 **「新增网站」**。 +1. 登录控制面板,进入左侧导航 **「网站管理」->「域名列表」**,点击 **「新增 Zone」**。 2. 填写域名配置: * **域名**:输入用于测试的域名(如 `first.example.com`)。 * **绑定证书**:选择不绑定证书(作为 HTTP 快速验证)。 - * 点击保存,完成网站登记。 -3. 进入左侧导航 **「规则管理」**,点击 **「新增规则」**: + * 点击保存,完成域名登记。 +3. 进入左侧导航 **「规则管理」**,点击 **「新建规则」**: * **规则名称**:输入简易标识(如 `first-app-route`)。 * **域名匹配**:填入你的测试域名(如 `first.example.com`)。 - * 在下方 **「反向代理」** 选项卡中,配置 **源站类型** 为「标准反代」 (Direct)。 + * 在下方 **「反向代理」** 选项卡中,配置 **回源方式** 为「直连上游」。 * **上游地址**:填写后端服务地址(如测试专用的 `http://httpbin.org`)。 * 点击保存创建规则。 @@ -45,8 +45,8 @@ OpenFlare 的发布链路以“不可变配置版本”为核心。你在管理 新增的网站配置仍保存在 Server 的数据库中,处于草稿状态,需要通过发布版本分发到数据面: -1. 点击控制面板右上角的 **「配置预览」** 按钮,系统会展示本次新增路由的物理配置文件 Diff 差异。 -2. 确认渲染出的配置内容正确无误后,点击 **「发布并激活」**。 +1. 点击控制面板右上角的 **「预览并发布」** 按钮,系统会展示本次新增路由的物理配置文件 Diff 差异。 +2. 确认渲染出的配置内容正确无误后,点击 **「确认发布」**。 3. 控制面将生成一个唯一的配置版本号(格式为 `YYYYMMDD-NNN`)。 --- diff --git a/docs/guide/index.md b/docs/guide/index.md index 150b13da..48c13bf8 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -1,6 +1,6 @@ # 指南 -你会学到:OpenFlare 文档如何组织、首次运行应该读哪些页面,以及部署、使用、排查和开发分别从哪里开始。 +你会学到:OpenFlare 文档如何组织、首次运行应该读哪些页面,以及部署、使用、排查分别从哪里开始。 OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站配置、配置版本发布、Agent 节点同步、TLS 证书和基础观测放到一个管理端中,适合单团队或单组织管理多台代理节点。 @@ -17,8 +17,8 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站 7. [WAF 安全防护使用](./waf-usage.md):配置 WAF 规则组,掌握 IP 黑白名单、自动/订阅 IP 组、地域限制与 PoW CC 防护。 8. [WAF 自动 IP 组语法](./waf-ip-group-expr.md):编写自动 IP 组 Expr 规则,了解关键字含义和预设规则。 9. [Uptime Kuma 监控同步](./uptime-kuma.md):配置并使用 Uptime Kuma 自动差分同步和监控范围控制。 -10. [SSO 登录配置](./sso.md):配置 GitHub 或 OIDC 实现第三方单点登录 (SSO) 接入。 -11. [故障排查](./troubleshooting.md):按症状排查登录、数据库、节点同步、OpenResty、边缘缓存命中与前端构建问题。 +10. [SSO 登录配置](./sso.md):配置 OIDC 实现第三方单点登录(SSO)接入。 +11. [故障排查](./troubleshooting.md):按症状排查登录、数据库、节点同步、OpenResty 与边缘缓存命中问题。 12. [引用与致谢](./credits.md):查看系统依赖的优秀开源项目与社区致谢清单。 ## 按角色查找 @@ -36,7 +36,7 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站 | 自动同步监测站点状态 | [Uptime Kuma 监控同步](./uptime-kuma.md) | | 接入或重装节点 Agent | [接入 Agent](../deployment/agent.md) | | 从源码启动 Server | [启动 Server](../deployment/server.md) | -| 配置 GitHub 或 OIDC 登录 | [SSO 登录配置](./sso.md) | +| 配置 OIDC 登录 | [SSO 登录配置](./sso.md) | | 升级 Server 或 Agent | [升级与维护](../deployment/upgrade.md) | | 理解架构和发布模型 | [系统架构](../design/architecture.md) 与 [Agent 与发布模型](../design/agent-design.md) | | 查看开源引用与致谢 | [引用与致谢](./credits.md) | diff --git a/docs/guide/pages-usage.md b/docs/guide/pages-usage.md index 752593ec..28ab013e 100644 --- a/docs/guide/pages-usage.md +++ b/docs/guide/pages-usage.md @@ -59,12 +59,12 @@ GitHub 来源仅支持公开 `github.com` 仓库。填写: 两种选择都可手动 **「检查更新」** 和 **「同步并发布」**。区别如下: -* **latest**:可设置 5~1440 分钟检查间隔,默认 60 分钟;自动更新默认关闭。开启后,scanner 发现新 revision 才会异步同步并发布。 +* **latest**:可设置 5~1440 分钟检查间隔,默认 1440 分钟(24 小时);自动更新默认关闭。开启后,scanner 发现新 revision 才会异步同步并发布。 * **tag**:只支持管理员手动检查和同步,不参与定时 scanner。 “检查更新”只解析 Release/asset 并更新版本游标,不下载部署包;“同步并发布”才会下载、校验、创建或复用 deployment 并激活。如果同一个 Release 下的 asset 被替换,来源会进入 **「需要确认」**,必须确认页面显示的精确 revision 后才能发布,避免静默覆盖。 -GitHub Release 在这里是预构建产物源,不等同于连接代码仓库自动构建。未来仓库集成会使用独立的 `git_repository` 来源和 Server build executor,再把构建产物送入同一部署管线。 +GitHub Release 来源只导入预构建产物,不执行仓库源码构建。 ### 4. 切换或删除来源 diff --git a/docs/guide/proxy-config.md b/docs/guide/proxy-config.md index c8a89115..677f0044 100644 --- a/docs/guide/proxy-config.md +++ b/docs/guide/proxy-config.md @@ -9,7 +9,7 @@ 在网关控制面中,建议遵循以下步骤新增反代规则: ```text - [ 步骤 1. 证书管理 ] ──► [ 步骤 2. 源站定义 (可选) ] ──► [ 步骤 3. 新增网站配置 ] + [ 步骤 1. 证书管理 ] ──► [ 步骤 2. 源站定义(可选) ] ──► [ 步骤 3. 新增网站配置 ] │ [ 步骤 5. 验证访问 ] ◄── [ 步骤 4. 发布与激活版本 ] ◄───────────────┘ ``` @@ -28,7 +28,7 @@ 源站(Origin)代表被代理的后端真实服务地址。虽然在新建网站时可以直接填写 IP,但推荐先在源站库中进行注册,以便后续复用与维护: -1. 进入左侧导航 **「网站管理」->「源站地址」**,点击 **「创建源站」**。 +1. 进入左侧导航 **「网站管理」->「源站地址」**,点击 **「新增源站」**。 2. 填写源站名称(如 `production-api`)。 3. 填入合法的上游地址(如 `http://10.0.0.10:8080`),点击保存。 @@ -38,13 +38,13 @@ 证书和源站就绪后,即可创建核心网站代理路由: -1. 进入左侧导航 **「网站管理」->「域名列表」**,点击 **「新增网站」**: +1. 进入左侧导航 **「网站管理」->「域名列表」**,点击 **「新增 Zone」**: * **域名**:输入该站点绑定的域名。 * **绑定证书**:选择第一步准备或申请好的证书。 -2. 配置请求路由规则:进入 **「规则管理」** 页面,点击 **「新增规则」** 或编辑已有规则: +2. 配置请求路由规则:进入 **「规则管理」** 页面,点击 **「新建规则」** 或编辑已有规则: * **规则名称**:输入规则的唯一简易标识(如 `app-portal-route`)。 * **域名匹配**:填入对应的域名(支持通配符或精确域名,需与上面登记的域名一致)。 - * 在下方 **「反向代理」** 选项卡下,选择源站类型为 **「标准反代」**。 + * 在下方 **「反向代理」** 选项卡下,选择 **回源方式** 为「直连上游」。 * **源站选择**:从下拉框中选择第二步创建的源站;或者选择手动输入并填入 `http://10.0.0.20:9000`。 3. 点击保存创建配置。 @@ -54,13 +54,13 @@ 你在管理端新增的网站配置仅保存在 Server 数据库中,**不会立即生效**。必须生成配置版本快照并分发到 Agent 边缘节点: -1. 点击控制面板右上角的 **「配置预览」** 按钮。 +1. 点击控制面板右上角的 **「预览并发布」** 按钮。 2. 检查配置文件的 Diff 差异,确认你刚刚新增的 `server` 块以及证书绑定规则无误。 -3. 点击 **「发布并激活」** 按钮。 +3. 点击 **「确认发布」** 按钮。 4. **Agent 落地机制**: * 数据面的 Agent 节点在心跳中发现激活的版本 Checksum 变更,会自动拉取完整的 OpenResty 配置文件和证书包到本地。 * 自动在本地执行配置校验(类似于 `openresty -t`),确认无语法错误后,执行平滑重载(`reload`)。 - * *如果重载或校验失败,Agent 会安全阻断并回滚至上一稳定版本,保证节点高可用。* + * 如果重载或校验失败,Agent 会安全阻断并回滚至上一稳定版本,保证节点高可用。 --- @@ -80,9 +80,9 @@ ### 2. 一键秒级回滚 如果发布的新配置导致了线上业务异常: -1. 导航至左侧 **「配置版本」** 菜单。 +1. 导航至左侧 **「版本发布」** 菜单。 2. 在历史列表中找到发布前的上一个稳定版本。 -3. 点击 **「激活此版本」**。 +3. 点击 **「激活」**。 4. 所有在线 Agent 节点将在秒级自动重载回历史配置,实现秒级避险。 --- diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md index c1e7cef1..cf3f7bbb 100644 --- a/docs/guide/quick-start.md +++ b/docs/guide/quick-start.md @@ -19,16 +19,12 @@ Agent 统一通过 OpenResty 二进制控制运行时。本地部署需要节点 | Docker / Docker Compose | 用于启动 Server 及其依赖的 PostgreSQL、Valkey;如采用 Docker Agent,也用于运行 Agent | | OpenResty | 本地安装 Agent 时需要可执行 `openresty`,或在安装脚本中指定路径 | | 可访问端口 | Server 默认监听 `3000`,Agent 节点需要能访问 Server 地址 | -| 浏览器 | 用于访问管理端 | - -- **Docker**:`20.10.0+` -- **Docker Compose**:`2.0.0+` --- ## 1. 启动 Server -快速开始推荐采用 **PostgreSQL + Redis ** 标准部署方案。 +快速开始推荐采用 **PostgreSQL + Valkey** 标准部署方案。 在空目录中创建 `docker-compose.yaml`: @@ -123,12 +119,14 @@ http://localhost:3000 > [!WARNING] > 为了你的系统安全,首次登录后请立即修改默认密码。 -如果忘记密码并且没有配置找回密码渠道, 可以使用命令进行重置 +如果忘记密码并且没有配置找回密码渠道,可以使用命令重置: ```bash -go run main.go reset-paswd # 重置管理员密码 +go run main.go reset-passwd --user admin ``` +未指定 `--password` 时命令会自动生成随机密码并输出到终端;也可以使用 `--password` 显式指定新密码。 + --- ## 2. 准备 Agent Token @@ -142,14 +140,14 @@ Agent 可以用两类凭证接入: 在管理端准备其中一种凭证后,进入下一步。 -- **`discovery_token`** 获取菜单路径:「系统设置」 (Settings) -> 「OpenFlare」选项卡 -> 「自动注册」凭证 +- **`discovery_token`** 获取菜单路径:「系统设置」->「OpenFlare」选项卡 ->「Discovery Token 与部署」中的 Discovery Token - **`agent_token`** 获取菜单路径:在「节点管理」中创建节点后,点击进入节点详情页即可查看到对应的专属 Token。 --- ## 3. 安装/运行 Agent -Agent 部署方式推荐使用 Docker 部署(即直接运行内置 OpenResty 的 Agent 镜像);亦支持通过安装脚本将 Agent 部署在本地宿主机上。 +推荐使用 Docker 镜像部署 Agent;也可以通过安装脚本部署到本地宿主机。 ### 方式 A:Docker 运行 Agent(推荐) @@ -217,17 +215,17 @@ journalctl -u openflare-agent -f --- -## 常见失败原因 +## 遇到问题时 -| 现象 | 排查方向 | -| --- | --- | -| 浏览器打不开管理端 | 确认 `docker compose ps` 中 Server 正在运行,宿主机 `3000` 端口没有被占用 | -| 登录后数据无法保存/提示报错 | 检查 PostgreSQL 容器健康状态,以及 `DB_PASSWORD` / 密码等连接参数是否一致 | -| Agent 无法注册 | 确认 Agent 节点能访问 `--server-url`,并检查 Token 是否填错或已失效 | -| Agent 在线但没有应用配置 | 确认网站配置已启用,并且已经发布并激活版本 | -| OpenResty 应用失败 | 查看节点应用记录和 `journalctl -u openflare-agent`,重点检查域名、证书、上游地址和端口占用 | +按以下顺序处理: -更多排查路径见 [故障排查](./troubleshooting.md)。 +1. 将 Server 与 Agent 升级到最新版本,确认问题是否仍然存在。 +2. 重新发布并激活配置版本,等待节点应用。 +3. 在节点详情页对目标节点执行「强制同步」,推动节点立即拉取最新配置。 +4. 重建或重装 Agent(重新执行安装脚本)。 +5. 上述步骤均无效时,携带 Server 日志与节点应用记录提交 [GitHub Issue](https://github.com/Rain-kl/OpenFlare/issues)。 + +更多排查思路见 [故障排查](./troubleshooting.md)。 --- diff --git a/docs/guide/sso.md b/docs/guide/sso.md index a358010a..1250580d 100644 --- a/docs/guide/sso.md +++ b/docs/guide/sso.md @@ -1,72 +1,51 @@ # SSO 登录配置 -你会学到:如何为 OpenFlare 配置 GitHub OAuth 或标准 OIDC 登录入口,如何填写回调地址,以及第三方账号如何绑定本地用户。 +你会学到:如何为 OpenFlare 配置 OIDC 第三方登录入口、填写回调地址,以及第三方账号如何绑定本地用户。 -OpenFlare 支持通过认证源配置第三方登录入口。当前支持 GitHub OAuth 与标准 OIDC Provider,例如 Logto、authentik、Keycloak、Casdoor 等。 +OpenFlare 通过 OIDC 认证源接入第三方登录。任意提供标准 OIDC Discovery 的服务(如 Google、Keycloak、authentik、Logto、Casdoor 等)都可以接入。 认证源配置完成并启用后,会显示在登录页的第三方账号登录区域。用户可以通过第三方账号登录,也可以在已登录状态下把第三方账号绑定到当前本地账号。 ## 使用前准备 -你需要先准备: - | 项目 | 说明 | | --- | --- | -| OpenFlare 访问地址 | 用户浏览器实际访问的地址,例如 `https://openflare.example.com` | -| 认证源名称 | OpenFlare 内部唯一标识,例如 `github`、`company-oidc` | +| 服务器访问地址 | 在管理端「系统设置」->「系统设置」选项卡 ->「通用设置」中配置,须与用户浏览器实际访问的地址一致(协议、域名、端口) | +| 认证源名称 | OpenFlare 内部唯一标识,例如 `company-oidc` | | Client ID | 第三方平台创建应用后提供 | | Client Secret | 第三方平台创建应用后提供 | -| OIDC Discovery URL | 仅 OIDC 需要,例如 `https://idp.example.com/.well-known/openid-configuration` | +| OIDC Discovery URL | 例如 `https://idp.example.com/.well-known/openid-configuration` | -**确认系统设置->通用设置->服务器地址能正确和域名匹配** - -认证源名称只能包含字母、数字、短横线或下划线,并且必须以字母或数字开头。认证源名称会出现在回调地址中,保存后如需修改名称,也必须同步修改第三方平台中的回调地址。 +认证源名称只能包含字母、数字、短横线或下划线,并且必须以字母或数字开头。 ## 回调地址 -第三方平台中的 Redirect URI / Callback URL 填写格式为: +第三方平台中的 Redirect URI / Callback URL 固定填写: ```text -/oauth/<认证源名称> +<服务器访问地址>/login ``` -示例: +例如服务器访问地址为 `https://openflare.example.com` 时: ```text -https://openflare.example.com/oauth/github -https://openflare.example.com/oauth/company-oidc +https://openflare.example.com/login ``` -在管理端新增或修改认证源时,表单会根据当前浏览器访问地址和你输入的认证源名称自动显示应填写的回调地址。 - -## 配置 GitHub 登录 - -1. 在 GitHub 创建 OAuth App。 -2. `Homepage URL` 填写 OpenFlare 访问地址。 -3. `Authorization callback URL` 填写 OpenFlare 显示的回调地址,例如 `https://openflare.example.com/oauth/github`。 -4. 复制 GitHub 提供的 Client ID 和 Client Secret。 -5. 登录 OpenFlare 管理端,进入左侧导航 **「系统设置」** (Settings),选择 **「安全设置」** 选项卡,在 **「认证源管理」** 栏目中进行配置。 -6. 新增认证源,类型选择 `GitHub`。 -7. 填写认证源名称、展示名称、Client ID、Client Secret。 -8. Scope 默认使用 `user:email`,通常无需修改。 -9. 保存并启用认证源。 - -启用后,登录页会显示对应的 GitHub 登录按钮。 +回调地址只与「服务器访问地址」相关,不包含认证源名称。第三方平台授权完成后会跳转到该地址,OpenFlare 登录页携带授权码完成登录或绑定。 ## 配置 OIDC 登录 -1. 在 OIDC Provider 中创建应用或客户端。 -2. 应用类型选择 Web / Confidential Client。 -3. Redirect URI / Callback URL 填写 OpenFlare 显示的回调地址,例如 `https://openflare.example.com/oauth/company-oidc`。 -4. 复制 Client ID 和 Client Secret。 -5. 获取 Provider 的 Discovery URL,通常以 `/.well-known/openid-configuration` 结尾。 -6. 登录 OpenFlare 管理端,进入左侧导航 **「系统设置」** (Settings),选择 **「安全设置」** 选项卡,在 **「认证源管理」** 栏目中进行配置。 -7. 新增认证源,类型选择 `OIDC`。 -8. 填写认证源名称、展示名称、Client ID、Client Secret、OIDC Discovery URL。 -9. Scope 默认使用 `openid profile email`。如果 Provider 限制了 scope,请按 Provider 允许的值调整。 -10. 保存并启用认证源。 +1. 在 OIDC Provider 中创建应用或客户端,应用类型选择 Web / Confidential Client。 +2. Redirect URI / Callback URL 填写 `<服务器访问地址>/login`。 +3. 复制 Client ID 和 Client Secret。 +4. 获取 Provider 的 Discovery URL,通常以 `/.well-known/openid-configuration` 结尾。 +5. 登录 OpenFlare 管理端,进入左侧导航 **「系统设置」**,选择 **「安全设置」** 选项卡,在 **「认证源管理」** 栏目中新增认证源。 +6. 类型选择 `OIDC`,填写认证源名称、展示名称、Client ID、Client Secret、OIDC Discovery URL。 +7. Scope 默认使用 `openid profile email`。如果 Provider 限制了 scope,请按 Provider 允许的值调整。 +8. 保存并启用认证源。 -启用后,登录页会显示对应的 OIDC 登录按钮。 +启用后,登录页会显示对应的第三方登录按钮。 ## 登录与绑定行为 @@ -85,17 +64,17 @@ https://openflare.example.com/oauth/company-oidc 修改认证源时,Client Secret 输入框留空表示保留已有密钥;填写新值则会覆盖保存。 -如果修改了认证源名称,回调地址也会随之变化。你必须到第三方平台同步修改 Redirect URI / Callback URL,否则第三方平台会拒绝回调或返回错误。 +修改认证源名称不会影响回调地址,无需同步修改第三方平台配置。 ## 常见问题 ### 返回 `invalid_scope` -说明第三方平台不允许当前配置的 Scope。OIDC 默认 Scope 是 `openid profile email`,GitHub 默认 Scope 是 `user:email`。请到认证源编辑页调整 Scope,或在第三方平台放行对应 Scope。 +说明第三方平台不允许当前配置的 Scope。OIDC 默认 Scope 是 `openid profile email`。请到认证源编辑页调整 Scope,或在第三方平台放行对应 Scope。 ### 提示回调地址不匹配 -检查第三方平台中配置的 Redirect URI / Callback URL 是否与 OpenFlare 表单提示完全一致。协议、域名、端口和路径都必须一致。 +检查第三方平台中配置的 Redirect URI / Callback URL 是否与 `<服务器访问地址>/login` 完全一致。协议、域名、端口和路径都必须一致。 ### 登录页没有显示第三方登录按钮 diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md index 4a7300a7..52029683 100644 --- a/docs/guide/troubleshooting.md +++ b/docs/guide/troubleshooting.md @@ -1,6 +1,6 @@ # 故障排查 -你会学到:如何按症状排查 OpenFlare Server、数据库、登录、Agent、OpenResty、配置发布和前端构建问题。 +你会学到:如何按症状排查 OpenFlare Server、数据库、登录、Agent、OpenResty 和配置发布问题。 排查时先确认问题发生在哪一层:浏览器、Server、数据库、Agent、OpenResty、源站或 DNS。OpenFlare 的配置不会直接在线写入所有节点,只有激活版本变化后,Agent 才会在 heartbeat 中发现并应用。 @@ -9,7 +9,7 @@ | 现象 | 先看哪里 | | --- | --- | | 管理端打不开 | Server 容器或进程日志、端口监听 | -| 登录异常 | 默认账号、OPENFLARE_TOKEN、浏览器请求、Server 日志 | +| 登录异常 | 默认账号、Session Cookie、Server 日志 | | 数据无法保存 | 数据库连接、SQLite 文件权限、PostgreSQL 健康状态 | | Agent 离线 | Agent 日志、Token、Server 地址、网络连通性 | | 发布后节点未更新 | 激活版本、节点 heartbeat、应用记录 | @@ -50,7 +50,7 @@ ls -ld "$(dirname /path/to/openflare.db)" | 日志或现象 | 处理 | | --- | --- | -| 数据库连接失败 | 检查 `DSN` 中用户名、密码、主机、端口、库名和 `sslmode` | +| 数据库连接失败 | 检查 `DB_HOST`、`DB_PORT`、`DB_USERNAME`、`DB_PASSWORD`、`DB_NAME`、`DB_SSL_MODE` 是否一致 | | SQLite 无法创建文件 | 检查 `SQLITE_PATH` 所在目录是否存在且可写 | | 端口被占用 | 修改 `PORT` 或 `--port`,或停止占用端口的进程 | @@ -62,21 +62,7 @@ ls -ld "$(dirname /path/to/openflare.db)" curl -I http://127.0.0.1:3000 ``` -2. 如果是源码运行,确认已经构建前端静态产物: - -```bash -cd frontend -pnpm build -``` - -3. 检查浏览器访问地址是否与反向代理配置一致。 - -4. 如果通过前端开发服务器访问,确认后端代理地址: - -```bash -cd frontend -NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev -``` +2. 检查浏览器访问地址是否与反向代理配置一致。 ## 默认账号无法登录 @@ -84,32 +70,20 @@ NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev 排查步骤: -1. 确认连接的是预期数据库,避免 `SQLITE_PATH` 或 `DSN` 指向了另一个环境。 +1. 确认连接的是预期数据库,避免 `SQLITE_PATH` 或 `DB_HOST` / `DB_NAME` 指向了另一个环境。 2. 查看 Server 日志中使用的是 `sqlite` 还是 `postgres`。 3. 在浏览器开发者工具中确认管理端 API 请求已正确携带 Session Cookie。 4. 清理浏览器缓存及 Cookie 后重新登录。 ### 应急重置管理员密码 -如果忘记了 `admin` 账户的密码,可以通过直接更新数据库中的密码哈希值将其重置为 `12345678`(登录后请务必立即修改): +忘记 `admin` 账户密码时,使用 `reset-passwd` 命令重置(支持 SQLite 与 PostgreSQL): -#### 1. 若使用 SQLite 数据库 -停止 Server 运行,使用 sqlite3 客户端打开数据库文件: ```bash -sqlite3 /path/to/openflare.db +go run main.go reset-passwd --user admin --password your-new-password ``` -执行以下 SQL 语句: -```sql -UPDATE users SET password = '$2a$10$eXpE9i/6S3gPT94/G0mu0.B8ser66ARETFz5NWYSYcrQ4JmtSrMXu' WHERE username = 'admin'; -``` -输入 `.exit` 退出并重新启动 Server。 -#### 2. 若使用 PostgreSQL 数据库 -通过您的数据库连接工具(如 psql、pgAdmin 或 DBeaver)连接到 PostgreSQL 实例,选择对应的 `openflare` 数据库,执行以下 SQL 语句: -```sql -UPDATE users SET password = '$2a$10$eXpE9i/6S3gPT94/G0mu0.B8ser66ARETFz5NWYSYcrQ4JmtSrMXu' WHERE username = 'admin'; -``` -执行成功后即可使用默认密码 `12345678` 重新登录管理后台。 +若使用 SQLite,建议先停止 Server 进程再执行,避免数据库文件锁冲突。未指定 `--password` 时命令会生成随机密码并输出到终端。重置成功后请立即登录并修改密码。 ## Agent 无法注册或一直离线 @@ -216,29 +190,6 @@ curl -Iv https://your-domain 4. 检查 `openresty_observability_port` 是否被占用,默认是 `18081`。 5. 确认 Server 侧没有因数据库清理策略删除对应时间窗口数据。 -## 前端构建失败 - -执行: - -```bash -cd frontend -corepack enable -pnpm install -pnpm lint -pnpm typecheck -pnpm test -pnpm build -``` - -常见原因: - -| 现象 | 处理 | -| --- | --- | -| pnpm 版本不一致 | 使用 `corepack enable` 后重新安装 | -| 类型错误 | 先运行 `pnpm typecheck` 定位具体文件 | -| API 类型不一致 | 检查 `lib/api/` 和 `types/` 中的响应结构 | -| E2E 失败 | 确认 Server 和前端开发服务器都已启动 | - ## 边缘缓存命中率异常 访问日志中缓存三态:**命中**(HIT/STALE/REVALIDATED/UPDATING)、**回源**(MISS/EXPIRED)、**未缓存**(BYPASS 或空,请求时未进入可缓存路径或响应未入库)。设计说明见 [边缘缓存策略设计](../design/edge-cache-design.md)。 @@ -269,12 +220,3 @@ pnpm build * 响应带 `Set-Cookie` 或 `private`:**不入库**。 * 无源站缓存头的可缓存状态码:使用默认 Edge TTL(如 200 约 120 分钟)。 -## 文档站构建失败 - -```bash -cd docs -pnpm install -pnpm build -``` - -如果是链接错误,检查新增页面是否已经加入 `docs/config.ts` 侧边栏,或者相对链接是否指向存在的 Markdown 文件。 diff --git a/docs/guide/tunnel-usage.md b/docs/guide/tunnel-usage.md index 293bad5d..f5c0c6d9 100644 --- a/docs/guide/tunnel-usage.md +++ b/docs/guide/tunnel-usage.md @@ -2,9 +2,9 @@ 你会学到:OpenFlare 内网穿透隧道的设计原理、核心概念(中继节点与隧道客户端),以及如何从零开始将内网开发环境或私有云服务一步步安全、稳定地发布到公网域名上。 -在许多实际开发和运维场景中,我们的源站服务部署在局域网、本地开发机或防范严密的私有 VPC 内部,没有公网 IP,亦无法在边界防火墙或路由器上配置端口映射。 +在许多实际开发和运维场景中,源站服务部署在局域网、本地开发机或私有 VPC 内部,没有公网 IP,也无法在边界防火墙或路由器上配置端口映射。 -OpenFlare 提供了**基于反向中继穿透隧道**的整体解决方案。你只需在内网环境发起向公网中继节点的出向安全连接,无需配置任何入方向端口,即可将公网的 Web 访问流量平滑引入内网源站,同时享有网关提供的 TLS 证书自动托管与 WAF 安全防护。 +OpenFlare 提供了**基于反向中继穿透隧道**的整体解决方案。你只需在内网环境发起向公网中继节点的出向安全连接,无需配置任何入方向端口,即可将公网的 Web 访问流量引入内网源站,同时享有网关提供的 TLS 证书自动托管与 WAF 安全防护。 --- @@ -12,10 +12,12 @@ OpenFlare 提供了**基于反向中继穿透隧道**的整体解决方案。你 在使用内网穿透功能前,你需要熟悉以下组件与核心概念: -| **中继节点 (Relay)** | 部署在公网边缘的流量中继服务,负责监听内网客户端的长连接,并作为网关 Agent (OpenResty) 与内网流量的中转桥梁。 | 运行 `openflare-relay` 守护的 `tunnel_relay` 节点 | -| **穿透隧道 (Tunnel)** | 逻辑上的穿透客户端实例,拥有全局唯一 ID 与安全认证令牌,用以标识一个具体的内网环境。 | 在「节点管理」中创建的 `tunnel_client` 节点,分配专属 Tunnel Token | -| **隧道客户端 (Client)** | 运行在内网环境下的轻量控制器,根据 Server 下发的配置自动管理底层的 frpc 隧道子进程。 | 内网部署的 `openflared` 容器或独立二进制进程 | -| **隧道上游 (Tunnel Upstream)** | 路由规则中的特殊反代类型。选择此类型后,网关会将公网流量转发至本地中继端的 Vhost 端口,最终送达内网源站。 | 在「规则管理」详情页中配置的反向代理类型,选择源站类型为「内网穿透」并绑定对应 Tunnel 节点 | +| 组件 | 说明 | 对应实体 | +| --- | --- | --- | +| **中继节点(Relay)** | 部署在公网边缘的流量中继服务,负责监听内网客户端的长连接,并作为网关 Agent(OpenResty)与内网流量的中转桥梁 | 运行 `openflare-relay` 守护的 `tunnel_relay` 节点 | +| **穿透隧道(Tunnel)** | 逻辑上的穿透客户端实例,拥有全局唯一 ID 与安全认证令牌,用以标识一个具体的内网环境 | 在「节点管理」中创建的 `tunnel_client` 节点,分配专属 Tunnel Token | +| **隧道客户端(Client)** | 运行在内网环境下的轻量控制器,根据 Server 下发的配置自动管理底层的 frpc 隧道子进程 | 内网部署的 `openflared` 容器或独立二进制进程 | +| **隧道上游(Tunnel Upstream)** | 路由规则中的特殊反代类型。选择此类型后,网关会将公网流量转发至本地中继端的 Vhost 端口,最终送达内网源站 | 在「规则管理」详情页中配置的反向代理类型,选择回源方式为「内网穿透(Tunnel)」并绑定对应 Tunnel 节点 | --- @@ -23,11 +25,11 @@ OpenFlare 提供了**基于反向中继穿透隧道**的整体解决方案。你 将一个内网服务发布到公网,推荐按这个顺序进行: -1. 注册并部署至少一个公网 **中继节点 (Relay)** 并保持在线。 -2. 进入 **「节点管理」**,新建一个类型为 **Tunnel 节点 (tunnel_client)** 的节点,获取专属 Token。 -3. 在内网服务器中部署并启动 **隧道客户端 (OpenFlared)**。 +1. 注册并部署至少一个公网 **中继节点(Relay)** 并保持在线。 +2. 进入 **「节点管理」**,新建一个类型为 **Tunnel 节点(tunnel_client)** 的节点,获取专属 Token。 +3. 在内网服务器中部署并启动 **隧道客户端(OpenFlared)**。 4. 确认管理端中该 Tunnel 节点的状态显示为「在线」。 -5. 在 **「规则管理」** 页面新增或编辑规则,在「反向代理」选项卡中选择源站类型为 **「内网穿透」**,绑定对应 Tunnel 节点并填写内网服务端口(如 `127.0.0.1:8080`)。 +5. 在 **「规则管理」** 页面新增或编辑规则,在「反向代理」选项卡中选择回源方式为 **「内网穿透(Tunnel)」**,绑定对应 Tunnel 节点并填写内网服务端口(如 `127.0.0.1:8080`)。 6. 发布并激活新版本。 7. 通过公网域名访问,验证内网穿透链路是否打通。 @@ -35,12 +37,12 @@ OpenFlare 提供了**基于反向中继穿透隧道**的整体解决方案。你 ## 详细配置步骤 -### 第一步:准备中继节点 (Relay) +### 第一步:准备中继节点(Relay) 内网流量需要通过公网的中继节点进行中转。在开始前,你需要确保公网有一台可用的中继服务器。 1. 登录管理端,进入 **「节点管理」**。 -2. 添加一个新节点,并将 **节点类型** 选择为 **中继节点 (tunnel_relay)**。 +2. 添加一个新节点,并将 **节点类型** 选择为 **中继节点(tunnel_relay)**。 3. 保存后,复制该节点专属的 `agent_token`。 4. 在你的公网服务器上启动 `openflare-relay`。你可以直接使用 Docker 快速运行: @@ -54,20 +56,20 @@ OpenFlare 提供了**基于反向中继穿透隧道**的整体解决方案。你 ``` > [!IMPORTANT] - > 请务必在云服务器安全组中放行 `7000` 端口(frpc 客户端连接控制端口)。如果你的 Server 与中继节点部署在同一台机器,这里的 `OPENFLARE_SERVER_URL` 应指向 Server 的公网或内网通信 IP。 + > 请务必在云服务器安全组中放行 `7000` 端口(frpc 客户端连接控制端口,默认 `relay_bind_port`)。如果你的 Server 与中继节点部署在同一台机器,这里的 `OPENFLARE_SERVER_URL` 应指向 Server 的公网或内网通信 IP。 ### 第二步:在管理端创建 Tunnel 节点 1. 导航至管理侧边栏的 **「节点管理」** 页面。 -2. 点击 **「新增节点」** 按钮,在弹窗中选择节点类型为 **「Tunnel 节点 (tunnel_client)」**。 +2. 点击 **「新增节点」** 按钮,在弹窗中选择节点类型为 **「Tunnel 节点(tunnel_client)」**。 3. 填入节点名称与描述,点击保存。 4. 在节点列表中点击进入刚才创建的 Tunnel 节点详情页,你可以找到专属的 **Tunnel Token** 及相应的客户端一键部署命令。 -### 第三步:部署内网客户端 (OpenFlared) +### 第三步:部署内网客户端(OpenFlared) 回到你的内网服务器中,根据刚才复制的部署命令运行客户端。 -#### 方案 A:使用 Docker 部署(强烈推荐) +#### 方案 A:使用 Docker 部署(推荐) 官方提供的 `openflared` 镜像已经内置了主控守护进程与 `frpc` 运行时,开箱即用,无需配置额外依赖: @@ -108,8 +110,8 @@ docker run -d --name openflared --restart unless-stopped \ 现在你可以为你的内网服务配置公网反向代理和域名访问了。 1. 首先进入 **「网站管理」->「域名列表」** 录入你想要公开访问的域名。 -2. 进入 **「规则管理」** 页面,点击 **「新增规则」** 或编辑已有规则。 -3. 在下方 **「反向代理」** 选项卡下,将 **源站类型** 切换为 **「内网穿透」**。 +2. 进入 **「规则管理」** 页面,点击 **「新建规则」** 或编辑已有规则。 +3. 在下方 **「反向代理」** 选项卡下,将 **回源方式** 切换为 **「内网穿透(Tunnel)」**。 4. 从下拉列表中选择刚才部署在线的 **Tunnel 节点**。 5. 填写 **内网目标地址**(对于内网客户端来说可访问的本地地址与端口,例如 `127.0.0.1:8080`)与 **内网协议**(通常为 `http`)。 6. 配置其他站点常规项,并点击保存。 @@ -118,35 +120,35 @@ docker run -d --name openflared --restart unless-stopped \ 为了让网关的 OpenResty 能够正确匹配并路由域名流量,我们需要发布新的配置版本。 -1. 点击导航栏右上角的 **「配置预览」**,确认生成的站点配置无误。 -2. 在弹出窗口中,点击 **「发布并激活」**。 -3. 此时,公网边缘的 Agent 会拉取到最新路由:它会将 `nas.example.com` 的请求转发至同机部署的 `openflare-relay (frps)` 的虚拟主机端口下。 -4. 内网客户端 `openflared (frpc)` 会接收到被中继的封包,并安全地透传给内网的 `127.0.0.1:8080` 服务,最后原路返回响应。 -5. 在你的公网浏览器中访问 `nas.example.com`,确认内网服务成功展示! +1. 点击导航栏右上角的 **「预览并发布」**,确认生成的站点配置无误。 +2. 在弹出窗口中,点击 **「确认发布」**。 +3. 此时,公网边缘的 Agent 会拉取到最新路由:它会将请求转发至同机部署的 `openflare-relay(frps)` 的虚拟主机端口下。 +4. 内网客户端 `openflared(frpc)` 会接收到被中继的封包,并安全地透传给内网的 `127.0.0.1:8080` 服务,最后原路返回响应。 +5. 在你的公网浏览器中访问对应域名,确认内网服务成功展示。 --- ## 高级应用场景 -### 1. 单隧道多服务复用 (多端口映射) +### 1. 单隧道多服务复用(多端口映射) 你并不需要为内网的每一个服务都部署一个 `openflared` 容器。 如果你想在一个内网环境映射多个不同的服务(例如:`127.0.0.1:80` 是博客,`127.0.0.1:8080` 是 API,`192.168.1.120:9000` 是内网网盘): 1. 保持这一个 `openflared` 客户端在线。 2. 在管理端创建三个独立的网站配置(绑定各自对应的公网域名)。 -3. 这三个网站配置都将 **上游类型** 选为 **同一个穿透隧道**。 -4. 分别在各自的“内网目标地址”中填入对应不同的端口或局域网 IP(例如 `127.0.0.1:80`、`127.0.0.1:8080`、`192.168.1.120:9000`)。 +3. 这三个网站配置都将 **回源方式** 选为 **同一个穿透隧道**。 +4. 分别在各自的内网目标地址中填入对应不同的端口或局域网 IP(例如 `127.0.0.1:80`、`127.0.0.1:8080`、`192.168.1.120:9000`)。 5. 发布并激活新版本,即可实现一隧多用。 ### 2. 网关安全功能无缝叠加 因为所有公网流量均首先进入公网的 Agent 节点,在此处完成了 HTTPS/TLS 握手与 WAF 引擎拦截,然后再通过安全隧道送达内网。 -因此,你的内网服务**天然且无需做任何改造**即可享受以下高级特性: -* **一键启用 HTTPS**:直接在管理端为域名选择或申请 SSL 证书,数据传输全程加密。 -* **全局/自定义 WAF 防护**:开启 SQL 注入拦截、XSS 注入防御与恶意地域 IP 屏蔽。 -* **人机挑战 (CC PoW)**:一键抵御针对内网服务的恶意 CC 刷接口攻击。 +因此,你的内网服务**无需做任何改造**即可享受以下特性: +* **一键启用 HTTPS**:直接在管理端为域名选择或申请 SSL 证书,数据传输全程加密。 +* **全局/自定义 WAF 防护**:开启 SQL 注入拦截、XSS 注入防御与恶意地域 IP 屏蔽。 +* **人机挑战(CC PoW)**:一键抵御针对内网服务的恶意 CC 刷接口攻击。 --- @@ -154,17 +156,17 @@ docker run -d --name openflared --restart unless-stopped \ ### 1. 隧道在管理端显示为「离线」 -* **检查 Token 是否正确**:查看 `flared` 日志或环境变量中配置的 `tunnel_token` 是否与管理端生成的一致。 -* **检查网络连通性**:内网服务器需能通过出向网络正常请求 Server 地址。确保控制面没有启用防火墙限制客户端的 HTTP 请求。 -* **中继节点防火墙未开**:检查对应中继节点的公网 `7000` 端口(或你自定义的 bindPort)是否已经在安全组中对公网放行。 +* **检查 Token 是否正确**:查看 `flared` 日志或环境变量中配置的 `tunnel_token` 是否与管理端生成的一致。 +* **检查网络连通性**:内网服务器需能通过出向网络正常请求 Server 地址。 +* **中继节点防火墙未开**:检查对应中继节点的公网 `7000` 端口(或自定义的 `relay_bind_port`)是否已经在安全组中对公网放行。 ### 2. 访问公网域名返回 502 Bad Gateway / 504 Gateway Timeout -* **内网服务未运行**:确认内网目标地址对应的服务已在内网服务器上成功启动并处于监听状态。 -* **目标地址不可达**:如果内网地址填的是 `127.0.0.1:8080`,确保服务确实在运行着 `openflared` 的同一台主机上;如果填的是局域网 IP `192.168.x.x`,请在 `openflared` 容器内测试该局域网 IP 的连通性。 -* **检查客户端应用日志**:在管理端查看「应用记录」或在内网查看 `flared` 运行日志,排查是否有 `LastError` 产生。frpc 在连不上内网端口时,会将连接失败报错原样上报至 Server 方便管理员定位。 +* **内网服务未运行**:确认内网目标地址对应的服务已在内网服务器上成功启动并处于监听状态。 +* **目标地址不可达**:如果内网地址填的是 `127.0.0.1:8080`,确保服务确实在运行着 `openflared` 的同一台主机上;如果填的是局域网 IP `192.168.x.x`,请在 `openflared` 容器内测试该局域网 IP 的连通性。 +* **检查节点状态与日志**:在管理端查看 Tunnel 节点详情与「应用记录」,排查是否有异常状态;frpc 进程异常时会在内网宿主机 `flared` 日志中记录详细报错。 ### 3. 多中继网络动荡或重试失败 -* 当控制面关联了多个 Relay 中继节点时,`openflared` 会为每个 Relay 独立派生 frpc 守护进程,并在 `flared.json` 中配置的 `sync_interval`(默认 30s)内定时向控制面拉取拓扑状态。 -* 若发现某一中继节点频繁由于网络抖动离线,系统会自动触发退避重试机制。你可以在宿主机日志中看到 `frpc process missing, starting` 的日志,这属于正常的进程自愈逻辑,通常在网络恢复后 5~10 秒内即可自动恢复建连。 +* 当控制面关联了多个 Relay 中继节点时,`openflared` 会为每个 Relay 独立派生 frpc 守护进程,并在 `flared.json` 中配置的 `sync_interval`(默认 30s)内定时向控制面拉取拓扑状态。 +* 若某一中继节点频繁由于网络抖动离线,系统会自动触发指数退避重试(初始 1 秒,上限 60 秒)。你可以在宿主机日志中看到 `frpc process missing, starting` 的日志,这属于正常的进程自愈逻辑,网络恢复后会自动重新建连。 diff --git a/docs/guide/uptime-kuma.md b/docs/guide/uptime-kuma.md index 67b2dbda..89df6a7d 100644 --- a/docs/guide/uptime-kuma.md +++ b/docs/guide/uptime-kuma.md @@ -14,11 +14,11 @@ ## 第一步:在系统设置中配置集成 -1. 登录管理端控制面板,进入左侧导航 **「系统设置」** (Settings),选择 **「OpenFlare」** 选项卡,在 **「Uptime Kuma 集成」** 区域进行配置。 +1. 登录管理端控制面板,进入左侧导航 **「系统设置」**,选择 **「OpenFlare」** 选项卡,在 **「Uptime Kuma 集成」** 区域进行配置。 2. 配置以下核心连接参数: - * **启用状态 (Enabled)**:开启集成开关。 - * **实例地址 (Instance URL)**:你的 Uptime Kuma 服务地址。例如 `http://192.168.1.100:3001` 或 `https://kuma.example.com`(必须包含协议前缀 `http://` 或 `https://`)。 - * **用户名 (Username)** 与 **密码 (Password)**:具有管理权限的 Uptime Kuma 账户凭证,用于 API 鉴权。 + * **启用状态(Enabled)**:开启集成开关。 + * **实例地址(Instance URL)**:你的 Uptime Kuma 服务地址。例如 `http://192.168.1.100:3001` 或 `https://kuma.example.com`(必须包含协议前缀 `http://` 或 `https://`)。 + * **用户名(Username)** 与 **密码(Password)**:具有管理权限的 Uptime Kuma 账户凭证,用于 API 鉴权。 --- @@ -26,24 +26,24 @@ 在集成面板中,你可以对监控范围和具体探测行为进行细粒度控制: -### 1. 监控范围 (Monitor Scope) -* **全部站点 (All)**:默认选项。OpenFlare 将自动同步所有**已启用**的代理路由站点。当新站点被创建且启用,或者旧站点被停用时,监控列表将自动增删。 -* **选择站点 (Selected)**:仅监控指定站点。选择此模式后,可以点击 **「选择监控站点」** 弹出框。在弹出框内可以通过搜索过滤站点并进行勾选。被取消勾选或未勾选的站点将不会被同步(若已存在则会被自动清理)。 +### 1. 监控范围(Monitor Scope) +* **全部站点(All)**:默认选项。OpenFlare 将自动同步所有**已启用**的代理路由站点。当新站点被创建且启用,或者旧站点被停用时,监控列表将自动增删。 +* **选择站点(Selected)**:仅监控指定站点。选择此模式后,可以点击 **「选择监控站点」** 弹出框。在弹出框内可以通过搜索过滤站点并进行勾选。被取消勾选或未勾选的站点将不会被同步(若已存在则会被自动清理)。 ### 2. 监测频率与心跳设置 你可以为自动生成的监控项指定统一的探测参数: -* **同步间隔 (Sync Interval)**:自动差分同步的频率(分钟),默认为 `5` 分钟。即控制面每 5 分钟与 Uptime Kuma 进行一次状态比对。 -* **心跳检测频率 (Interval)**:Uptime Kuma 探测站点的频率(秒),默认为 `60` 秒。 -* **最大重试次数 (Retry)**:探测失败后,判定为 Down 之前的最大重试次数,默认为 `0`。 -* **重试间隔时间 (Retry Interval)**:重试之间的等待秒数,默认为 `60` 秒。 -* **请求超时时间 (Timeout)**:探测请求判定为超时的秒数,默认为 `48` 秒。 +* **同步间隔(Sync Interval)**:自动差分同步的频率(分钟),默认为 `5` 分钟。即控制面每 5 分钟与 Uptime Kuma 进行一次状态比对。 +* **心跳检测频率(Interval)**:Uptime Kuma 探测站点的频率(秒),默认为 `60` 秒。 +* **最大重试次数(Retry)**:探测失败后,判定为 Down 之前的最大重试次数,默认为 `0`。 +* **重试间隔时间(Retry Interval)**:重试之间的等待秒数,默认为 `60` 秒。 +* **请求超时时间(Timeout)**:探测请求判定为超时的秒数,默认为 `48` 秒。 --- ## 同步与清理机制 -* **专属标签隔离**:所有自动创建的监控项均会绑定 `OpenFlare` 专属标签(紫蓝色)。同步和清理程序仅操作带有该标签的监控任务,**绝不干扰或破坏你在 Uptime Kuma 中手动创建的其他监控项**。 -* **差分增量同步**:同步程序会周期性对比监控元数据。当检测到域名或心跳配置变更时,仅执行差分更新,避免中断历史统计数据;当站点停用或移出范围时,会自动执行监控下线清理。 +* **专属标签隔离**:所有自动创建的监控项均会绑定 `OpenFlare` 专属标签(紫蓝色)。同步和清理程序仅操作带有该标签的监控任务,不会干扰或破坏你在 Uptime Kuma 中手动创建的其他监控项。 +* **差分增量同步**:同步程序会周期性对比监控元数据。当检测到域名或心跳配置变更时,仅执行差分更新,避免中断历史统计数据;当站点停用或移出范围时,会自动执行监控下线清理。 > [!TIP] > 关于 Uptime Kuma 监控同步的 Socket.IO 控制流、防污染标签模型及差分比对算法细节,请参阅 [Uptime Kuma 监控同步设计](../design/kuma-design.md)。 diff --git a/docs/guide/waf-ip-group-expr.md b/docs/guide/waf-ip-group-expr.md index 2cf72e72..3a4f6573 100644 --- a/docs/guide/waf-ip-group-expr.md +++ b/docs/guide/waf-ip-group-expr.md @@ -29,7 +29,7 @@ ## 执行口径 -自动规则不是逐条请求判断,而是先按单个客户端 IP 聚合: +自动 IP 组先按单个客户端 IP 聚合指标,再对每个 IP 执行规则表达式: 1. Server 读取最近 `lookback` 时长内的请求日志。 2. 按 `remote_addr` 归一化后的 IP 分组。 diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 5e338909..386ad82a 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -24,7 +24,7 @@ go run main.go scheduler # 仅定时任务调度 编译二进制: ```bash -make build-server +make build-backend # 产物:bin/openflare-server ``` @@ -40,13 +40,13 @@ GOCACHE=/tmp/openflare-go-cache go test ./... make code-check ``` -自动格式化后端 Go 与前端 TypeScript、JavaScript、CSS 等源码: +自动格式化后端 Go 源码(整理导入)与前端源码: ```bash -make prettier +make format ``` -该命令使用 `gofmt` 格式化后端,并使用项目固定版本的 Prettier 格式化 `frontend/` 源码;构建产物、依赖、公开静态资源和锁文件会被忽略。 +该命令使用 `goimports` 整理后端 Go 源码导入,并使用项目固定版本的 Prettier 格式化 `frontend/` 源码;构建产物、依赖、公开静态资源和锁文件会被忽略。 ## Frontend @@ -71,7 +71,8 @@ pnpm build:embed ```bash cd frontend pnpm lint -pnpm typecheck +pnpm tsc --noEmit --jsx preserve +pnpm check:i18n ``` ## Agent @@ -147,7 +148,7 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/unin make swagger ``` -访问:`http://localhost:3000/swagger/index.html` +访问:`http://localhost:3000/api/swagger/index.html`(默认 `api_prefix` 为 `/api`,仅非生产环境挂载) ## Docs @@ -162,5 +163,5 @@ pnpm dev ```bash cd docs -pnpm build:embed +pnpm build ``` diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 46fb1dff..4ddbe696 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -152,20 +152,22 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | `password_login_enabled` | `bool` | 是否允许管理员通过常规用户名密码方式登录后台 | `true` | | `registration_enabled` | `bool` | 是否允许自助注册新用户(默认禁止,需由 root 账户邀请或分发) | `false` | | `password_register_enabled` | `bool` | 是否允许通过邮箱/密码方式在前端直接注册 | `false` | -| `oidc_login_enabled` | `bool` | 是否启用 OIDC (SSO) 第三方免密登录方案 | `false` | +| `oidc_login_enabled` | `bool` | 是否启用 OIDC (SSO) 第三方免密登录方案 | `true` | | `max_api_keys_per_user` | `int` | 每个后台用户可生成的最大 API 密钥(API Token)数量 | `5` | | `login_session_ttl_hours` | `int` | 用户会话在浏览器 Cookie 中的有效期(小时)。0 为随浏览器关闭清除 | `0` | -| `upload_allowed_extensions` | `string` | 允许用户上传的静态静态托管包文件扩展名(逗号分隔) | `zip,tar.gz,gz,tar,ssl,key,pem,txt,json` | +| `upload_allowed_extensions` | `string` | 允许上传的文件扩展名(逗号分隔,空则不限) | `jpg,png,webp` | | `file_access_whitelist` | `json` | 允许免登录直接公开下载或访问的文件业务类型列表 (JSON 数组) | `["avatar"]` | | `disk_cache_max_size_mb` | `int` | 平台本地磁盘缓存的最大存储阈值(MB) | `100` | | `disk_cache_ttl_minutes` | `int` | 本地磁盘缓存对象的默认生存周期(分钟) | `60` | | `disk_cache_lru_enabled` | `bool` | 当本地磁盘缓存空间不足时是否启用 LRU 算法剔除最旧缓存 | `true` | | `update_upstream_repository` | `string` | 系统检测自更新的 GitHub 仓库地址 | `Rain-kl/OpenFlare` | | `storage_config` | `json` | 对象存储的结构化配置 (JSON),支持本地磁盘与 AWS S3 兼容存储配置 | 本地存储模式 | -| `relay_frps_web_ui_enabled` | `bool` | 是否允许在中继节点上默认开启内嵌的 frps 流量监视面板 Web UI | `true` | -| `relay_frps_web_ui_port` | `int` | 中继节点 frps 监视面板所监听绑定的宿主机端口 | `7500` | +| `relay_frps_web_ui_enabled` | `bool` | 是否在中继节点上开启内嵌的 frps 流量监视面板 Web UI | `false` | +| `relay_frps_web_ui_port` | `int` | 中继节点 frps 监视面板所监听绑定的宿主机端口 | `17500` | | `search_engine_indexing_enabled` | `bool` | 是否允许搜索引擎爬取/检索该站点 | `false` | | `menu_display_config` | `string` | 目录显示的结构化配置 (JSON 字符串,格式为 `{url: enabled}`) | `{}` | +| `pages_max_package_size_mb` | `int` | Pages 部署包上传大小上限(MiB,范围 1~2048) | `100` | +| `pages_max_history_count` | `int` | Pages 每个项目最大历史部署保留数(0 表示不限制) | `20` | ### 2. 人机安全校验 (PoW Captcha) | 配置键 (Key) | 数据类型 | 作用说明 | 默认值 | @@ -175,8 +177,8 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | `cap_challenge_count` | `int` | 人机验证所需的计算难题数。数量越大,计算要求时间越长(推荐 1~5) | `1` | | `cap_challenge_difficulty`| `int`| 每次计算所需的 PoW 哈希前缀匹配难度。推荐数值在 3-5 之间 | `4` | | `cap_challenge_size` | `int` | 人机验证盐值长度 | `32` | -| `cap_challenge_ttl_seconds`| `int`| 难题下发后等待计算提交的最长有效时间(秒),超时自动作废 | `300` | -| `cap_token_ttl_seconds` | `int` | 完成计算并置换到登录凭证后的有效期(秒),限制需在规定时间内登录 | `600` | +| `cap_challenge_ttl_seconds`| `int`| 难题下发后等待计算提交的最长有效时间(秒),超时自动作废 | `600` | +| `cap_token_ttl_seconds` | `int` | 完成计算并置换到登录凭证后的有效期(秒),限制需在规定时间内登录 | `1200` | ### 3. SMTP 邮件推送配置 | 配置键 (Key) | 数据类型 | 作用说明 | 默认值 | @@ -191,7 +193,7 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 ### 4. 节点与 Agent 运维运行时参数 | 配置键 (Key) | 数据类型 | 作用说明 | 默认值 | | --- | --- | --- | --- | -| `agent_discovery_token` | `string` | 新节点首次一键接入并自动注册的全局通用验证发现 Token | 无(系统初始化生成) | +| `agent_discovery_token` | `string` | 新节点首次一键接入并自动注册的全局通用验证发现 Token | 无(首次访问时自动生成) | | `agent_heartbeat_interval`| `int` | 控制并向所有接入 Agent 周期下发的标准心跳检测间隔(毫秒) | `3000` (3s) | | `agent_websocket_upgrade_enabled` | `bool` | 是否授权 Agent 在 HTTP 心跳握手成功后升级建立持久 WebSocket 实时连接 | `true` | | `node_offline_threshold` | `int` | 在管理后台中判定节点失去心跳并标注为离线状态的无响应阈值(毫秒) | `60000` (60s) | @@ -227,7 +229,7 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | `openresty_client_header_timeout` | `int` | 接收客户端整个 Request Header 头信息的读取超时上限时长(秒) | `15` | | `openresty_client_body_timeout` | `int` | 接收客户端 Request Body 载荷体的数据读取超时上限时长(秒) | `15` | | `openresty_client_max_body_size` | `string` | 允许客户端请求上传的最大 Body 大小限制,通常需要单位如 `10m`/`50m` | `64m` | -| `openresty_large_client_header_buffers` | `string` | 复杂请求超大请求头的专属缓冲区数目与大小大小(如 `4 16k`) | `4 16k` | +| `openresty_large_client_header_buffers` | `string` | 复杂请求超大请求头的专属缓冲区数目与大小(如 `4 16k`) | `4 16k` | | `openresty_send_timeout` | `int` | 向客户端推送 Response 数据回执单次传输最大的间隔超时时长(秒)| `30` | | `openresty_resolvers` | `string` | 节点进行 DNS 域名动态解析所关联绑定的域名解析器地址与配置参数 | 空 | | `openresty_proxy_connect_timeout` | `int` | 向后台代理源站发起 TCP 三次握手建连的最长超时上限时长(秒) | `3` | @@ -248,13 +250,14 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | `openresty_cache_levels` | `string` | 代理缓存的存储目录树层级分配设置 | `1:2` | | `openresty_cache_inactive` | `string` | 缓存文件多长时间无人访问后将自动从磁盘上失效抹除的时间时长 | `30m` (30分钟) | | `openresty_cache_max_size` | `string` | 代理缓存区域在节点上占用的最大可用物理磁盘额度 | `1g` (1GB) | -| `openresty_cache_key_template` | `string` | 默认生成代理缓存键 the 识别模板 | `$scheme$host$request_uri` | +| `openresty_cache_key_template` | `string` | 默认生成代理缓存键的识别模板 | `$scheme$host$request_uri` | | `openresty_cache_lock_enabled` | `bool` | 遭遇高并发请求击穿同一失效资源时是否对向源站发起建连排队加锁 | `true` | | `openresty_cache_lock_timeout` | `string` | 抢夺代理缓存锁排队建连时排队等待的最长等待耗时限制 | `5s` | | `openresty_cache_use_stale` | `string` | 当源站遇到特定报错(如500/502/504等)时是否直接向用户投递过期缓存 | `error timeout updating http_500 http_502 http_503 http_504` | | `openresty_default_limit_conn_per_server` | `int` | 站点未配置时的默认并发连接上限;`0` 表示默认关闭 | `0` | | `openresty_default_limit_conn_per_ip` | `int` | 站点未配置时的默认单 IP 并发上限;`0` 表示默认关闭 | `0` | | `openresty_default_limit_rate` | `string` | 站点未配置时的默认单请求带宽(如 `512k`);空表示默认关闭 | 空 | +| `openresty_default_limit_req_per_ip` | `string` | 站点未配置时的默认单 IP 请求频率限制(如 `10r/s`、`100r/m`);空表示默认关闭 | 空 | | `openresty_main_config_template` | `string` | 允许用户完全重写整个 OpenResty nginx.conf 的底层结构大骨架模板 | 空 (内置缺省骨架) | ### 7. 源站错误页 (Origin Error Page) @@ -289,9 +292,9 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | 环境变量 | 作用 | 默认值 | | --- | --- | --- | -| `NEXT_PUBLIC_API_BASE_URL` | 前端请求 API 的基础路径 | `/api` | +| `WAVELET_BACKEND_URL` | 服务端渲染与开发代理访问的后端地址 | `http://localhost:3000` | +| `NEXT_PUBLIC_WAVELET_BACKEND_URL` | 浏览器端请求 API 的后端地址;为空时使用同源 | 空 | | `NEXT_PUBLIC_APP_VERSION` | 前端展示版本号 | `dev` | -| `NEXT_DEV_BACKEND_URL` | 本地开发服务器代理的后端地址 | `http://127.0.0.1:3000` | --- @@ -402,14 +405,3 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | `heartbeat_interval` | 心跳间隔 | 否 | `10000` 毫秒 | | `sync_interval` | 配置拉取同步间隔 | 否 | `30000` 毫秒 | | `request_timeout` | HTTP 请求超时 | 否 | `10000` 毫秒 | - ---- - -## 维护要求 - -以下内容变化时,必须同步更新本文档: -- Server 命令行参数。 -- Server 环境变量。 -- SystemConfig 数据库系统配置字段(新增、修改、废弃)。 -- Agent / Relay / Client 的命令行参数与配置字段。 -- 任何配置项的默认值、用途或配置示例。