From cc5e53c51e2565e43779ecfc56c77d48efdc783a Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 19 Jun 2026 14:43:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 4 +- README.md | 39 +- docs/changelog/index.md | 6 + docs/deployment/agent.md | 4 +- docs/deployment/deployment.md | 77 +--- docs/deployment/openflared.md | 5 +- docs/deployment/relay.md | 3 +- docs/deployment/server.md | 93 ++--- docs/design/agent-design.md | 8 +- docs/design/architecture.md | 9 +- docs/design/index.md | 113 +++--- docs/en/config.ts | 119 ------ docs/en/deployment/agent.md | 176 --------- docs/en/deployment/deployment.md | 287 -------------- docs/en/deployment/index.md | 24 -- docs/en/deployment/openflared.md | 119 ------ docs/en/deployment/relay.md | 126 ------ docs/en/deployment/server.md | 170 -------- docs/en/deployment/upgrade.md | 52 --- docs/en/design/agent-design.md | 181 --------- docs/en/design/architecture.md | 223 ----------- docs/en/design/development.md | 182 --------- docs/en/design/index.md | 204 ---------- docs/en/design/repository.md | 93 ----- docs/en/design/tunnel-design.md | 130 ------ docs/en/design/waf-design.md | 132 ------- docs/en/guide/credits.md | 27 -- docs/en/guide/first-site.md | 100 ----- docs/en/guide/index.md | 43 -- docs/en/guide/quick-start.md | 219 ----------- docs/en/guide/sso.md | 106 ----- docs/en/guide/troubleshooting.md | 249 ------------ docs/en/guide/tunnel-usage.md | 174 -------- docs/en/guide/usage.md | 156 -------- docs/en/guide/waf-ip-group-expr.md | 161 -------- docs/en/guide/waf-usage.md | 162 -------- docs/en/index.md | 35 -- docs/en/reference/api.md | 155 -------- docs/en/reference/cli.md | 149 ------- docs/en/reference/configuration.md | 370 ------------------ docs/en/reference/index.md | 13 - docs/guide/index.md | 1 - ...618-openflare-wavelet-backend-migration.md | 10 - docs/plan/handover-docs-restructure-update.md | 53 +++ .../handover-openflare-backend-migration.md | 1 - docs/plan/index.md | 1 + docs/reference/cli.md | 72 ++-- docs/reference/index.md | 2 +- 48 files changed, 226 insertions(+), 4612 deletions(-) delete mode 100644 docs/en/config.ts delete mode 100644 docs/en/deployment/agent.md delete mode 100644 docs/en/deployment/deployment.md delete mode 100644 docs/en/deployment/index.md delete mode 100644 docs/en/deployment/openflared.md delete mode 100644 docs/en/deployment/relay.md delete mode 100644 docs/en/deployment/server.md delete mode 100644 docs/en/deployment/upgrade.md delete mode 100644 docs/en/design/agent-design.md delete mode 100644 docs/en/design/architecture.md delete mode 100644 docs/en/design/development.md delete mode 100644 docs/en/design/index.md delete mode 100644 docs/en/design/repository.md delete mode 100644 docs/en/design/tunnel-design.md delete mode 100644 docs/en/design/waf-design.md delete mode 100644 docs/en/guide/credits.md delete mode 100644 docs/en/guide/first-site.md delete mode 100644 docs/en/guide/index.md delete mode 100644 docs/en/guide/quick-start.md delete mode 100644 docs/en/guide/sso.md delete mode 100644 docs/en/guide/troubleshooting.md delete mode 100644 docs/en/guide/tunnel-usage.md delete mode 100644 docs/en/guide/usage.md delete mode 100644 docs/en/guide/waf-ip-group-expr.md delete mode 100644 docs/en/guide/waf-usage.md delete mode 100644 docs/en/index.md delete mode 100644 docs/en/reference/api.md delete mode 100644 docs/en/reference/cli.md delete mode 100644 docs/en/reference/configuration.md delete mode 100644 docs/en/reference/index.md create mode 100644 docs/plan/handover-docs-restructure-update.md diff --git a/AGENTS.md b/AGENTS.md index e9e6856f..4f1da2fc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -276,7 +276,7 @@ func doSomething(c *gin.Context) { response.AbortBadRequest(c, "...") } 路由与模块: - 仅在 `internal/router/router.go` 中作为统一高层入口进行路由分发委派,不允许在 `router.go` 中直接挂载业务 Handler。 -- 关于所有的路由归属划分、接口开发隔离防线以及详细的注册和开发步骤,请直接阅读并严格遵循 [new-api](file:///Users/ryan/DEV/Go/OpenFlare/openflare-server/.claude/skills/new-api/SKILL.md) 技能。 +- 关于所有的路由归属划分、接口开发隔离防线以及详细的注册和开发步骤,请直接阅读并严格遵循 [new-api](.agent/skills/new-api/SKILL.md) 技能。 应用装配与跨模块集成: @@ -308,7 +308,7 @@ func doSomething(c *gin.Context) { response.AbortBadRequest(c, "...") } 在进行任何 Next.js 工作之前,请在 `node_modules/next/dist/docs/` 中找到并阅读相关文档。您的训练数据已过时 —— 这些文档是唯一的真理来源。 -请直接查看并参考项目提供的示例和 Demo 代码:[frontend/app/(main)/admin/demo](file:///Users/ryan/DEV/Go/OpenFlare/openflare-server/frontend/app/(main)/admin/demo)。 +请直接查看并参考项目提供的示例和 Demo 代码:[frontend/app/(main)/admin/demo](frontend/app/(main)/admin/demo)。 样式规范: diff --git a/README.md b/README.md index ec3c5b24..f23cc2ee 100644 --- a/README.md +++ b/README.md @@ -52,45 +52,16 @@ OpenFlare 是开源 CDN 编排与边缘安全平台。它支持反向代理、 ### 1. 启动 Server -```yaml -services: - postgres: - image: postgres:17-alpine - restart: unless-stopped - environment: - POSTGRES_DB: openflare - POSTGRES_USER: openflare - POSTGRES_PASSWORD: replace-with-strong-password - volumes: - - postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U openflare -d openflare"] - interval: 10s - timeout: 5s - retries: 5 - - openflare: - image: ghcr.io/rain-kl/openflare:latest - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - ports: - - "3000:3000" - environment: - SESSION_SECRET: replace-with-random-string - DSN: postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable - GIN_MODE: release - LOG_LEVEL: info - -volumes: - postgres-data: -``` +仓库根目录提供完整 `docker-compose.yaml`(PostgreSQL、Redis、ClickHouse、Jaeger): ```bash +cp .env.example .env +# 编辑 .env,至少修改 APP_SESSION_SECRET docker compose up -d ``` +详细部署说明见 [部署文档](https://open-flare.pages.dev/deployment/deployment)。 + 访问地址:`http://localhost:3000` 默认账号: diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 0572d4f7..c6fdc8d5 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -18,6 +18,12 @@ sidebar: false ### 变更 +- 合并并简化仓库结构:将 `openflare-server` 单体目录下的所有文件/目录提升至仓库根目录(去除了 `openflare-server` 嵌套层级),保留 `.github` 目录不变;统一配置 `docker-compose.yaml` 及所有 Dockerfile 的构建上下文为根目录。 +- 调整子项目结构与包路径:将 `agent`、`relay` 和 `flared` 子项目从 `internal/` 移动至 `internal/apps/`(分别为 `internal/apps/agent`、`internal/apps/relay` 和 `internal/apps/flared`),并递归更新了所有涉及的 Go 导入路径(如 `github.com/Rain-kl/Wavelet/internal/apps/agent` 等)。 +- 调整编译产物输出名称与 Makefile: + - 更新 `Makefile` 编译目标,在 `bin/` 目录下统一输出 `openflare-server`(而不是 `wavelet`)、`openflare-agent`、`openflare-relay` 及 `flared`。 + - 新增 `build-all` 编译目标以一键按序编译所有服务端、客户端和网关组件。 +- 修复 `internal/apps/openflare/tasks/ssl_renew_test.go` 中在未模拟 ACME 证书续期调用时测试执行的并发/竞态问题。 - `of_node_access_logs` 从 PostgreSQL/SQLite 迁移至 ClickHouse(数据库 `openflare`);ClickHouse 表结构改由 goose 独立迁移管线管理(`goose_clickhouse_version`),启动时在 `migrator.MigrateClickHouse()` 中执行,移除 `clickhouse_schema.go` 手写 DDL。 - ClickHouse 分析库接入 GORM(`db.ChDB`)与 `internal/repository/analytics/`:用户访问日志(`w_user_access_logs`)读写、风控批量写入与管理端日志统计 API 统一经 repository 访问;新增 `internal/model/analytics/` 分析表模型。 - OpenFlare 节点访问日志(`of_node_access_logs`)ClickHouse 读写迁入 `internal/repository/analytics/`;`model` 层保留聚合编排与内存测试 store,生产路径经薄适配器调用 repository。 diff --git a/docs/deployment/agent.md b/docs/deployment/agent.md index 1bcf8214..c4ba69fe 100644 --- a/docs/deployment/agent.md +++ b/docs/deployment/agent.md @@ -149,7 +149,7 @@ journalctl -u openflare-agent -f 源码运行: ```bash -cd openflare-agent + export LOG_LEVEL='info' go run ./cmd/agent -config /path/to/agent.json ``` @@ -157,7 +157,7 @@ go run ./cmd/agent -config /path/to/agent.json 编译后二进制运行: ```bash -cd openflare-agent + go build -o openflare-agent ./cmd/agent export LOG_LEVEL='info' ./openflare-agent -config /path/to/agent.json diff --git a/docs/deployment/deployment.md b/docs/deployment/deployment.md index 686b92b9..c028ab23 100644 --- a/docs/deployment/deployment.md +++ b/docs/deployment/deployment.md @@ -2,7 +2,7 @@ 你会学到:OpenFlare 的推荐部署方式、Server 与 Agent 的运行要求、源码启动方式、联调步骤、升级与卸载入口。 -生产环境建议使用 PostgreSQL 作为 Server 数据库,并为 Server 显式配置 `JWT_SECRET`。Agent 部署方式推荐为 Docker 部署(即直接使用内置 OpenResty 的 Agent 镜像);亦支持通过安装脚本或手动本地运行。 +生产环境建议使用 PostgreSQL 作为 Server 数据库,并通过 `config.yaml` 或环境变量配置 `APP_SESSION_SECRET` 等参数。完整 Docker Compose 部署还需 Redis 与 ClickHouse(见仓库根目录 `docker-compose.yaml`)。Agent 部署方式推荐为 Docker 部署(即直接使用内置 OpenResty 的 Agent 镜像);亦支持通过安装脚本或手动本地运行。 ## 部署拓扑 @@ -78,53 +78,14 @@ Agent: ## Docker Compose 部署 Server -创建 `docker-compose.yml`: - -```yaml -services: - postgres: - image: postgres:17-alpine - restart: unless-stopped - environment: - POSTGRES_DB: openflare - POSTGRES_USER: openflare - POSTGRES_PASSWORD: replace-with-strong-password - volumes: - - postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U openflare -d openflare"] - interval: 10s - timeout: 5s - retries: 5 - - openflare: - image: ghcr.io/rain-kl/openflare:latest - container_name: openflare - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - ports: - - "3000:3000" - environment: - JWT_SECRET: replace-with-a-long-random-string - DSN: postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable - GIN_MODE: release - LOG_LEVEL: info - volumes: - - openflare-data:/data - -volumes: - postgres-data: - openflare-data: -``` - -启动: +仓库根目录已提供完整 `docker-compose.yaml`(含 PostgreSQL、Redis、ClickHouse、Jaeger)。 ```bash +cp .env.example .env +# 编辑 .env,至少修改 APP_SESSION_SECRET 与数据库密码 docker compose up -d docker compose ps -docker compose logs -f openflare +docker compose logs -f wavelet ``` 首次访问 `http://localhost:3000`,默认账号为 `root` / `123456`。登录后请立即修改默认密码。 @@ -134,29 +95,23 @@ docker compose logs -f openflare 先构建管理端前端: ```bash -cd openflare-server/web +cd frontend corepack enable pnpm install -pnpm build +pnpm build:embed ``` -再启动 Server: +再启动 Server(仓库根目录): ```bash -cd openflare-server -export JWT_SECRET='replace-with-a-long-random-string' -export SQLITE_PATH='./openflare.db' -export LOG_LEVEL='info' -# 可选:设置后优先使用 PostgreSQL。 -# export DSN='postgres://openflare:secret@127.0.0.1:5432/openflare?sslmode=disable' -go run . +cp config.example.yaml config.yaml +export APP_SESSION_SECRET='replace-with-a-long-random-string' +# 可选:使用 PostgreSQL +# export DB_HOST=127.0.0.1 DB_USERNAME=postgres DB_PASSWORD=postgres DB_NAME=openflare +go run main.go all ``` -默认监听 `3000` 端口。也可以显式指定: - -```bash -go run . --port 3000 --log-dir ./logs -``` +默认监听 `:3000`(由 `config.yaml` 的 `app.addr` 或 `APP_ADDR` 控制)。 ## Docker 运行 Agent(推荐) @@ -230,7 +185,7 @@ journalctl -u openflare-agent -f 源码运行: ```bash -cd openflare-agent + export LOG_LEVEL='info' go run ./cmd/agent -config /path/to/agent.json ``` @@ -238,7 +193,7 @@ go run ./cmd/agent -config /path/to/agent.json 编译后二进制运行: ```bash -cd openflare-agent + go build -o openflare-agent ./cmd/agent export LOG_LEVEL='info' ./openflare-agent -config /path/to/agent.json diff --git a/docs/deployment/openflared.md b/docs/deployment/openflared.md index b246f52d..52482474 100644 --- a/docs/deployment/openflared.md +++ b/docs/deployment/openflared.md @@ -58,8 +58,7 @@ docker run -d --name openflared --restart unless-stopped \ ### 1. 编译二进制 ```bash -cd openflared -go build -o flared ./cmd/flared +go build -o bin/flared ./cmd/flared ``` ### 2. 准备 `flared.json` @@ -91,7 +90,7 @@ export LOG_LEVEL='info' ### 1. 自动同步逻辑 启动成功后,OpenFlared 将执行以下工作流: -- **心跳与配置获取**:周期性向 Server 的 `/api/flared/heartbeat` 和 `/api/flared/config` 接口发起同步,验证 Token 并检测配置版本。 +- **心跳与配置获取**:周期性向 Server 的 `/api/v1/tunnel/heartbeat` 和 `/api/v1/tunnel/config/active` 接口发起同步,验证 Token 并检测配置版本。 - **文件渲染**:当检测到配置版本(或校验和 Checksum)变化时,会自动拉取该隧道的完整路由规则。如果绑定了多个中继 Relay,将为每个 Relay 分别在 `data_dir` 下渲染出 `frpc_{relayNodeID}.toml`。 - **热重载或重启**:拉起对应的 `frpc` 子进程,或在配置文件发生改变时执行 `frpc reload` / 重启动作,以确保流量映射保持最新。 - **异常自恢复**:如果本地 `frpc` 隧道进程异常退出,主控程序会在 5 秒的退避惩罚后自动尝试重新启动。 diff --git a/docs/deployment/relay.md b/docs/deployment/relay.md index 6ea02d74..adfcd43d 100644 --- a/docs/deployment/relay.md +++ b/docs/deployment/relay.md @@ -68,8 +68,7 @@ docker run -d --name openflare-relay --restart unless-stopped \ ### 1. 编译二进制 ```bash -cd openflare-relay -go build -o openflare-relay ./cmd/relay +go build -o bin/openflare-relay ./cmd/relay ``` ### 2. 准备 `relay.json` diff --git a/docs/deployment/server.md b/docs/deployment/server.md index fb288b32..13a188da 100644 --- a/docs/deployment/server.md +++ b/docs/deployment/server.md @@ -13,14 +13,14 @@ OpenFlare Server 是 Gin + GORM 单体控制面,负责管理端 UI、管理 AP | pnpm | 推荐通过 `corepack enable` 使用项目声明的 pnpm | | 数据库 | SQLite 文件目录可写,或可访问的 PostgreSQL 实例 | -生产环境必须配置 `session_secret`(或 `SESSION_SECRET`),并优先使用 PostgreSQL 与 Redis。 +生产环境必须配置 `app.session_secret`(或 `APP_SESSION_SECRET`),并优先使用 PostgreSQL、Redis 与 ClickHouse。 ## 构建管理端前端 -Go Server 会嵌入 `openflare-server/frontend/out` 静态产物。源码启动前先构建前端: +Go Server 会嵌入 `frontend/out` 静态产物(构建后复制到 `internal/router/root/dist`)。源码启动前先构建前端: ```bash -cd openflare-server/frontend +cd frontend corepack enable pnpm install pnpm build:embed @@ -37,10 +37,9 @@ pnpm test ## 使用 SQLite 启动 ```bash -cd openflare-server cp config.example.yaml config.yaml # 编辑 config.yaml:设置 session_secret,并将 database.enabled 设为 false -go run . all +go run main.go all ``` 默认监听 `3000` 端口,访问: @@ -52,13 +51,12 @@ http://localhost:3000 ## 使用 PostgreSQL 启动 ```bash -cd openflare-server cp config.example.yaml config.yaml # 编辑 config.yaml:设置 session_secret、database.* 与 redis.* -go run . all +go run main.go all ``` -生产环境推荐分进程部署:`go run . api`、`go run . worker`、`go run . scheduler`。 +生产环境推荐分进程部署:`go run main.go api`、`go run main.go worker`、`go run main.go scheduler`。 ## 使用 Docker 启动 @@ -77,85 +75,39 @@ docker run -d \ --name openflare-server \ -p 3000:3000 \ -v $(pwd)/openflare-data:/data \ - -e JWT_SECRET='replace-with-a-long-random-string' \ + -e APP_SESSION_SECRET='replace-with-a-long-random-string' \ + -e DB_ENABLED=false \ -e SQLITE_PATH='/data/openflare.db' \ - -e GIN_MODE='release' \ -e LOG_LEVEL='info' \ - openflare-server:latest + ghcr.io/rain-kl/openflare:latest ``` 启动参数说明: * **`-p 3000:3000`**:映射宿主机 `3000` 端口到容器内 `3000` 端口。 -* **`-v $(pwd)/openflare-data:/data`**:挂载本地目录到容器的 `/data`,确保数据库文件 `openflare.db` 在重启或重建容器时不丢失。 -* **`JWT_SECRET`**:管理端 API 登录令牌的 JWT 签名密钥,生产环境必须配置,避免重启后已登录令牌全部失效。 +* **`-v $(pwd)/openflare-data:/data`**:挂载本地目录到容器的 `/data`,确保数据库文件在重启或重建容器时不丢失。 +* **`APP_SESSION_SECRET`**:Session Cookie 签名密钥,生产环境必须配置。 --- -### 2. 使用 Docker Compose 一键启动(集成 PostgreSQL) +### 2. 使用 Docker Compose 一键启动 -推荐在生产环境使用 Docker Compose,自动编排独立的 PostgreSQL 数据库并建立服务间的高可用关联。 - -在项目控制面目录下使用 `docker-compose.yaml` 进行编排: - -```yaml -services: - postgres: - image: postgres:17-alpine - restart: unless-stopped - environment: - POSTGRES_DB: openflare - POSTGRES_USER: openflare - POSTGRES_PASSWORD: replace-with-strong-password - volumes: - - ./postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U openflare -d openflare"] - interval: 10s - timeout: 5s - retries: 5 - - openflare: - image: openflare-server:latest - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - ports: - - "3000:3000" - environment: - JWT_SECRET: replace-with-random-string - SQLITE_PATH: /data/openflare.db - DSN: postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable - GIN_MODE: release - LOG_LEVEL: info - volumes: - - ./openflare-data:/data -``` - -启动命令: +推荐在生产环境使用仓库根目录的 `docker-compose.yaml`,自动编排 PostgreSQL、Redis、ClickHouse 与 Jaeger: ```bash -# 启动编排服务 +cp .env.example .env docker compose up -d ``` -Compose 参数说明: -* **`depends_on` 与 `healthcheck`**:通过 PostgreSQL 的健康度检查(pg_isready),确保数据库初始化完成并完全准备就绪后,再自动拉起 OpenFlare 控制面服务,避免首次连接数据库失败抛出 panic。 -* **数据目录分离挂载**:`postgres` 数据挂载在 `./postgres-data`,`openflare` 数据与本地备份挂载在 `./openflare-data`,结构清晰,便于日常备份和维护。 - - ## 命令行参数 ```bash -go run . --port 3000 --log-dir ./logs +go run main.go api # 仅 API +go run main.go worker # 仅 Worker +go run main.go scheduler # 仅 Scheduler +go run main.go all # 融合模式(默认) ``` -| 参数 | 作用 | 默认值 | -| --- | --- | --- | -| `--port` | 指定 Server 监听端口 | `3000` | -| `--log-dir` | 指定日志目录 | 空,输出到标准输出 | -| `--version` | 输出版本后退出 | `false` | -| `--help` | 输出帮助后退出 | `false` | +监听地址与日志由 `config.yaml`(`app.addr`、`log.*`)或 `APP_ADDR`、`LOG_*` 环境变量控制。 ## 首次登录 @@ -169,7 +121,7 @@ go run . --port 3000 --log-dir ./logs ## 配置要点 -复制 `openflare-server/config.example.yaml` 为 `config.yaml`,或使用 `openflare-server/.env.example` 中的环境变量。关键默认值: +复制 `config.example.yaml` 为 `config.yaml`,或使用 `.env.example` 中的环境变量。关键默认值: | 项 | 值 | | --- | --- | @@ -179,14 +131,13 @@ go run . --port 3000 --log-dir ./logs | `application_name` | `openflare-server` | | Redis 键前缀 | `openflare:` | -也可使用 `docker compose up`(见 `openflare-server/docker-compose.yml`)拉起 PostgreSQL、Redis 与 Server。 +也可使用 `docker compose up`(见根目录 `docker-compose.yaml`)拉起完整依赖栈。 ### 验证 ```bash -cd openflare-server go build ./... go test ./internal/apps/openflare/... -count=1 -curl http://127.0.0.1:3000/api/status +curl http://127.0.0.1:3000/api/v1/d/status ``` diff --git a/docs/design/agent-design.md b/docs/design/agent-design.md index 351e5e9b..de1130dd 100644 --- a/docs/design/agent-design.md +++ b/docs/design/agent-design.md @@ -38,13 +38,13 @@ Agent 在生命周期中主要通过 **基于 Token 的自动注册** 和 **心 ### 1. 自动注册流程 若 Agent 启动时本地 `agent.json` 的 `access_token` 为空,但配置了 `discovery_token`,将触发自动注册流程: -1. Agent 向控制面 `/api/agent/register` 发送注册请求,携带本地硬件摘要、IP 及主机名。 +1. Agent 向控制面 `/api/v1/agent/nodes/register` 发送注册请求,携带本地硬件摘要、IP 及主机名。 2. Server 校验 `discovery_token` 有效后,在数据库生成唯一的 `NodeID` 与专属 `AccessToken`(即 `agent_token`)并返回。 3. Agent 将获取的专用 Token 写入本地配置文件,擦除一次性 `discovery_token`,后续所有的通信均基于专属 `AccessToken` 进行鉴权认证。 ### 2. 双通道心跳与同步机制 * **HTTP 轮询通道(兜底与探测)**:Agent 默认按设定的 `heartbeat_interval` 间隔发送 POST 心跳包。上报指标的同时获取当前激活版本的摘要信息(Version & Checksum)。 -* **WebSocket 通道(实时通信)**:在 HTTP 心跳成功后,Agent 自动尝试将连接升级为 WebSocket (`/api/agent/ws`)。 +* **WebSocket 通道(实时通信)**:在 HTTP 心跳成功后,Agent 自动尝试将连接升级为 WebSocket (`/api/v1/agent/ws`)。 * WS 连接建立后,心跳与指标上报全面转移到 WS 管道,降低网络开销。 * Server 发布或激活新版本时,通过 WS 广播通知 Agent。Agent 收到变更事件后,**立即触发同步流程**,实现秒级配置生效。 * 若 WS 链路因网络问题断开,Agent 自动降级为 HTTP 轮询,并采用指数退避机制尝试重建 WS。 @@ -67,7 +67,7 @@ sequenceDiagram Note over Agent, Server: HTTP 兜底与 WebSocket 升级 Agent->>Server: 3. 发送 HTTP Heartbeat (上报系统状态与健康度) Server-->>Agent: 4. 返回 ActiveConfig 摘要及 AgentSettings - Agent->>Server: 5. 发起 WebSocket 升级请求 (/api/agent/ws) + Agent->>Server: 5. 发起 WebSocket 升级请求 (/api/v1/agent/ws) Server-->>Agent: 6. 升级成功 (建立双向持久实时通道) end @@ -171,5 +171,5 @@ graph TD 为保证数据与控制链路的安全边界,Agent 代码编写与二次开发必须严格遵守以下工程约束: 1. **零特权指令通道**:Server 绝对禁止向 Agent 传递任何任意 shell 命令或远程执行脚本(如 exec/eval 等)。所有系统控制原语(如启动、停止、重载、更新)必须硬编码在 Agent 二进制内部。 -2. **严格的 Token 过滤与前缀验证**:Agent 侧向 Server 请求资源时,接口端点固定以 `/api/agent/` 为前缀,并强制携带 `X-Agent-Token` 进行签名或令牌核验。 +2. **严格的 Token 过滤与前缀验证**:Agent 侧向 Server 请求资源时,接口端点固定以 `/api/v1/agent/` 为前缀,并强制携带 `X-Agent-Token` 进行签名或令牌核验。 3. **节点自治原则**:Agent 须具备完备的离线工作能力。在与 Server 失去连接期间,本地 OpenResty 必须依靠本地已落地的配置保持反向代理服务的绝对正常运行。 diff --git a/docs/design/architecture.md b/docs/design/architecture.md index 65d1af9c..8fce3d12 100644 --- a/docs/design/architecture.md +++ b/docs/design/architecture.md @@ -70,19 +70,19 @@ OpenResty (Agent, TLS/WAF) | **OpenResty** | 接收真实流量,执行 WAF 过滤、PoW 防护、Basic Auth 认证与静态/反代服务 | [WAF 设计](./waf-design.md) / [Pages 设计](./pages-design.md) | | **Relay** | 部署于边缘节点,管理 `frps` 守护进程生命周期,接受心跳派发的穿透中继配置 | [内网穿透设计](./tunnel-design.md) | | **OpenFlared** | 部署于内网,管理 `frpc` 进程组,向多个 Relay 建立反向隧道,上报连接状态 | [内网穿透设计](./tunnel-design.md) | -| **Frontend** | Next.js 管理界面,提供路由、WAF、证书、节点、穿透隧道和 Pages 项目的可视化管理 | [开发约束](../guideline/Constraints.md) | --- ## 组件架构与分工 ### 1. Server (控制面) -`openflare-server` 是 Go 编写的单体控制面: -* 提供管理端 REST API,通过 `OPENFLARE_TOKEN` 请求头鉴权。 +仓库根目录的 Go 后端(模块 `github.com/Rain-kl/Wavelet`)是 OpenFlare 控制面,基于 Wavelet 全栈脚手架构建: +* 提供管理端 REST API(`/api/v1/d/*`),通过 **Session Cookie** 鉴权,可选 `X-Access-Token` 访问令牌。 +* 边缘节点协议走 `/api/v1/agent|relay|tunnel/*`,分别使用 `X-Agent-Token` / `X-Tunnel-Token` 鉴权。 * 包含配置编译器(Compiler),将数据库中的规则、证书与全局参数统一编译为不可变的配置快照及 OpenResty 物理配置文件文本。 * 存储 Pages 部署 ZIP 包于本地 Artifacts 目录,并向 Agent 提供受控的下载接口。 * 后台集成 Uptime Kuma 监控同步服务,自动为可用站点维护 HTTP 探测任务。 -* Go 物理结构采用 `cmd/server` 启动入口、`internal` 私有应用层与根级 `pkg` 共享能力包,跨组件协议类型统一放在 `pkg/protocol`。 +* 启动入口为根目录 `main.go` + `internal/cmd/`(`api` / `worker` / `scheduler` / `all`);OpenFlare 业务在 `internal/apps/openflare/`,边缘协议处理在 `internal/apps/openflare/{agent,relay,flared}/`。 * *详细设计请参阅:[Agent 与发布模型设计](./agent-design.md) 以及 [Uptime Kuma 监控同步设计](./kuma-design.md)* ### 2. Agent (配置落地端) @@ -165,7 +165,6 @@ OpenResty (Agent, TLS/WAF) 修改系统架构或开发新功能前,请按以下顺序阅读: 1. **[产品边界](./index.md)**:了解 OpenFlare 核心定位与不允许逾越的设计边界。 -2. **[开发约束](../guideline/Constraints.md)**:掌握数据模型、API 约定、数据库迁移(Goose)与前端规范。 3. **[Agent 与发布模型](./agent-design.md)**:理解版本快照同步及失败回滚的安全兜底逻辑。 4. **细分领域设计**: * 穿透相关开发:阅读 [内网穿透隧道设计](./tunnel-design.md)。 diff --git a/docs/design/index.md b/docs/design/index.md index 4326b055..9a4958a1 100644 --- a/docs/design/index.md +++ b/docs/design/index.md @@ -62,39 +62,52 @@ OpenFlare 适合需要统一管理多台 OpenResty 代理节点的团队,具 ## 仓库结构 -在贡献代码时,请严格遵守以下物理分层与目录分工,保持代码结构清晰: +OpenFlare 已收敛为**单 monorepo**(Go 模块 `github.com/Rain-kl/Wavelet`)。控制面 Server 与边缘组件(Agent、Relay、OpenFlared)共享同一仓库,业务代码按 Wavelet `internal/apps/` 领域模块组织。 -| 路径 | 职责 | -| ---------------------- | ---------------------------------------------------- | -| `cmd` | 各组件的命令行启动入口及主函数(server, agent, relay, flared) | -| `internal` | 各组件的内部业务逻辑,通过子包隔离控制(agent, relay, flared, 核心控制面等) | -| `frontend` | Next.js App Router 管理端前端,由 Go Server 嵌入托管 | -| `pkg` | 跨组件复用的协议类型与通用工具包 | -| `scripts` | 安装、自更新等系统辅助脚本 | -| `docs` | VitePress 文档站、设计基线、开发规范、部署与配置文档 | -| `docker` | 各组件 of Dockerfile 构建文件 | +在贡献代码时,请严格遵守以下物理分层与目录分工: -### 1. Server 分层 (`internal/` / `cmd/server/`) +| 路径 | 职责 | +| --- | --- | +| `main.go` | Server 唯一入口,委派给 `internal/cmd/` | +| `cmd/agent`、`cmd/relay`、`cmd/flared` | 边缘组件 CLI 入口(**不含** Server) | +| `internal/` | 控制面与边缘运行时实现 | +| `frontend/` | Next.js 管理端,构建产物嵌入 Go Server | +| `pkg/` | 跨组件共享库(协议、渲染、GeoIP 等) | +| `scripts/` | Swagger 生成、安装脚本等 | +| `docs/` | VitePress 文档站与设计基线 | +| `docker/` | 各组件 Dockerfile | +| `uploads/`、`data/` | 运行时上传目录与静态数据(`.gitignore` 忽略) | -| 目录 | 职责 | -| ----------------------- | ------------------------------------------------ | -| `cmd/server/` | Server 命令行启动入口及主函数 | -| `internal/controller/` | 参数解析、调用 service、返回响应 | -| `internal/service/` | 业务逻辑、校验、事务编排、配置渲染 | -| `internal/model/` | 纯净实体模型类定义、旧迁移框架兼容与上下文注入 | -| `internal/model/goose/` | goose 迁移提供者、桥接逻辑、注册入口与具体迁移文件 | -| `internal/router/` | 路由注册 | -| `internal/middleware/` | 认证、鉴权、限流、CORS、Turnstile 验证等横切逻辑 | -| `internal/common/` | 配置、全局状态与初始化入口 | -| `internal/job/` | 定时任务(各业务定时逻辑在独立文件中定义,cron.go 仅用于初始化调度) | -| `internal/utils/` | 仅 Server 内部使用的基础能力包,如 ACME、限流、验证码、邮件、安全校验等 | -| `pkg/protocol/` | Server、Relay、OpenFlared 之间共享 of HTTP/WS 协议结构 | -| `pkg/utils/` | 跨组件可复用的纯工具函数 | -| `pkg/geoip`、`pkg/render`、`pkg/wsclient` | 被多个组件复用的 GeoIP、OpenResty 配置渲染与 WebSocket 客户端能力 | -| `upload/` | 运行时本地临时文件上传目录(在 .gitignore 中忽略) | -| `logs/` | 运行时本地日志输出目录(在 .gitignore 中忽略) | -| `docs/` | API 文档(Swagger) | -| `data/` | 静态数据(如 GeoIP 数据库) | +### 1. Server 分层(`main.go` + `internal/`) + +| 目录 | 职责 | +| --- | --- | +| `main.go` | Server 启动入口 | +| `internal/cmd/` | Cobra 子命令:`api`、`worker`、`scheduler`、`all`(默认融合模式) | +| `internal/bootstrap/` | 跨模块装配:任务 Handler、推送域事件、进程级初始化 | +| `internal/router/` | HTTP 路由注册与全局中间件 | +| `internal/router/v1/openflare/` | OpenFlare 路由注册器(`register_*.go`) | +| `internal/apps/openflare/` | OpenFlare 控制面业务域(`routers.go` + `logics.go`) | +| `internal/apps/{admin,user,oauth,upload,cap,...}/` | Wavelet 平台能力(用户、认证、任务、推送等) | +| `internal/apps/openflare/{agent,relay,flared}/` | **Server 侧**边缘协议处理器(鉴权、心跳、WS) | +| `internal/model/` | GORM 实体(`openflare_*.go` + 平台模型) | +| `internal/db/migrator/goose/` | goose SQL 迁移(PostgreSQL / SQLite / ClickHouse) | +| `internal/repository/` | 平台域数据访问层 | +| `internal/task/` | Asynq 异步任务(Worker + Scheduler) | +| `internal/config/` | Viper 配置加载 | +| `internal/common/` | 统一 API 响应封装(`response/`) | +| `pkg/protocol/` | Relay / Tunnel 共享 HTTP/WS 协议结构 | +| `pkg/render/`、`pkg/geoip/`、`pkg/wsclient/` | OpenResty 配置渲染、GeoIP、WebSocket 客户端 | + +**API 路由前缀:** + +| 前缀 | 用途 | 鉴权 | +| --- | --- | --- | +| `/api/v1/d/*` | OpenFlare 管理控制台 API | Session Cookie + 可选 `X-Access-Token` | +| `/api/v1/agent/*` | Agent 节点协议 | `X-Agent-Token` | +| `/api/v1/relay/*` | Relay 中继协议 | `X-Agent-Token` | +| `/api/v1/tunnel/*` | Tunnel 客户端协议 | `X-Tunnel-Token` | +| `/api/v1/admin/*` | Wavelet 平台管理 API | 管理员 Session | ### 2. Agent 模块 (`internal/apps/agent/` / `cmd/agent/`) @@ -118,24 +131,29 @@ OpenFlare 适合需要统一管理多台 OpenResty 代理节点的团队,具 ### 3. Frontend 分层 (`frontend/`) -| 目录 | 职责 | -| ------------- | -------------------------------------------- | -| `app/` | Next.js App Router 路由、布局、页面组装 | -| `features/` | 按业务域组织的功能模块 | -| `components/` | 跨 feature 复用的 UI 组件 | -| `lib/` | 请求客户端、环境变量、工具函数、常量 | -| `store/` | 少量跨页面 UI 状态管理 | -| `types/` | 共享类型定义 | -| `styles/` | 全局样式 | -| `tests/` | 前端单元测试与集成测试(Vitest、Playwright) | -| `scripts/` | 构建和部署相关脚本 | -| `public/` | 静态资源 | +基于 Wavelet Next.js 脚手架,OpenFlare 业务 UI 以路由共置方式组织在 `app/(main)/` 下。 + +| 目录 | 职责 | +| --- | --- | +| `app/` | Next.js App Router;`(main)` 控制台、`(auth)` 认证、`(docs)` 文档页 | +| `app/(main)//` | 业务页面与域内组件(路由共置) | +| `components/` | 跨域复用 UI(`ui/`、`layout/`、`common/` 等) | +| `lib/services/` | API 服务层:`core/` 基类 + `openflare/` 业务 API | +| `lib/navigation/` | OpenFlare 侧栏导航配置(`openflare-nav.ts`) | +| `lib/theme/` | 主题解析与切换 | +| `contexts/` | 跨页面 UI 状态(用户、通知等) | +| `hooks/`、`lib/hooks/` | 可复用 React Hooks | +| `public/` | 静态资源与主题 CSS | +| `scripts/` | 构建辅助脚本 | +| `proxy.ts` | 开发/生产代理:API 限流与页面鉴权 | + +**API 约定**:OpenFlare 业务接口统一前缀 `/api/v1/d/*`,通过 `OpenFlareBaseService` 封装;页面数据获取使用 `@tanstack/react-query`。 ### 4. Relay 模块 (`internal/apps/relay/` / `cmd/relay/`) | 模块 | 职责 | | ---------------- | ------------------------------------------------ | -| `cmd/` | Relay 命令行启动入口及初始化主函数 | +| `cmd/relay/` | Relay 命令行启动入口及初始化主函数 | | `internal/apps/relay/config/`| 本地配置文件解析与默认参数初始化 | | `internal/apps/relay/frps/` | 管理 frps 进程生命周期、端口与 Token 并监控运行 | | `internal/apps/relay/heartbeat/`| 周期性 HTTP 心跳通信、上报状态并获取更新请求 | @@ -150,16 +168,18 @@ OpenFlare 适合需要统一管理多台 OpenResty 代理节点的团队,具 | 模块 | 职责 | | ---------------- | ------------------------------------------------ | -| `cmd/` | Client 命令行启动入口及初始化主函数 | +| `cmd/flared/` | Client 命令行启动入口及初始化主函数 | | `internal/apps/flared/config/`| 本地客户端配置加载与解析 | | `internal/apps/flared/flared/`| 内网穿透客户端的核心调度与状态管理机制 | -| `internal/apps/flared/frpc/` | 热重载/动态生成多 Relay 的 `frpc.toml` 并监控 frpc | +| `internal/apps/flared/frpc/` | 热重载/动态生成多 Relay 的 `frpc_{relayNodeID}.toml` 并监控 frpc | | `internal/apps/flared/heartbeat/`| 与控制面进行的心跳通信,包含 Token 校验机制 | -| `internal/apps/flared/httpclient/`| 客户端通用 API 通信客户端 | +| `internal/apps/flared/httpclient/`| 客户端通用 API 通信(`/api/v1/tunnel/*`) | | `internal/apps/flared/sync/` | 增量拉取最新 Tunnel 路由绑定关系、生成快照并应用 | | `internal/apps/flared/updater/`| 客户端自更新、新版检查与更新落地逻辑 | | `internal/apps/flared/wsclient/`| 用于实时监听 Server 端隧道配置变更推送的 WS 信道 | +> **说明**:OpenFlared 无独立 `state/` 包;版本与 checksum 由 `frpc/manager.go` 持久化到 `flared-state.json`。 + --- ## 文档维护原则 @@ -167,6 +187,5 @@ OpenFlare 适合需要统一管理多台 OpenResty 代理节点的团队,具 * 产品范围或系统边界变化:更新本文档([产品边界](./index.md))。 * 系统结构、组件分工变化:更新 [系统架构](./architecture.md)。 * 发布、同步、回滚与 Agent 模型变化:更新 [Agent 与发布模型](./agent-design.md)。 -* 开发约束、代码规范、接口约定变化:更新 [开发约束](../guideline/Constraints.md)。 * 部署方式变化:更新 [部署说明](../deployment/deployment.md) 与 README。 * 配置项变化:更新 [配置项参考](../reference/configuration.md)。 diff --git a/docs/en/config.ts b/docs/en/config.ts deleted file mode 100644 index c77e3683..00000000 --- a/docs/en/config.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { defineAdditionalConfig, type DefaultTheme } from 'vitepress' - -export default defineAdditionalConfig({ - description: - 'OpenFlare is a lightweight, self-hosted OpenResty control plane for managing reverse proxy rules, configuration publishing, node synchronization, TLS certificates, and basic observability.', - - themeConfig: { - nav: nav(), - - sidebar: { - '/en/guide/': { base: '/en/guide/', items: sidebarGuide() }, - '/en/reference/': { base: '/en/reference/', items: sidebarReference() }, - '/en/design/': { base: '/en/design/', items: sidebarDesign() } - }, - - editLink: { - pattern: 'https://github.com/Rain-kl/OpenFlare/edit/main/docs/:path', - text: 'Edit this page on GitHub' - }, - - footer: { - message: 'Released under the Apache License 2.0', - copyright: 'Copyright © OpenFlare contributors' - }, - - docFooter: { - prev: 'Previous Page', - next: 'Next Page' - }, - - outline: { - label: 'On this page' - }, - - lastUpdated: { - text: 'Last updated at' - }, - - notFound: { - title: 'Page Not Found', - quote: 'This document does not have a corresponding page yet.', - linkLabel: 'Go to Home', - linkText: 'Back to OpenFlare Docs' - }, - - langMenuLabel: 'Language', - returnToTopLabel: 'Back to top', - sidebarMenuLabel: 'Menu', - darkModeSwitchLabel: 'Theme', - lightModeSwitchTitle: 'Switch to light theme', - darkModeSwitchTitle: 'Switch to dark theme', - skipToContentLabel: 'Skip to content' - } -}) - -function nav(): DefaultTheme.NavItem[] { - return [ - { text: 'Guide', link: '/en/guide/', activeMatch: '/en/guide/' }, - { text: 'Reference', link: '/en/reference/', activeMatch: '/en/reference/' }, - { text: 'Design', link: '/en/design/', activeMatch: '/en/design/' } - ] -} - -function sidebarGuide(): DefaultTheme.SidebarItem[] { - return [ - { - text: 'Guide', - items: [ - { text: 'Overview', link: '' }, - { text: 'Quick Start', link: 'quick-start' }, - { text: 'Basic Usage', link: 'usage' }, - { text: 'Tunnel & Intranet Penetration', link: 'tunnel-usage' }, - { text: 'WAF Security Protection', link: 'waf-usage' }, - { text: 'WAF Auto IP Group Expressions', link: 'waf-ip-group-expr' }, - { text: 'SSO Login Configuration', link: 'sso' }, - { text: 'Publish First Configuration', link: 'first-site' }, - { text: 'Troubleshooting', link: 'troubleshooting' }, - { text: 'Credits', link: 'credits' } - ] - } - ] -} - -function sidebarReference(): DefaultTheme.SidebarItem[] { - return [ - { - text: 'Reference', - items: [ - { text: 'Overview', link: '' }, - { text: 'System Architecture', link: '../design/architecture' }, - { text: 'Launch Server', link: '../deployment/server' }, - { text: 'Access Agent', link: '../deployment/agent' }, - { text: 'Deployment Guide', link: '../deployment/deployment' }, - { text: 'Deploy Relay (Tunnel)', link: '../deployment/relay' }, - { text: 'Deploy OpenFlared', link: '../deployment/openflared' }, - { text: 'Upgrade & Maintenance', link: '../deployment/upgrade' }, - { text: 'Configuration Options', link: 'configuration' }, - { text: 'CLI Commands', link: 'cli' }, - { text: 'API Conventions', link: 'api' } - ] - } - ] -} - -function sidebarDesign(): DefaultTheme.SidebarItem[] { - return [ - { - text: 'Design', - items: [ - { text: 'Product Boundaries', link: '' }, - { text: 'System Architecture', link: 'architecture' }, - { text: 'Agent & Publish Model', link: 'agent-design' }, - { text: 'Tunnel & Intranet Penetration', link: 'tunnel-design' }, - { text: 'WAF Design', link: 'waf-design' }, - { text: 'Repository Structure', link: 'repository' } - ] - } - ] -} diff --git a/docs/en/deployment/agent.md b/docs/en/deployment/agent.md deleted file mode 100644 index fc5c7408..00000000 --- a/docs/en/deployment/agent.md +++ /dev/null @@ -1,176 +0,0 @@ -# Access Agent - -You will learn: The responsibilities of the Agent, the difference between the two access Tokens, installation script parameters, `agent.json` settings, and how to verify that the node has successfully connected. - -The OpenFlare Agent runs on the proxy node. It does not receive arbitrary remote shell commands; instead, it pulls the configuration version published by the control plane via the Agent API, writes files for OpenResty locally, executes configuration validation, reloads, and attempts to roll back to a working configuration if it fails. - -## Connection Credentials - -| Method | Applicable Scenario | -| --- | --- | -| `discovery_token` | Automatically registers a node for the first time, which the Server exchanges for a node-specific credential | -| `agent_token` | Node has already been created/allocated in the management console, directly uses this node-specific credential | - -At least one of `agent_token` or `discovery_token` must be configured. - -### Credential Retrieval Path - -- **`discovery_token` (Auto Registration Token)**: Log into the management console, navigate to "System Settings" -> "Auto Registration", where you can generate, view, and copy the global auto-registration credential. -- **`agent_token` (Node Specific Token)**: Log into the management console, navigate to "Node Management" -> "Add Node", fill in basic node information, save, and copy the node-specific access Token in the node details. - -## One-Click Installation - -Using the `discovery_token`: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --discovery-token YOUR_DISCOVERY_TOKEN -``` - -Using the node-specific `agent_token`: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --agent-token YOUR_AGENT_TOKEN -``` - -The installation script downloads the latest Agent, writes to `/opt/openflare-agent` by default, generates `agent.json`, and registers `openflare-agent.service` on Linux + systemd environments. - -Supported arguments: - -| Argument | Description | Default Value | -| --- | --- | --- | -| `--server-url` | Server address (required) | | -| `--discovery-token` | One-time auto-registration Token | | -| `--agent-token` | Node-specific Token | | -| `--install-dir` | Target installation directory | `/opt/openflare-agent` | -| `--openresty-path` | Path to the OpenResty binary; automatically detects `openresty` if unspecified | | -| `--repo` | GitHub repository to download from | `Rain-kl/OpenFlare` | -| `--no-service` | Do not register systemd service | | - -## Configuration File - -Default configuration file path: - -```text -/opt/openflare-agent/agent.json -``` - -Example local configuration: - -```json -{ - "server_url": "http://127.0.0.1:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "./data", - "openresty_path": "openresty", - "openresty_observability_port": 18081, - "observability_replay_minutes": 15, - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -Example customized OpenResty paths configuration: - -```json -{ - "server_url": "http://127.0.0.1:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "/var/lib/openflare-agent", - "openresty_path": "/usr/local/openresty/nginx/sbin/openresty", - "main_config_path": "/var/lib/openflare-agent/etc/nginx/nginx.conf", - "route_config_path": "/var/lib/openflare-agent/etc/nginx/conf.d/openflare_routes.conf", - "access_log_path": "/var/lib/openflare-agent/var/log/openflare/access.log", - "cert_dir": "/var/lib/openflare-agent/etc/nginx/certs", - "lua_dir": "/var/lib/openflare-agent/etc/nginx/lua", - "runtime_config_dir": "/var/lib/openflare-agent/etc/openflare", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -If `openresty_path` is not configured, the Agent calls `openresty` by default. For the full fields, see [Configurations Reference](../reference/configuration.md#agent-configurations-fields). - -## Running in Docker - -For Docker deployments, run the Agent image containing built-in OpenResty directly: - -```bash -docker pull ghcr.io/rain-kl/openflare-agent:latest -docker rm -f openflare-agent 2>/dev/null || true -docker run -d --name openflare-agent --restart unless-stopped \ - -p 80:80 -p 443:443 \ - -e OPENFLARE_SERVER_URL=http://your-server:3000 \ - -e OPENFLARE_AGENT_TOKEN=YOUR_AGENT_TOKEN \ - ghcr.io/rain-kl/openflare-agent:latest -``` - -## Start & Validate - -In a systemd environment: - -```bash -systemctl start openflare-agent -systemctl status openflare-agent -journalctl -u openflare-agent -f -``` - -Manual execution: - -```bash -/opt/openflare-agent/openflare-agent -config /opt/openflare-agent/agent.json -``` - -Running from source: - -```bash -cd openflare-agent -export LOG_LEVEL='info' -go run ./cmd/agent -config /path/to/agent.json -``` - -Running compiled binary: - -```bash -cd openflare-agent -go build -o openflare-agent ./cmd/agent -export LOG_LEVEL='info' -./openflare-agent -config /path/to/agent.json -``` - -Confirm in the management console: - -| Position | Expected Result | -| --- | --- | -| Node List | Node status is online | -| Node Details | Heartbeat, current version, and basic resource metrics display correctly | -| Apply Logs | Application result displays after publishing | - -## Uninstall - -To completely uninstall the Agent and wipe local data: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash -``` - -Supported arguments: - -| Argument | Description | Default Value | -| --- | --- | --- | -| `--install-dir` | Installation directory | `/opt/openflare-agent` | -| `--service-name` | systemd service name | `openflare-agent` | - -The uninstallation script only removes the Agent service, processes, and installation directory; it does not uninstall OpenResty from the host. - -## Common Questions - -| Symptom | Actions | -| --- | --- | -| `agent_token and discovery_token cannot both be empty` | Check if at least one Token is configured in `agent.json` | -| Node stays offline | Run `curl -I http://your-server:3000` on the Agent node to verify that the Server is reachable | -| OpenResty is not running | Review `journalctl -u openflare-agent`, checking that `openresty_path` is executable and ports 80/443 are not bound | -| Repeated application failures after publishing | The Agent blocks repeated sync attempts of the same failing `version + checksum`; fix the configuration and republish, or activate an older version to roll back | diff --git a/docs/en/deployment/deployment.md b/docs/en/deployment/deployment.md deleted file mode 100644 index f17e9834..00000000 --- a/docs/en/deployment/deployment.md +++ /dev/null @@ -1,287 +0,0 @@ -# Deployment Guide - -You will learn: The recommended deployment strategies for OpenFlare, the system requirements for Server and Agent, how to run from source, integration steps, upgrades, and uninstallation entrypoints. - -In production environments, we highly recommend using PostgreSQL as the Server database and explicitly configuring `SESSION_SECRET` for the Server. The recommended Agent deployment method is Docker (which runs the Agent image containing built-in OpenResty); host systemd service installation via script and manual local run are also supported. - -## Deployment Topology - -### Standard Reverse Proxy Traffic Path - -```text -Browser - | - v -OpenFlare Server :3000 - | - | Agent API / heartbeat / config pull - v -OpenFlare Agent - | - v -OpenResty binary - | - v -Origin service -``` - -### Intranet Penetration Traffic Path - -```text -Browser - | - v -OpenResty (Agent, WAF/HTTPS Termination) <-- TunnelRelay Node - | - | proxy_pass (127.0.0.1:{vhost_port}) - v -OpenFlareRelay (frps process) <-- TunnelRelay Node - | - | frp tunnel protocol - v -OpenFlared (frpc client) <-- Intranet Server - | - v -Internal Service (192.168.x.x) -``` - -## Prerequisites - -Server: - -| Item | Requirement | -| --- | --- | -| Go | `1.25+`, required only when running from source | -| Node.js | `18+`, required only when building the admin frontend from source | -| Database | Writable SQLite parent directory, or a reachable PostgreSQL instance | -| Port | Listens on port `3000` by default | - -Agent: - -| Item | Requirement | -| --- | --- | -| System | The installation script supports Linux and macOS; the systemd service is created only on Linux + systemd environments | -| Architecture | `amd64` or `arm64` | -| OpenResty | Required to have the `openresty` executable when deploying locally, or specify its path via `--openresty-path` | -| Docker | Required only when deploying the Agent via Docker image | -| Network | The Agent node must be able to reach the Server address | -| GeoIP | WAF regional rules rely on the Agent's local MaxMind mmdb; the Agent initializes a built-in library on startup and updates it periodically | - -### Hardware Allocation Recommendations - -| Component | Minimum Allocation | Recommended Allocation | Note | -| --- | --- | --- | --- | -| **Server Control Plane** | 1 Core CPU / 1 GB RAM / 10 GB Disk | 2 Cores CPU / 4 GB RAM / 50 GB+ Disk | Expand disk allocation according to log retention windows and concurrency. | -| **Agent Data Plane** | 1 Core CPU / 512 MB RAM / 2 GB Disk | 2 Cores CPU / 2 GB RAM / 10 GB+ Disk | Expand according to concurrent reverse proxy connections and WAF workloads. | -| **Relay Node** | 1 Core CPU / 1 GB RAM / 5 GB Disk | 2 Cores CPU / 2 GB RAM / 20 GB Disk | frps throughput is primarily bounded by CPU processing capacity and bandwidth. | -| **OpenFlared Client** | 1 Core CPU / 256 MB RAM / 1 GB Disk | 1 Core CPU / 512 MB RAM / 5 GB Disk | Runs inside the intranet; utilizes minimal CPU/RAM, optimize for network throughput. | - -## Docker Compose Deployment for Server - -Create a `docker-compose.yml` file: - -```yaml -services: - postgres: - image: postgres:17-alpine - restart: unless-stopped - environment: - POSTGRES_DB: openflare - POSTGRES_USER: openflare - POSTGRES_PASSWORD: replace-with-strong-password - volumes: - - postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U openflare -d openflare"] - interval: 10s - timeout: 5s - retries: 5 - - openflare: - image: ghcr.io/rain-kl/openflare:latest - container_name: openflare - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - ports: - - "3000:3000" - environment: - SESSION_SECRET: replace-with-a-long-random-string - DSN: postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable - GIN_MODE: release - LOG_LEVEL: info - volumes: - - openflare-data:/data - -volumes: - postgres-data: - openflare-data: -``` - -Start the Server: - -```bash -docker compose up -d -docker compose ps -docker compose logs -f openflare -``` - -Access `http://localhost:3000` for the first time, using the default credentials `root` / `123456`. Please change the default password immediately after logging in. - -## Start Server from Source - -First, build the admin frontend: - -```bash -cd openflare-server/web -corepack enable -pnpm install -pnpm build -``` - -Then, launch the Server: - -```bash -cd openflare-server -export SESSION_SECRET='replace-with-a-long-random-string' -export SQLITE_PATH='./openflare.db' -export LOG_LEVEL='info' -# Optional: Prefer PostgreSQL by setting DSN -# export DSN='postgres://openflare:secret@127.0.0.1:5432/openflare?sslmode=disable' -go run . -``` - -By default, the Server listens on port `3000`. You can also specify it explicitly: - -```bash -go run . --port 3000 --log-dir ./logs -``` - -## Running Agent in Docker (Recommended) - -Docker is the recommended deployment method for the Agent. Running the Agent image directly launches the Agent controller alongside the built-in OpenResty binary. If `node_ip` is left blank, the Agent automatically resolves its outbound public IP via third-party APIs, avoiding registering the Docker bridge address as the node IP. - -Mounting the configuration file: - -```bash -docker pull ghcr.io/rain-kl/openflare-agent:latest -docker rm -f openflare-agent 2>/dev/null || true -docker run -d --name openflare-agent --restart unless-stopped \ - -p 80:80 -p 443:443 \ - -v openflare-agent-data:/data \ - -v ./agent.json:/etc/openflare/agent.json:ro \ - ghcr.io/rain-kl/openflare-agent:latest -``` - -Using environment variables: - -```bash -docker pull ghcr.io/rain-kl/openflare-agent:latest -docker rm -f openflare-agent 2>/dev/null || true -docker run -d --name openflare-agent --restart unless-stopped \ - -p 80:80 -p 443:443 \ - -e OPENFLARE_SERVER_URL=http://your-server:3000 \ - -e OPENFLARE_AGENT_TOKEN=YOUR_AGENT_TOKEN \ - ghcr.io/rain-kl/openflare-agent:latest -``` - -## Agent Connection via Installation Script - -Apart from Docker, you can deploy the Agent directly on a Linux/macOS host using the installation script. - -Auto-register using `discovery_token`: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --discovery-token YOUR_DISCOVERY_TOKEN -``` - -Connect using node-specific `agent_token`: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --agent-token YOUR_AGENT_TOKEN -``` - -Installation script arguments: - -| Argument | Description | Default Value | -| --- | --- | --- | -| `--server-url` | Server address (required) | | -| `--discovery-token` | Auto-registration Token; mutually exclusive with `--agent-token` | | -| `--agent-token` | Node-specific Token; mutually exclusive with `--discovery-token` | | -| `--install-dir` | Target installation directory | `/opt/openflare-agent` | -| `--openresty-path` | Path to the OpenResty binary; automatically detects `openresty` if unspecified | | -| `--repo` | GitHub repository to download from | `Rain-kl/OpenFlare` | -| `--no-service` | Do not register systemd service | | - -Confirm service status: - -```bash -systemctl status openflare-agent -journalctl -u openflare-agent -f -``` - -## Running the Agent Manually - -Running from source: - -```bash -cd openflare-agent -export LOG_LEVEL='info' -go run ./cmd/agent -config /path/to/agent.json -``` - -Running compiled binary: - -```bash -cd openflare-agent -go build -o openflare-agent ./cmd/agent -export LOG_LEVEL='info' -./openflare-agent -config /path/to/agent.json -``` - -Minimal `agent.json` example: - -```json -{ - "server_url": "http://127.0.0.1:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "./data", - "openresty_path": "openresty", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -If `openresty_path` is left blank, the Agent calls `openresty` by default. - -By default, the Agent attempts to upgrade the HTTP heartbeat connection to WebSocket once successfully registered. Once upgraded, configuration activations on the Server notify the Agent instantly; if WebSocket disconnects or fails to establish, the Agent gracefully falls back to HTTP polling. - -WAF geographical filtering depends on the local `GeoLite2-Country.mmdb`. The Agent automatically writes the built-in database to `data_dir/etc/openflare/GeoLite2-Country.mmdb` on startup and checks for periodic updates. Muted warnings are logged if updates fail, having no impact on Nginx configuration sync or reloads. - -## Upgrades & Uninstallation - -Server: - -* Root users can check and trigger Server upgrades in the top header of the management console. -* To deploy preview releases, manually check the GitHub Releases page. -* You can also trigger upgrades by uploading the compiled Server binary in the console. - -Agent: - -* By default, the Agent automatically upgrades following stable releases. -* Agent self-updates require the GitHub Release to contain the compiled binary and a matching `.sha256` checksum file; updates are blocked if the downloaded binary fails the SHA-256 validation. -* You can re-execute the installation script to redeploy or force-update the Agent. -* Upgrading to preview releases requires a manual trigger. - -Uninstalling the Agent: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash -``` - -The uninstallation script stops the Agent process, removes the systemd service unit, and wipes the installation directory, without uninstalling OpenResty from the host. diff --git a/docs/en/deployment/index.md b/docs/en/deployment/index.md deleted file mode 100644 index 570f8f3f..00000000 --- a/docs/en/deployment/index.md +++ /dev/null @@ -1,24 +0,0 @@ -# Deployment & Upgrade - -This section provides detailed deployment guides, configuration instructions, and upgrade maintenance procedures for the OpenFlare Server, Agent, Relay, and the OpenFlared client. - -## Content Navigation - -### Quick Start -* **[Quick Start](../guide/quick-start.md)**: Start the Server and your first Agent in under 5 minutes using Docker Compose (recommended for new users). - -### Server Deployment -* **[Launch Server](./server.md)**: Learn how to build the frontend from source, start the Server, and choose between SQLite or PostgreSQL. - -### Agent Deployment -* **[Deploy Agent](./agent.md)**: Explore Agent connection methods, Docker deployment, host script installation, config files, and troubleshooting. - -### Tunnel Intranet Penetration Deployment -* **[Deploy Relay](./relay.md)**: View config descriptions, Docker deployment, and host runtime guides for TunnelRelay nodes. -* **[Deploy OpenFlared](./openflared.md)**: Access config descriptions, Docker runtime, and auto-sync mechanisms for the intranet client. - -### Upgrade & Maintenance -* **[Upgrade & Maintenance](./upgrade.md)**: Discover upgrading procedures for Server/Agent, data retention rules, and validation commands. - -### Reference Manuals -* **[Deployment Guide](./deployment.md)**: Browse deployment topologies, prerequisites, Docker Compose samples, and multiple deployment strategies. diff --git a/docs/en/deployment/openflared.md b/docs/en/deployment/openflared.md deleted file mode 100644 index a8ad41d5..00000000 --- a/docs/en/deployment/openflared.md +++ /dev/null @@ -1,119 +0,0 @@ -# Deploy OpenFlared Client - -You will learn: The responsibilities of the OpenFlared client, configuration parameters and environment variables, how to run the client via Docker, and how to deploy the client on an intranet server using the compiled host binary. - -**OpenFlared** is a tunnel client deployed in the user's intranet environment (LANs, private VPCs, or other environments that cannot be directly accessed from the public internet). Its core responsibility is to establish communication with the control plane (OpenFlare Server) via the `X-Tunnel-Token` header, automatically spawning and managing one or more **frpc (Fast Reverse Proxy Client)** subprocesses locally to securely and stably tunnel HTTP traffic back to public relay nodes. - ---- - -## Prerequisites - -1. **Retrieve Tunnel Token**: Create a new tunnel instance on the "Intranet Penetration" or "Tunnel Management" page in the OpenFlare management console; the system will automatically generate a unique `tunnel_id` and a `tunnel_token` (e.g., `tun-<32hex>`). -2. **Outbound Network Permissions**: The intranet server does not require any inbound public IPs or port mappings, but it must be able to reach the **OpenFlare Server URL** and the corresponding **TunnelRelay node control port (default 7000)** over the outbound network. -3. **Software Dependencies** (Host deployment only): - - You must have an executable `frpc` binary locally (recommended version `v0.61.0+` or the latest stable `v0.69.0`), or specify its path explicitly in the configuration. - ---- - -## Configuration & Environment Variables - -`openflared` reads `flared.json` in the working directory by default on startup. Overriding options via environment variables is fully supported. - -### Configuration Fields Details - -| JSON Field | Environment Variable | Description | Default Value | -| --- | --- | --- | --- | -| `server_url` | `OPENFLARE_SERVER_URL` | OpenFlare Server API base URL | **None (Required)** | -| `tunnel_token` | `OPENFLARE_TUNNEL_TOKEN` | Tunnel client dedicated access Token | **None (Required)** | -| `frpc_path` | `OPENFLARE_FRPC_PATH` | Path to the `frpc` executable binary | `"frpc"` | -| `data_dir` | `OPENFLARE_DATA_DIR` | Directory to store local data and generated `frpc_{relayNodeID}.toml` configs | `"./data"` | -| `state_path` | - | Path to store local state JSON file (saving the last applied version) | `"{data_dir}/flared-state.json"` | -| `heartbeat_interval`| - | Heartbeat reporting interval (ms or Go Duration string) | `10000` (10s) | -| `sync_interval` | - | Tunnel config polling interval (ms or Go Duration string) | `30000` (30s) | -| `request_timeout` | - | HTTP request timeout duration | `10000` (10s) | - ---- - -## Docker Deployment (Recommended) - -Docker is the simplest and safest way to run the client inside the intranet. The official `openflared` image embeds the client controller and `frpc v0.69.0` out of the box, requiring no environment setup. - -```bash -docker pull ghcr.io/rain-kl/openflared:latest -docker rm -f openflared 2>/dev/null || true - -docker run -d --name openflared --restart unless-stopped \ - -e OPENFLARE_SERVER_URL=http://your-server:3000 \ - -e OPENFLARE_TUNNEL_TOKEN=YOUR_TUNNEL_TOKEN \ - -v openflared-data:/app/data \ - ghcr.io/rain-kl/openflared:latest -``` - ---- - -## Manual Host Deployment - -If you need to run the client directly on a Linux/macOS/Windows host inside the intranet: - -### 1. Compile the Binary - -```bash -cd openflared -go build -o flared ./cmd/flared -``` - -### 2. Prepare `flared.json` - -Create a `flared.json` configuration file in the same directory as the executable: - -```json -{ - "server_url": "http://your-server-ip:3000", - "tunnel_token": "your-tunnel-auth-token", - "frpc_path": "/usr/local/bin/frpc", - "data_dir": "./data", - "heartbeat_interval": "10s", - "sync_interval": "30s" -} -``` - -### 3. Start the Service - -```bash -export LOG_LEVEL='info' -./flared -config ./flared.json -``` - ---- - -## Start & Validate - -### 1. Auto-Sync Workflow - -Once started successfully, OpenFlared operates the following workflow: -- **Heartbeat & Config Fetching**: Periodically polls `/api/flared/heartbeat` and `/api/flared/config` endpoints to validate the Token and evaluate configuration versions. -- **File Rendering**: When a new configuration version (or checksum mismatch) is detected, it pulls the complete tunnel routing rules. If multiple Relays are bound, it renders `frpc_{relayNodeID}.toml` configurations in `data_dir` for each Relay. -- **Hot Reload or Restart**: Spawns the corresponding `frpc` subprocesses, or executes `frpc reload` / restart actions when configurations change, ensuring traffic mappings are kept up to date. -- **Process Auto-Recovery**: If a local `frpc` tunnel process exits unexpectedly, the master program automatically restarts it after a 5-second backoff penalty. - -### 2. View Logs & Connection Status - -```bash -# Docker container logs -docker logs -f openflared -``` - -If running correctly, the logs will show output similar to: -```text -flared config loaded ... -detected frpc version v0.69.0 -flared process started -applying new tunnel config {"version": "...", "checksum": "..."} -frpc process missing, starting {"relay_id": "..."} -``` - -### 3. Verify in the Management Console - -Open the **"Intranet Penetration"** page in the management console: -- Check the online status of the corresponding tunnel; it should display green as **"Online"**. -- You can inspect which relay nodes the tunnel is connected to, and view the detailed routing configurations of the intranet services. diff --git a/docs/en/deployment/relay.md b/docs/en/deployment/relay.md deleted file mode 100644 index ee0b8eb9..00000000 --- a/docs/en/deployment/relay.md +++ /dev/null @@ -1,126 +0,0 @@ -# Deploy Relay (Tunnel Relay) - -You will learn: The responsibilities of a TunnelRelay node, `openflare-relay` configuration parameters and environment variables, how to run the Relay via Docker, and how to build and deploy the Relay from source manually. - -In the OpenFlare intranet penetration architecture, the **TunnelRelay node** plays a key role. Unlike standard Edge Nodes, in addition to running the traditional Agent (managing OpenResty for HTTPS/WAF processing), it co-locates the **Relay (frps tunnel manager)** service, responsible for listening to intranet client (OpenFlared) tunnel connections and relaying traffic. - ---- - -## Prerequisites - -Before deploying a TunnelRelay node, ensure: - -1. **Registered as a TunnelRelay node**: Add a node of type `tunnel_relay` in the OpenFlare management console under "Node Management", and retrieve its node-specific `agent_token` or use the global `discovery_token`. -2. **Network Ports**: - - Ensure `bindPort` (the port frpc clients connect to, default `7000`) is accessible from the public/intranet client networks. - - Ensure `vhostHTTPPort` (the HTTP Vhost port, default `8080`) is free and not bound by other processes, as the Agent routes traffic to frps on this port. -3. **Software Dependencies** (Host deployment only): - - You must have an executable `frps` binary locally (recommended version `v0.61.0+` or the latest stable `v0.69.0`), or specify its path explicitly in the configuration. - ---- - -## Configuration & Environment Variables - -`openflare-relay` reads `relay.json` in the working directory by default on startup. Overriding options via environment variables is fully supported. - -### Configuration Fields Details - -| JSON Field | Environment Variable | Description | Default Value | -| --- | --- | --- | --- | -| `server_url` | `OPENFLARE_SERVER_URL` | OpenFlare Server API base URL | **None (Required)** | -| `agent_token` | `OPENFLARE_AGENT_TOKEN` | Node-specific Token | Mutually exclusive with below | -| `discovery_token` | `OPENFLARE_DISCOVERY_TOKEN` | One-time auto-registration Token | Mutually exclusive with above | -| `node_name` | `OPENFLARE_NODE_NAME` | Custom name for the node | Hostname by default | -| `node_ip` | `OPENFLARE_NODE_IP` | Outbound/listening IP of the node | Automatically detects real outbound IP | -| `frps_path` | `OPENFLARE_FRPS_PATH` | Path to the `frps` executable binary | `"frps"` | -| `data_dir` | `OPENFLARE_DATA_DIR` | Directory to store local data and generated `frps.toml` | `"./data"` | -| `state_path` | - | Path to store local state JSON file | `"{data_dir}/relay-state.json"` | -| `heartbeat_interval`| - | Heartbeat interval (integer ms or Go Duration string) | `10000` (10s) | -| `request_timeout` | - | HTTP request timeout duration | `10000` (10s) | - ---- - -## Docker Deployment (Recommended) - -Docker is the most convenient way to deploy a TunnelRelay node. The official Docker image embeds the `openflare-relay` controller and `frps v0.69.0` out of the box. - -```bash -docker pull ghcr.io/rain-kl/openflare-relay:latest -docker rm -f openflare-relay 2>/dev/null || true - -docker run -d --name openflare-relay --restart unless-stopped \ - -p 7000:7000 \ - -e OPENFLARE_SERVER_URL=http://your-server:3000 \ - -e OPENFLARE_AGENT_TOKEN=YOUR_AGENT_TOKEN \ - -v openflare-relay-data:/var/lib/openflare-relay \ - ghcr.io/rain-kl/openflare-relay:latest -``` - -> [!TIP] -> The `-p 7000:7000` option maps the port `frpc` clients connect to. If a custom `relay_bind_port` is configured in the management console, change this port mapping on the host accordingly. - ---- - -## Manual Host Deployment - -If you prefer to run the Relay directly on a physical host or VM: - -### 1. Compile the Binary - -```bash -cd openflare-relay -go build -o openflare-relay ./cmd/relay -``` - -### 2. Prepare `relay.json` - -Create a `relay.json` configuration file in the same directory as the executable: - -```json -{ - "server_url": "http://127.0.0.1:3000", - "agent_token": "your-relay-node-agent-token", - "frps_path": "/usr/local/bin/frps", - "data_dir": "./data", - "heartbeat_interval": "10s", - "request_timeout": "10s" -} -``` - -### 3. Start the Service - -```bash -export LOG_LEVEL='info' -./openflare-relay -config ./relay.json -``` - ---- - -## Start & Validate - -### 1. View Process Logs - -```bash -# Docker container logs -docker logs -f openflare-relay -``` - -If managed via systemd on Linux, execute: -```bash -journalctl -u openflare-relay -f -``` - -### 2. Verify Runtime Status - -Upon starting successfully, the Relay operates as follows: -- Sends HTTP heartbeats to register and go online with the control plane. -- Retrieves the active frps baseline settings (including `bindPort`, `vhostHTTPPort`, and the auto-generated `auth_token`). -- Automatically renders the `data/frps.toml` configuration locally. -- Spawns the subprocess `frps -c data/frps.toml`. -- If the `frps` process crashes, the Relay automatically restarts it after 2 seconds. - -### 3. Verify in the Management Console - -Log into the management console and navigate to **"Node Management"** to verify: -- The TunnelRelay node status is marked as **"Online"**. -- The Node Type is correctly displayed as **Relay Node** and the frps status displays as **Healthy**. diff --git a/docs/en/deployment/server.md b/docs/en/deployment/server.md deleted file mode 100644 index 9f862980..00000000 --- a/docs/en/deployment/server.md +++ /dev/null @@ -1,170 +0,0 @@ -# Launch Server - -You will learn: How to build the admin frontend from source, start the OpenFlare Server, choose between SQLite or PostgreSQL, and access Swagger. - -OpenFlare Server is a Gin + GORM monolithic control plane, responsible for managing the Admin UI, Admin API, Agent API, configuration rendering, version publishing, data storage, and aggregated queries. - -## Prerequisites - -| Item | Requirement | -| --- | --- | -| Go | `1.25+` | -| Node.js | `18+` | -| pnpm | Recommended enabling via `corepack enable` | -| Database | SQLite parent directory must be writable, or a reachable PostgreSQL instance | - -In production environments, we highly recommend explicitly configuring `SESSION_SECRET` and prioritizing PostgreSQL. - -## Build the Admin Frontend - -The Go Server hosts static assets located in `openflare-server/web/build`. Before starting the Server from source, build the frontend: - -```bash -cd openflare-server/web -corepack enable -pnpm install -pnpm build -``` - -Common frontend quality checks: - -```bash -pnpm lint -pnpm typecheck -pnpm test -``` - -## Start with SQLite - -```bash -cd openflare-server -export SESSION_SECRET='replace-with-a-long-random-string' -export SQLITE_PATH='./openflare.db' -export LOG_LEVEL='info' -go run . -``` - -By default, the Server listens on port `3000`. Access it at: - -```text -http://localhost:3000 -``` - -## Start with PostgreSQL - -```bash -cd openflare-server -export SESSION_SECRET='replace-with-a-long-random-string' -export DSN='postgres://openflare:secret@127.0.0.1:5432/openflare?sslmode=disable' -export LOG_LEVEL='info' -go run . -``` - -If `DSN` is set, it takes precedence over SQLite. When both `DSN` and the legacy `SQL_DSN` exist, `DSN` is prioritized. - -If the target PostgreSQL database is empty and a local SQLite database exists at `SQLITE_PATH`, the Server automatically migrates the SQLite data into PostgreSQL during startup, outputting the migration progress in the logs. - -## Start with Docker - -Deploying with Docker avoids the hassle of setting up local Go and Node.js environments. OpenFlare provides official Dockerfiles and Compose configurations to support independent container startups and multi-service orchestrations. - -### 1. Quick Start via Docker Run (SQLite Example) - -Ensure that a local directory for persisting databases and logs has been created. Run the following command to start the Server: - -```bash -# Create local mount directory -mkdir -p ./openflare-data - -# Start the container -docker run -d \ - --name openflare-server \ - -p 3000:3000 \ - -v $(pwd)/openflare-data:/data \ - -e SESSION_SECRET='replace-with-a-long-random-string' \ - -e SQLITE_PATH='/data/openflare.db' \ - -e GIN_MODE='release' \ - -e LOG_LEVEL='info' \ - ghcr.io/rain-kl/openflare:latest -``` - -Startup parameters: -* **`-p 3000:3000`**: Maps port `3000` on the host to port `3000` inside the container. -* **`-v $(pwd)/openflare-data:/data`**: Mounts the local directory to `/data` in the container, ensuring that the SQLite database `openflare.db` is not lost when restarting or rebuilding the container. -* **`SESSION_SECRET`**: The session signing hash key (required). - ---- - -### 2. One-click Startup via Docker Compose (Integrated PostgreSQL) - -We recommend using Docker Compose in production environments to orchestrate an independent PostgreSQL database and establish high-availability relationships. - -Create a `docker-compose.yml` file: - -```yaml -services: - postgres: - image: postgres:17-alpine - restart: unless-stopped - environment: - POSTGRES_DB: openflare - POSTGRES_USER: openflare - POSTGRES_PASSWORD: replace-with-strong-password - volumes: - - ./postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U openflare -d openflare"] - interval: 10s - timeout: 5s - retries: 5 - - openflare: - image: ghcr.io/rain-kl/openflare:latest - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - ports: - - "3000:3000" - environment: - SESSION_SECRET: replace-with-random-string - SQLITE_PATH: /data/openflare.db - DSN: postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable - GIN_MODE: release - LOG_LEVEL: info - volumes: - - ./openflare-data:/data -``` - -Start the services: - -```bash -docker compose up -d -``` - -Compose configuration options: -* **`depends_on` and `healthcheck`**: Uses PostgreSQL's health check (`pg_isready`) to ensure that the database is fully initialized and ready before launching the OpenFlare Server, preventing panics from failed database connection attempts on first launch. -* **Separated Data Volume Mounts**: PostgreSQL data is mounted under `./postgres-data`, and OpenFlare data and backups are mounted under `./openflare-data`, making backups and maintenance simple. - -## CLI Arguments - -```bash -go run . --port 3000 --log-dir ./logs -``` - -| Argument | Description | Default Value | -| --- | --- | --- | -| `--port` | The port the Server listens to | `3000` | -| `--log-dir` | The directory to write logs to | Empty, outputs to stdout | -| `--version` | Outputs version and exits | `false` | -| `--help` | Outputs help and exits | `false` | - -## First Login - -Default credentials: - -| Username | Password | -| --- | --- | -| `root` | `123456` | - -Please change the default password immediately after your first login. diff --git a/docs/en/deployment/upgrade.md b/docs/en/deployment/upgrade.md deleted file mode 100644 index 67abd0ed..00000000 --- a/docs/en/deployment/upgrade.md +++ /dev/null @@ -1,52 +0,0 @@ -# Upgrade & Maintenance - -You will learn: How to upgrade the Server and the Agent, how to clean up observability data, and which validation commands to execute before and after maintenance. - -Before upgrading, verify the currently active version, the most recent Agent application results, and your database backup strategy. In production environments, never trigger upgrades while a configuration is being published, during large-scale Agent reconnections, or while database migrations are in progress. - -## Server Upgrade - -Root users can check and trigger stable Server upgrades in the top header of the management console. You can also trigger upgrades by uploading the compiled Server binary in the console. - -To deploy preview releases, manually check the GitHub Releases page. We highly recommend prioritizing stable releases in production environments. - -Verify after upgrading: - -```bash -docker compose ps -docker compose logs -n 100 openflare -``` - -If deployed from source, restart the Server and verify that no database migration or startup errors appear in the logs. - -## Agent Upgrade - -Node Agents automatically update following stable releases by default. Upgrading to preview releases requires a manual trigger. - -You can re-execute the installation script to redeploy or force-update the Agent: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --agent-token YOUR_AGENT_TOKEN -``` - -Note: Re-executing the current installation script wipes the entire installation directory, including the existing `agent.json`, local states, cached databases, and downloaded binaries. Ensure you have the node Token handy before executing the script. - -Verify after upgrading: - -```bash -systemctl status openflare-agent -journalctl -u openflare-agent -n 100 --no-pager -``` - -## Data Maintenance - -The management console's Settings page maintains options for automatic cleanup of observability data: - -| Parameter | Description | -| --- | --- | -| `DatabaseAutoCleanupEnabled` | Toggles daily automatic cleanup | -| `DatabaseAutoCleanupRetentionDays` | Data retention duration in days, minimum 1 day | - -When enabled, the Server cleans up access logs, metrics snapshots, and request reports at 3:00 AM daily. diff --git a/docs/en/design/agent-design.md b/docs/en/design/agent-design.md deleted file mode 100644 index c804a0f2..00000000 --- a/docs/en/design/agent-design.md +++ /dev/null @@ -1,181 +0,0 @@ -# Agent Design Document - -You will learn: Agent design principles, core functional modules, interaction links with the Server, and how configuration applications are secured and made reliable through immutable version models and the three-stage disaster recovery rollback mechanism. - ---- - -## Requirements Analysis - -In distributed reverse proxy and edge security gateway scenarios, the Agent plays a central role in connecting the control plane (Server) and the data plane (OpenResty). Since the Agent runs on the user's actual node server, its design must adhere to the following core security and high-availability requirements: - -1. **Active Pull (Pull Model) instead of Push**: The Server does not hold the SSH keys of the nodes, nor does it actively initiate inbound connections to the nodes. All control directives and configuration updates are actively pulled by the Agent via heartbeats or long-lived connections (WebSockets). This eliminates inbound firewall security risks on the node side and prevents control channels from being hijacked. -2. **Minimal Intrusiveness**: The Agent runs as an independent Go binary process. It only interacts with the local OpenResty process through file-based configuration rewriting and signal notifications, without interfering with other system services on the node. -3. **Robust Disaster Recovery & Self-Healing**: Since network jitter, disk exhaustion, or erroneous configurations can easily lead to configuration sync failures, the Agent must possess zero-dependency local rollback and self-healing capabilities, strictly preventing a single configuration error from causing a complete node outage. -4. **Pure Data and State Landing**: The Agent is only responsible for executing file generation and control intentions rendered by the Server. It does not carry complex control plane duties like business logic validation or multi-tenant authorization, ensuring the node side remains highly efficient and lightweight. - ---- - -## Core Capabilities - -The Agent is composed of the following core sub-modules, cooperating to manage its complete lifecycle: - -| Module Name | Directory | Responsibilities | -| :--- | :--- | :--- | -| **Config Sync** | `sync/` | Pulls full configuration packages, writes files, triggers reloads, and records and reports sync statuses. | -| **Heartbeat** | `heartbeat/` | Periodically reports node health and resource metrics to the Server and retrieves the latest active version summary. | -| **WebSocket** | `wsclient/` | Maintains a persistent connection with the Server, providing sub-second real-time configuration pushes and commands. | -| **OpenResty Control** | `nginx/` | Executes Nginx config validation (`openresty -t`), rewrites, graceful reloads (`reload`), and process auto-start. | -| **Local State Store** | `state/` | Persistently records local applied versions, error logs, and buffers unsent observability metrics. | -| **Self-Updater** | `updater/` | Listens to Server self-update commands, securely pulls new binary versions, and completes in-place upgrades. | -| **Observability** | `observability/` | Collects host CPU/memory/disk and Nginx performance metrics, processes access logs, and uploads them. | -| **GeoIP Maintenance** | `geoipdata/` `geoipupdate/` | Maintains and updates the local GeoIP database periodically to support WAF country-level filtering. | - ---- - -## Interaction Flows with Server - -The Agent communicates with the control plane through **Token-based Auto-Registration** and a **Dual-channel Heartbeat/WebSocket** system during its lifecycle. - -### 1. Auto-Registration Flow - -If the Agent starts with an empty `access_token` in its local `agent.json`, but has a `discovery_token` configured, it triggers the auto-registration flow: -1. The Agent sends a registration request to `/api/agent/register`, carrying a local hardware fingerprint, IP, and hostname. -2. After validating the `discovery_token`, the Server generates a unique `NodeID` and a dedicated `AccessToken` (i.e., `agent_token`) in the database and returns them. -3. The Agent writes the dedicated Token to its local configuration file, clears the one-time `discovery_token`, and uses the `AccessToken` for all subsequent authenticated communications. - -### 2. Dual-Channel Heartbeat & Sync Mechanism - -* **HTTP Polling (Fallback and Detection)**: The Agent sends POST heartbeat packets at configured `heartbeat_interval` intervals by default. It reports health metrics while retrieving the currently active configuration version summary (Version & Checksum). -* **WebSocket Channel (Real-time Communication)**: Upon a successful HTTP heartbeat, the Agent automatically attempts to upgrade the connection to WebSocket (`/api/agent/ws`). - * Once the WS connection is established, heartbeats and metrics reporting shift entirely to the WS pipeline, reducing network overhead. - * When the Server publishes or activates a new version, it broadcasts a notification to the Agent via WS. The Agent triggers the synchronization flow **immediately** upon receiving the change event, achieving sub-second configuration deployment. - * If the WS connection drops due to network issues, the Agent automatically falls back to HTTP polling and uses an exponential backoff algorithm to attempt rebuilding the WS channel. - -### 3. Interaction Sequence Diagram - -```mermaid -sequenceDiagram - autonumber - participant Agent as OpenFlare Agent - participant OR as Local OpenResty - participant Server as OpenFlare Server - - Note over Agent: First Startup (No AccessToken) - Agent->>Server: 1. Auto-registration request (carrying discovery_token) - Server-->>Agent: 2. Issue NodeID & dedicated AccessToken (agent_token) - Note over Agent: Store Token in local configuration file - - rect rgb(240, 248, 255) - Note over Agent, Server: HTTP Fallback & WebSocket Upgrade - Agent->>Server: 3. Send HTTP Heartbeat (report system metrics & health) - Server-->>Agent: 4. Return ActiveConfig summary & AgentSettings - Agent->>Server: 5. Initiate WebSocket upgrade request (/api/agent/ws) - Server-->>Agent: 6. Upgrade successful (persistent bi-directional channel) - end - - rect rgb(245, 245, 245) - Note over Agent, Server: Real-time Configuration Publication - Note over Server: Administrator clicks publish config in UI - Server->>Agent: 7. Broadcast active config summary via WS (WSMessageTypeActiveConfig) - Agent->>Server: 8. Request full configuration details (carrying target Version/Checksum) - Server-->>Agent: 9. Return complete configuration snapshot (Nginx configs, certs, WAF rules, etc.) - Note over Agent: Backup old files, write new config to local temp path - Agent->>OR: 10. Execute config syntax validation (openresty -t) - OR-->>Agent: 11. Return validation result (OK) - Agent->>OR: 12. Send graceful reload signal (openresty -s reload) - Agent->>Server: 13. Report application success status (Apply Log & ActiveVersion) - end -``` - ---- - -## Control of OpenResty - -The Agent implements end-to-end closed-loop control of the data plane OpenResty, including configuration rendering, syntax validation, graceful reloading, and exception state capturing: - -### 1. Configuration Layout on Disk - -Upon successful sync, the Agent writes configuration files to `/etc/nginx/openflare-lua/` (or the configured `LuaDir`) according to a strict physical structure: -* `nginx.conf`: Main configuration file (replaces absolute path placeholders, configures performance parameters, shared dictionaries, and global server blocks). -* `routes.conf`: Route configuration file (generated by the Agent, containing all website server blocks, certificate paths, cache settings, and rate limit directives). -* `certs/`: Certificate storage directory (files named as `{cert_id}.crt` and `{cert_id}.key`). -* `waf/` and `pow/`: Dedicated Lua runtime scripts required for WAF and CC mitigation. -* `waf_config.json` and `waf_ip_groups.json`: Structured rules and IP databases required by the WAF filtering engine. - -### 2. Refined Reload Operations - -1. **Backup Current Config**: Before writing new files, the Agent copies the existing configuration files to a `.backup` directory, keeping a complete rollback snapshot. -2. **Write and Replace Placeholders**: Writes the pulled templates, automatically replacing absolute path placeholders (e.g., `__OPENFLARE_LUA_DIR__`) with actual local execution paths. -3. **Syntax Validation**: Calls `openresty -t -c ` to run a strict syntax test. -4. **Graceful Reload**: If validation passes, the Agent moves the files to the official paths and executes `openresty -s reload`. If OpenResty is not running, it launches the process. -5. **Exception Capture**: If validation or reload fails, the Agent intercepts the standard error output (stderr) and extracts the first 2000 characters of the detailed error log. - ---- - -## Publishing & Config Application Model - -OpenFlare discards the fragile mechanism of dynamically patching node configurations, instead using an **immutable configuration version publishing model**. - -```text -Edit rules -> Preview / View diff -> Publish -> Generate full configuration version -> Activate version -> Agent pulls -> Local application -> Report result -``` - -### 1. Core Design Principles - -* **Complete Publication**: Every publication compiles all enabled proxy routes, certificates, and global/custom WAF rules at once, generating a complete version package with a unique `checksum`. -* **Version Format**: Uses the `YYYYMMDD-NNN` incremental format, ensuring version histories are intuitive and strictly monotonic. -* **Global Single Active Version**: The system supports only one globally `active` configuration version at any given time. Rollbacks do not require reverse patching; they simply transition an older healthy version to the `active` state, and the Agent pulls and applies it. - -### 2. Three-Stage Disaster Recovery & Rollback Mechanism - -If the Agent fails to apply a configuration (or reload fails), it automatically triggers the following three-stage self-healing pipeline: - -```mermaid -graph TD - A[Config Application Failed] --> B[Stage 1: Attempt Local Backup Recovery] - B -- Backup Exists --> C[Write Local Backup Files] - C --> D[Run openresty -t Validation] - D -- Validation OK --> E[Reload Old Configuration] - D -- Validation Failed --> F[Proceed to Stage 2] - B -- No Backup --> F[Stage 2: Write Built-in Safe Fallback Config] - F --> G[Write fallback nginx.conf: Listen on Port 80 Only] - G --> H[Enable stub_status health checks] - G --> I[Return 503 for all other routes & block errors] - G --> J[Attempt to launch OpenResty to maintain basic survival] - J --> K[Proceed to Stage 3] - E --> L[Report Apply Warning] - K --> M[Block Local Repeated Application of Failed Version] - M --> N[Report Apply Error with detailed logs] -``` - -1. **Stage 1: Local Backup Rollback** - * The Agent attempts to restore the main configuration, routes, and certificates from the `.backup` directory. - * It runs `openresty -t` validation on the restored backup. If successful, it reloads and reports a `Warning` to the Server (Warning: failed to apply new version, automatically rolled back to the previous healthy version). -2. **Stage 2: Built-in Safe Fallback Runtime** - * If no local backup exists (e.g., first deployment failed) or if the rollback validation fails, the Agent activates the ultimate self-healing mechanism: writing a **built-in safe fallback configuration**. - * **Fallback Configuration Specification**: - * Listens only on port `80`, containing no real user reverse proxy routes. - * The `/openflare/stub_status` endpoint returns a healthy response, while all other requests uniformly return a `503 Service Unavailable` status code with the fixed response body `OpenFlare: No Valid Configuration`. - * It attempts to launch OpenResty with this minimal configuration. This keeps the Nginx process alive, preserving underlying health probes and metric endpoints, preventing containers/pods from being repeatedly killed and restarted by orchestration systems, while keeping sensitive routes secure. -3. **Stage 3: Local Configuration Blocking** - * The Agent records the failing configuration's `version + checksum` in its local state store blacklist. - * Until the control plane activates a new configuration (resulting in a changed `checksum`), the Agent's heartbeat blocks repeated synchronization pulls of this erroneous version, preventing nodes from entering an infinite loop of "heartbeat -> pull failing config -> crash rollback". - -### 3. WAF IP Group Asynchronous Runtime Synchronization - -To prevent highly volatile IP blacklists from triggering frequent full config publications and Nginx reloads (which still incur minor CPU and connection overhead), WAF IP groups are synchronized via an **asynchronous differential sync design**: - -* **Static Publication Snapshot**: The `waf_config.json` generated upon publication only contains the group ID reference mapping (i.e., `ip_whitelist_group_ids` / `ip_blacklist_group_ids`) and does not contain the actual list of IP addresses. -* **Heartbeat Differential Check**: The Agent uploads its locally cached IP groups MD5 checksum map in its heartbeat. -* **Differential Delivery**: The Server compares checksums and only delivers missing or modified IP groups, which are written directly to `waf_ip_groups.json` on the node without reload. -* **WebSocket Real-time Push**: When an administrator updates an IP group, or a threat intelligence subscription successfully pulls, or a security rule triggers a temporary block, the Server immediately broadcasts the IP group update package via WebSocket. The Agent receives and applies it instantly **without Nginx reloads**. - ---- - -## Design Constraints - -To protect the security boundary of the data and control plane, Agent development must strictly comply with the following engineering constraints: - -1. **Zero-Privilege Command Execution**: The Server is strictly prohibited from sending any arbitrary shell commands or scripts to the Agent (such as exec/eval). All system control operations (such as start, stop, reload, update) must be hardcoded inside the Agent binary. -2. **Strict Token Filtering and Prefix Validation**: Agent requests to the Server must be prefixed with `/api/agent/` and must carry the `X-Agent-Token` header for signature or token verification. -3. **Node Autonomy**: The Agent must support complete offline capabilities. During disconnected periods, the local OpenResty must rely on local configuration copies to keep reverse proxy services running normally. diff --git a/docs/en/design/architecture.md b/docs/en/design/architecture.md deleted file mode 100644 index 7dc48291..00000000 --- a/docs/en/design/architecture.md +++ /dev/null @@ -1,223 +0,0 @@ -# System Architecture - -You will learn: The overall architecture of OpenFlare, the boundaries of responsibilities for Server, Agent, OpenResty, and Admin Frontend, and the request flow of a configuration publication from the admin dashboard to activation on a node. - -OpenFlare consists of the Server, the Agent, the node-local OpenResty, and the Admin Frontend. The Server is the control plane, the Agent is the only controlled entry point on the node side, and OpenResty serves as the actual data plane. In intranet penetration scenarios, the Relay (frps manager) and OpenFlared (frpc manager) extend the data plane traffic path. - -### Standard Reverse Proxy Traffic Path - -```text -Browser - | - | Management UI / API - v -OpenFlare Server (Gin + GORM + SQLite/PostgreSQL) - | - | Agent API / heartbeat / config pull - v -OpenFlare Agent - | - | write config / openresty -t / reload / rollback - v -OpenResty binary - | - | reverse proxy - v -Origin -``` - -### Intranet Penetration Traffic Path - -```text -Browser - | - | HTTPS request - v -OpenResty (Agent, TLS/WAF) <-- TunnelRelay Node - | - | proxy_pass http://localhost:vhost_port (Host header preserved) - v -OpenFlareRelay (frps) <-- TunnelRelay Node, co-located with Agent - | - | frp tunnel protocol (HTTP Vhost routing by Host header) - v -OpenFlared (frpc) <-- Intranet Server - | - | HTTP/HTTPS forward - v -Internal Service (192.168.x.x) -``` - -## Component Responsibilities - -| Component | Responsibility | -| --- | --- | -| Server | Admin UI, Admin API, Agent/Relay/Client API, configuration rendering, version publishing, data storage, and aggregated queries. | -| Agent | Registration, heartbeats, synchronization, file writing, validation, reload, rollback on failure, self-updating, and light metrics collection. | -| OpenResty | Receives real traffic, executing WAF, PoW, authentication, and reverse proxying according to the configuration rendered by OpenFlare. | -| OpenFlareRelay | Manages the lifecycle of the frps process, providing tunnel relay services and receiving frps configurations via heartbeat. | -| OpenFlared | Manages frpc processes (can be multiple), connecting to the Relay and forwarding traffic to intranet services. | -| Frontend | Manages pages for website configs, WAF, origins, certificates, nodes, tunnels, versions, users, settings, and observability. | - -## Server - -`openflare-server` is the single-control-plane monolith: - -* Gin provides the HTTP services. -* GORM accesses SQLite or PostgreSQL. -* The existing login system provides Admin Session management. -* Authentication sources support GitHub OAuth and standard OIDC logins with external account binding. -* The Go Server hosts the `openflare-server/web` static build assets. - -The Server does not directly SSH to nodes, nor does it modify node files online. It only stores control plane state, generates complete configuration versions, and lets nodes actively pull them via the Agent API. - -## Agent - -`openflare-agent` is a Go monolithic application: - -* Runs as a single binary on the node side. -* Reads or generates local node information on startup. -* Performs periodic heartbeat check-ins to report status and retrieve active version summaries. -* Upon discovering a new version, it pulls the configuration, backs up old files, writes new files, validates them, and reloads. -* Automatically rolls back to restore operations if the application fails. -* Maintains the local WAF GeoIP mmdb, writing the built-in library on startup and updating it periodically based on configuration. - -The Agent executes validation, reload, startup, and restart uniformly via the path specified in `openresty_path`; if unconfigured, it defaults to calling `openresty`. During Docker deployments, the Agent image packages OpenResty and follows the same execution control logic. - -The node IP is maintained by default through Agent registration and heartbeat reporting; if the administrator locks the node IP, the Server only updates running status, versions, and observability fields, and no longer accepts reports from the Agent to override the locked IP. - -## Frontend - -`openflare-server/web` is the official Next.js-based frontend: - -* Next.js 15 App Router. -* React 19. -* TypeScript. -* Tailwind CSS. -* TanStack Query for server-side state. - -The frontend uses static export mode (`output: 'export'`), which is then hosted by the Go Server using `embed.FS`. All API requests must go through `lib/api/` and process the `success/message/data` response structure. - -The Server integrates the following security features: -* CORS middleware: Cross-Origin Resource Sharing protection. -* Rate limiting: Global and key API endpoint throttling. -* Session management: Cookie/Redis-based session storage. - -## Data & Request Flow - -### Management Request Flow - -```text -Browser -> Frontend -> /api/* -> controller -> service -> model -> database -``` - -Admin mutation APIs use `POST`, while read-only APIs use `GET`. Both success and failure responses return a clear `message`. - -### Agent Sync Flow - -```text -Agent HTTP heartbeat -> Server returns active version summary -Agent detects new version -> Pulls complete configuration details -Agent writes main configuration / route configurations / certificates / Lua resources / WAF runtimes -Agent runs OpenResty validation (openresty -t) and reload -Agent reports application result -``` - -### Relay Sync Flow - -The Relay (OpenFlareRelay process) runs on the TunnelRelay node and shares the same `agent_token` with the Agent: - -```text -Relay HTTP heartbeat -> Server returns frps base configuration (bindPort, vhostHTTPPort, auth_token) -Relay generates frps.toml and starts or updates the frps process -Relay periodically reports frps health status and connection statistics -Relay attempts WebSocket upgrade for real-time configuration pushes -``` - -frps configurations are relatively static (ports, auth token), dispatched via heartbeats, and **not included in the versioned publishing flow**. The Relay must monitor the frps process and auto-recover it on failures. Authentication: `X-Agent-Token` + API path prefix `/api/relay/*`, distinguished by Server via `node_type = tunnel_relay`. - -### OpenFlared Sync Flow - -OpenFlared (client) runs inside the intranet server, using independent `tunnel_token` authentication: - -```text -Client HTTP heartbeat -> Server returns tunnel configuration version summary (version, checksum) -Client detects new version -> Pulls complete tunnel route configuration (relay list + frpc proxy definitions) -Client generates independent frpc.toml configuration files for each Relay -Client starts a new frpc process for new Relays, or hot-reloads (frpc reload) existing ones -Client reports application results (success/failure details) -``` - -OpenFlared communicates with the Server via `/api/flared/*` using the `X-Tunnel-Token` header. Tunnel route configurations are versioned along with the publishing flow, ensuring all configuration changes are consistently published to both Agents and Clients via a single version number. - -**WebSocket Upgrade Flow** (Optional, controlled via `AgentWebsocketUpgradeEnabled`): - -When WebSocket upgrade is enabled: -1. The Agent retrieves run configurations and settings via HTTP heartbeat. -2. The Agent attempts to upgrade the connection to `GET /api/agent/ws` (WebSocket). -3. Once the WS connection is established, periodic state reporting and real-time commands are carried over the WebSocket pipeline, minimizing latency. -4. When the Server publishes or activates a version, it immediately broadcasts the active version summary to connected Agents, triggering the sync flow instantly. -5. If the WebSocket disconnects or fails to establish, the Agent automatically falls back to HTTP heartbeats, ensuring high availability. - -Through the `OpenRestyWebsocketEnabled` option, WebSocket reverse proxy support can be enabled or disabled at the OpenResty layer. - -### Reverse Proxy Flow - -```text -Client -> OpenResty server block -> WAF Lua -> named upstream -> Origin -``` - -Website configurations are the boundaries of reverse proxy aggregation. A single website configuration can bind multiple domains, sharing site-level rate limiting, reverse proxy, and cache settings. - -WAF executes in the OpenResty `access_by_lua_file` phase. Rules originate from the `waf_config.json` carried in the currently active version; global rule groups take effect by default, and websites can overlay custom rule groups. `waf_config.json` only stores rule group references and IP group IDs; IP group members are synchronized independently by the Agent into `waf_ip_groups.json`, and the OpenResty Lua engine merges and evaluates them by reference ID. - -WAF IP groups are managed by the Server. Manual IP groups store IP/CIDR lists directly; auto IP groups are evaluated by Server cron jobs reading request logs and applying Expr boolean rules; subscription IP groups are fetched by Server cron jobs from remote text or JSON sources. The Agent reports local IP group checksums in heartbeats, and the Server only returns mismatched IP groups. When an IP group is updated on the Server, a broadcast is sent via WebSocket to push changes, and the OpenResty Lua reads the local JSON file directly without querying the DB, request logs, or remote subscription sources. - -## Core Objects - -Current valid entities include: - -* `proxy_routes` -* `origins` -* `config_versions` -* `nodes` -* `tunnels` -* `auth_sources` -* `external_accounts` -* `node_system_profiles` -* `apply_logs` -* `tls_certificates` -* `managed_domains` -* `node_request_reports` -* `node_access_logs` -* `node_metric_snapshots` -* `traffic_analytics_rollups` -* `node_health_events` -* `waf_rule_groups` -* `waf_ip_groups` -* `waf_rule_group_bindings` -* `acme_accounts` -* `dns_accounts` -* `geoip_update_configs` - -## Key Design Decisions - -| Decision | Rationale | -| --- | --- | -| Full Config Versioning instead of Patches | Provides stable, verifiable boundaries for previewing, activating, history, and rollbacks. | -| Pull Model (Agent-driven) | Server does not need SSH keys or inbound command ports, preventing control channel hijacking. Supports HTTP and WebSocket. | -| Global Single Active Version | Reduces MVP complexity, ensuring all nodes are uniform by default. Supports previews, version history, and one-click rollback. | -| Website Multi-Domain Aggregation | Enables sharing site-level policies across domains while supporting per-domain certificate binding. | -| Server-side Observability Aggregation | Prevents UI-side temporary statistical calculations from producing inconsistent data metrics. | -| Intranet Penetration based on frp | Reuses a mature tunnel protocol rather than custom implementations to minimize stability risks. frps Vhost routing aligns naturally with HTTP. | -| Independent Binary for Relay/Client | Separation of concerns: Relay manages frps, Client manages frpc, allowing independent updates and deployments. | -| Tunnel decoupled from Node system | Tunnel clients run internally, using completely different registration and authentication flows compared to edge nodes. | - -## Recommended Reading for Contributors - -Before modifying architectural code, please read: - -1. [Product Boundaries](./index.md) -2. [Agent & Publish Model](./agent-design.md) -3. [Development Constraints](../../guideline/Constraints.md) -4. [Repository Structure](./repository.md) diff --git a/docs/en/design/development.md b/docs/en/design/development.md deleted file mode 100644 index 0b22c546..00000000 --- a/docs/en/design/development.md +++ /dev/null @@ -1,182 +0,0 @@ -# Local Development - -You will learn: How to build OpenFlare's local development environment, start the Server, the Agent, and the Admin Frontend, run test and build commands, and understand the boundaries to respect before contributing code. - -This page is aimed at contributors. Product boundaries, data model constraints, API conventions, and frontend layering specifications are governed by [Development Constraints](../../guideline/Constraints.md); this page only provides actionable workflows for local development. - -## Repository Structure - -For details on the physical directory structure and responsibilities of each module (Server, Agent, Frontend, etc.), see [Repository Structure](./repository.md). - -## Environment Requirements - -| Item | Requirement | -| --- | --- | -| Go | `1.25+` | -| Node.js | `18+` | -| pnpm | Recommended enabling via `corepack enable` | -| Docker | Required for Server containers, local integration testing, and Agent Docker images | -| OpenResty | Required to execute `openresty` locally when running the Agent | -| PostgreSQL | Optional; if not configured, the Server defaults to SQLite | - -## Initializing Frontend Dependencies - -```bash -cd openflare-server/web -corepack enable -pnpm install -``` - -Build the static assets hosted by the Go Server: - -```bash -pnpm build -``` - -## Starting the Server - -SQLite Mode: - -```bash -cd openflare-server -export SESSION_SECRET='dev-session-secret' -export SQLITE_PATH='./openflare-dev.db' -export LOG_LEVEL='debug' -go run . -``` - -PostgreSQL Mode: - -```bash -cd openflare-server -export SESSION_SECRET='dev-session-secret' -export DSN='postgres://openflare:secret@127.0.0.1:5432/openflare?sslmode=disable' -export LOG_LEVEL='debug' -go run . -``` - -Default access URL: - -```text -http://localhost:3000 -``` - -The default credentials are `root` / `123456`. - -## Starting the Frontend Dev Server - -The frontend dev server listens to port `3001` by default and proxies requests to the backend via `NEXT_DEV_BACKEND_URL`: - -```bash -cd openflare-server/web -export NEXT_DEV_BACKEND_URL='http://127.0.0.1:3000' -pnpm dev -``` - -Access: - -```text -http://localhost:3001 -``` - -## Starting the Agent - -Create a local `agent.json`: - -```json -{ - "server_url": "http://127.0.0.1:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "./data", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -Run: - -```bash -cd openflare-agent -export LOG_LEVEL='debug' -go run ./cmd/agent -config ./agent.json -``` - -If `openresty_path` is not configured, the Agent calls `openresty` by default. For debugging, you can explicitly configure `openresty_path`, `main_config_path`, `route_config_path`, `access_log_path`, `cert_dir`, `lua_dir`, and `runtime_config_dir`. - -## Running Tests - -Server: - -```bash -cd openflare-server -GOCACHE=/tmp/openflare-go-cache go test ./... -``` - -Agent: - -```bash -cd openflare-agent -GOCACHE=/tmp/openflare-go-cache go test ./... -``` - -Frontend: - -```bash -cd openflare-server/web -pnpm lint -pnpm typecheck -pnpm test -pnpm test:e2e -``` - -Docs: - -```bash -cd docs -pnpm build -``` - -## Building - -Admin static assets: - -```bash -cd openflare-server/web -pnpm build -``` - -Server binary: - -```bash -cd openflare-server -go build -o openflare-server . -``` - -Agent binary: - -```bash -cd openflare-agent -go build -o openflare-agent ./cmd/agent -``` - -## Debugging Entrypoints - -| Context | Command or Path | -| --- | --- | -| Server Logs | `LOG_LEVEL=debug go run .` | -| Agent Logs | `LOG_LEVEL=debug go run ./cmd/agent -config ./agent.json` | -| Swagger Docs | `http://localhost:3000/swagger/index.html` | -| Frontend API Proxy | `NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev` | -| OpenResty Validation | `openresty -t -c ./data/etc/nginx/nginx.conf` | - -## Code Style & Change Admission - -Before contributing, verify: - -1. The requirement matches [Product Boundaries](./index.md). -2. The implementation conforms to [Development Constraints](../guideline/development-constraints.md). -3. The change does not disrupt publishing, sync, rollback, or upgrading lifecycles. -4. Update corresponding documentation if configurations, deployments, APIs, or boundaries change. -5. High-risk edits must be accompanied by unit tests or equivalent integration testing. - -Database schema alterations must elevate the database version number and supply explicit migration and validation methods from the previous version. diff --git a/docs/en/design/index.md b/docs/en/design/index.md deleted file mode 100644 index 35e842b0..00000000 --- a/docs/en/design/index.md +++ /dev/null @@ -1,204 +0,0 @@ -# Product Boundaries - -You will learn: What OpenFlare is, what problems it solves, who the target audience is, what current stable features are available, and which design boundaries cannot be bypassed during implementation. - -OpenFlare is a self-hosted OpenResty control plane designed for single-team or single-organization internal operations. It solves the problems of decentralized management of reverse proxy configurations, node synchronization, certificate hosting, configuration publication and rollback, and basic observability. - -## Project Positioning - -OpenFlare is suitable for teams that need to centrally manage multiple OpenResty proxy nodes: - -* Wanting to maintain reverse proxy website configurations using a management dashboard. -* Wanting every configuration change to have a complete version history, preview, activation, and rollback support. -* Wanting nodes to actively synchronize configurations, rather than the control plane SSHing into nodes to execute commands. -* Wanting to manage TLS certificates, domain assets, node statuses, and basic access analytics in a single system. - -OpenFlare is currently not positioned as a general-purpose logging platform, service mesh, Kubernetes Ingress Controller, or multi-tenant cloud platform. - -## Current Capabilities - -| Capability | Description | -| --- | --- | -| Reverse Proxy Rules | Uses website configuration as the aggregation boundary, supporting multiple domains and origin settings. | -| Website-level Config | One rule corresponds to one website, which can bind one or more domains and share site-level configurations. | -| Origin Management | Maintains a lightweight origin directory and allows websites to save renderable origin snapshots. | -| Config Versioning | Supports previews, publishing, activation, immutable history, and rollbacks. | -| Agent Sync | Supports registration, heartbeats, synchronization, application result reporting, and self-updating. | -| OpenResty Hosting | Manages main config templates, performance parameters, cache parameters, and Lua resources. | -| HTTPS/TLS | Hosts certificate and domain assets, binding certificates on a per-domain basis. | -| WAF | Maintains IP/CIDR block blacklists/whitelists, IP groups, and country-level geographic access controls at both global and site-specific levels. | -| Basic Observability | Aggregates node requests, resource snapshots, health events, and access analytics. | -| Node Management | Manages node status, token systems, and deployment/update lifecycles. | -| Admin UI | Next.js-based official management dashboard. | -| Auth Source Login | Supports configuring GitHub OAuth and standard OIDC login portals, allowing third-party accounts to bind to existing local users. | -| Intranet Penetration | Securely exposes intranet HTTP services to the public internet using TunnelRelay nodes and the OpenFlared client, reusing the Agent's HTTPS/WAF capabilities. | - -Default Working Model: - -* All nodes consume the same globally activated configuration version. -* The Server stores configurations and state, and does not directly SSH to manage nodes. -* The Agent is the only controlled entry point on the node side. -* TunnelRelay nodes run both the Agent (OpenResty) and the Relay (frps manager) to provide intranet penetration relays. -* The OpenFlared client runs inside the intranet, managing the frpc process to connect to the Relay and forward traffic to intranet services. - -## Typical Use Cases - -| Scenario | Description | -| --- | --- | -| Unified Entrance | Exposes multiple internal HTTP services via a unified domain and TLS certificate. | -| Multi-Node Sync | Multiple OpenResty nodes consume the same active configuration version. | -| Change Review | View previews or diffs before publishing, keeping an immutable history post-publish. | -| Rapid Rollback | Re-activate an older version, letting the Agent pull and apply it. | -| Certificate Hosting | Bind TLS certificates to different domains under the same website. | -| Observability | Check node health status, aggregated requests, traffic analytics, and health events. | -| Intranet Penetration | Exposes intranet HTTP services that are not directly reachable from the public internet using Tunnels, benefiting from HTTPS, WAF, and all other protections. | - -## Website Configuration Constraints - -`proxy_routes` is the aggregate object for "website configurations". One record corresponds to one website, which can bind one or more domains and share a set of site-level configurations. - -Constraints: - -* `proxy_routes.site_name` is the unique business identifier of the website. -* `proxy_routes.domains` must contain at least one domain, and `domains[0]` is treated as the primary domain. -* Any domain can globally belong to only one `proxy_routes`. -* Site-level rate limits, reverse proxies, and caching configurations are shared by the site, with no per-domain differences allowed within the same website. -* HTTPS allows binding certificates on a per-domain basis within the same site. - -## Origin & Upstream Constraints - -`origins` serve the reuse of the origin directory, storing only the origin address, display name, and remarks, without carrying protocols, ports, paths, weights, or health check policies. `proxy_routes` can optionally associate with an `origins` record, but the rule internally still saves a complete upstream snapshot for rendering. - -Upstream Constraints: - -* `proxy_routes` must contain at least one upstream address (for direct type `direct`), or be associated with a Tunnel (for intranet penetration type `tunnel`). -* Multi-upstream load balancing is uniformly rendered into a named `upstream` with keepalive enabled. -* A single upstream is allowed to carry a base path or query, which is appended in `proxy_pass`. Multi-upstream is strictly limited to pure `scheme://host[:port]` structures, and all upstreams in the same rule must use the same protocol. -* `proxy_routes.origin_host` is an optional field used to override the `Host` header during back-to-source requests. -* All direct upstream addresses must be valid `http://` or `https://` URLs. -* Intranet penetration upstreams must associate with a valid `tunnel_id` and specify the intranet target address and protocol. - -## Intranet Penetration Constraints - -OpenFlare implements intranet penetration through TunnelRelay nodes and the OpenFlared client, built on top of frp (Fast Reverse Proxy). - -### Node & Component Model - -**Node Types**: - -* `nodes.node_type` distinguishes the node type: `edge_node` (edge node, default) and `tunnel_relay` (tunnel relay). -* TunnelRelay nodes run both the Agent (OpenResty) and the Relay (frps manager) concurrently, sharing the same `agent_token`. - - The Agent is responsible for HTTPS termination, WAF protection, caching, and rate limiting. - - The Relay manages the frps process, providing tunnel relay services for intranet clients. -* TunnelRelay nodes introduce new fields: `node_type`, `relay_bind_port` (frpc connection port, default 7000), `relay_vhost_http_port` (HTTP Vhost port, default 8080), `relay_auth_token` (automatically generated), `relay_status`, etc. - -**Tunnel Client**: - -* The `tunnels` table independently stores intranet penetration client registration info and is decoupled from the `nodes` system. -* Each Tunnel has a unique `tunnel_id` (format `tun-<32hex>`) and `tunnel_token` (client authentication credential). -* The OpenFlared client runs inside the intranet, is not exposed to the public internet, uses `tunnel_token` for authentication, and communicates with the Server via `/api/flared/*` endpoints. -* An OpenFlared client can connect to multiple Relays simultaneously for high availability. - -### Upstream Type Expansion - -The upstream configuration of `proxy_routes` is divided into two types, distinguished by the `upstream_type` field: - -* **Direct Upstream (`direct`, default)**: Forwards traffic directly to the origin address, behaving exactly like the existing mechanism. -* **Intranet Penetration Upstream (`tunnel`)**: Forwards traffic to the intranet service via a TunnelRelay node. - - Must specify `tunnel_id` (associated with the `tunnels` table). - - Must specify `tunnel_target_addr` (intranet target address, e.g., `192.168.1.100:8080`) and `tunnel_target_protocol` (`http` or `https`). - - During publication, the Server automatically replaces the upstream address with `http://127.0.0.1:{relay_vhost_http_port}`. - -### Traffic Paths & Protocols - -**Complete Data Plane Traffic Path**: - -``` -Browser → OpenResty (Agent, TLS/WAF) [TunnelRelay Node] - ↓ - frps (Relay, HTTP Vhost Routing) [TunnelRelay Node, 127.0.0.1:{vhost_port}] - ↓ - frp Tunnel Protocol (Host Header Routing) - ↓ - frpc (Client, Multi-process) [Intranet Server] - ↓ - Intranet Service (192.168.x.x:port) -``` - -**Key Features**: - -* frps uses the HTTP Vhost single-port reuse mechanism; all HTTP tunnels share one `vhost_port`, automatically routed to the corresponding frpc based on the Host header. -* The Agent preserves the original `Host` header, which frps uses to match the virtual host. -* Each tunnel corresponds to a single `proxy_routes` and can bind multiple domains. -* The OpenFlared client manages an independent frpc process for each connected Relay, transmitting multiple HTTP proxy definitions via a single frp tunnel. - -### Configuration Sync Model - -The publication process generates two types of configuration version data simultaneously, linked by a single `config_version` version number: - -* **Agent-side Config**: OpenResty main configuration + route configurations + WAF rules. If a tunnel upstream is included, it is automatically rendered as a `http://127.0.0.1:{vhost_port}` upstream. -* **Tunnel-side Config**: Relay list + frpc proxy definitions. Versioned alongside the publishing process; changes are hot-reloaded using `frpc reload` first. -* **Relay Config**: Dispatched via heartbeat responses, relatively static, and not included in the versioned publishing flow. - -### Tunnel Design Constraints - -* Only HTTP protocol tunnel traffic is supported (keeping TCP/UDP tunnels extensible); separate TCP/UDP port allocation is not supported for now. -* The DNS for domains using Tunnel upstreams should resolve to the designated TunnelRelay node. -* frp binaries (v0.61+) are packaged and provided by the system deployment script or container images. - -## HTTPS Constraints - -`proxy_routes.domain_cert_ids` is used to record the domain-certificate bindings parallel to `domains`; a value of `0` means the domain does not have HTTPS enabled and stays HTTP-only. - -During rendering: - -* Domains with certificates are grouped by certificate and output as independent `443 ssl` `server` blocks. -* Domains without certificates bound must not be automatically routed to HTTPS. -* All domains in `proxy_routes.domains` must be kept in the same site configuration to avoid being split across version snapshots. - -## WAF Constraints - -WAF centers around rule groups. The system provides a single global rule group (applied to all sites by default), on top of which websites can overlay multiple custom rule groups. - -Core Capabilities: - -* Supports individual IP / CIDR block whitelists and blacklists. -* Supports IP group references (including manual, automatic Expr calculated, and URL subscribed IP groups). -* Supports GeoIP-based country/region level admission filtering. -* Supports custom interception responses for rule groups (custom status codes and interception HTML pages, default is `418`). - -IP Group & Judgment Constraints: - -* **Runtime Decoupling**: The WAF runtime only reads local JSON files and does not access the Server database; configuration versions only store referenced IP group IDs. IP group members are synchronized via MD5 checksum differences and WebSocket push notifications, achieving hot activation without reloading Nginx. -* **Built-in Expr Rules**: - * High-frequency 404 scanning block: `request_count > 100 && status_404_ratio >= 0.8` - * Malicious IP direct probe: `ip_host_count > 50 && ip_host_ratio > 0.5` -* **Decision Priority**: The whitelist has absolute priority. If it does not match the whitelist, the blacklist funnel is triggered (global rule group first, custom groups matched in ascending ID order). -* GeoIP resolution depends on the local MaxMind database; if GeoIP is anomalous, region rules are automatically ignored and must not disrupt the availability of IP rules and the main reverse proxy chain. - -## Authentication Source Constraints - -`auth_sources` uniformly supports `github` and `oidc` login configurations. `external_accounts` stores bindings between third-party accounts and local users. Logic for first-time third-party login: - -* If already bound, directly authorize login; if there is an active local session, automatically bind. -* If unbound and registration is enabled, automatically create a local account; if registration is closed, require the user to provide an existing local username and password to establish the association. - -## Version & Observability Constraints - -* `config_versions` must save the complete snapshot, rendering result, and `checksum`. -* Globally, only one version can be active at a time. -* Rollback is achieved by re-activating an older version. -* `nodes` only carry control plane state and low-frequency summaries; they do not carry high-frequency observability facts. -* Metrics, trends, and access analytics prioritize server-side aggregation rather than client-side temporary statistics. -* Access detail logs are only retained within a controlled time window, not evolving into a general logging platform. - -## Documentation Maintenance Principles - -* Update this document when the product range or system boundaries change. -* Update [System Architecture](./architecture.md) when the system structure or module responsibilities change. -* Update [Agent & Publish Model](./agent-design.md) when the publishing, synchronization, rollback, or Agent model changes. -* Update [Development Constraints](../../guideline/Constraints.md) when developer constraints, code specifications, or API conventions change. -* Update README and [Deployment Instructions](../../deployment/deployment.md) when deployment methods change. -* Update [Configurations Reference](../reference/configuration.md) when configuration items change. -* Completed phases should no longer be backfilled as "version plans". -* Before starting a new phase, complement the design first, then proceed to implementation. diff --git a/docs/en/design/repository.md b/docs/en/design/repository.md deleted file mode 100644 index 75ae3203..00000000 --- a/docs/en/design/repository.md +++ /dev/null @@ -1,93 +0,0 @@ -# Repository Structure - -You will learn: The responsibilities of Server, Agent, Frontend, scripts, and documentation folders in the OpenFlare repository, and where to place logic when contributing code. - -| Path | Responsibility | -| --- | --- | -| `openflare-server` | Gin + GORM + SQLite/PostgreSQL single monolithic control plane | -| `openflare-server/web` | Next.js 15 App Router Admin Frontend, hosted by Go Server | -| `openflare-agent` | Go monolithic Agent running on the node side | -| `openflare-relay` | Tunnel relay daemon running on public edges, managing frps processes | -| `openflared` | Tunnel client running on intranet servers, managing frpc processes | -| `scripts` | System helper scripts for installation, self-updating, etc. | -| `docs` | VitePress documentation website, design baselines, specifications, and configurations | -| `docs/en` | English version of documentation | - -## Server Layering - -| Folder | Responsibility | -| --- | --- | -| `controller/` | Parameter parsing, service calling, and returning responses | -| `service/` | Business logic, validations, transaction orchestration, and configuration rendering | -| `model/` | Model definitions, database versioning, and migrations | -| `router/` | Route registration | -| `middleware/` | Cross-cutting concerns like authentication, authorization, rate limiting, CORS, and Turnstile | -| `common/` | Configurations, global states, and initialization entrypoints | -| `utils/` | Pure utility functions and general helpers | -| `job/` | Periodic cron tasks (such as SSL certificate auto-renewals) | -| `upload/` | File upload handlers | -| `docs/` | API documentation (Swagger) | -| `data/` | Static data (such as GeoIP databases) | - -## Agent Modules - -| Module | Responsibility | -| --- | --- | -| `config/` | Configuration loading and default values | -| `heartbeat/` | Heartbeat check-in and configuration version evaluation | -| `sync/` | Configuration fetching and application orchestration | -| `nginx/` | OpenResty file writing, validation, reloads, startup, and rollbacks | -| `state/` | Local states and buffers for metric reporting | -| `httpclient/` | Server HTTP API communication | -| `wsclient/` | WebSocket client communication | -| `protocol/` | Agent API protocol types and structures | -| `updater/` | Agent self-updating logic | -| `logging/` | Logging processing | -| `observability/` | Observability (metrics, tracing, etc.) | -| `geoipdata/` | GeoIP database handling | -| `geoipupdate/` | GeoIP database updates | -| `agent/` | Core Agent bootstrap and lifecycle orchestration | - -## Frontend Layering - -| Folder | Responsibility | -| --- | --- | -| `app/` | Next.js App Router routes, layouts, and page assemblies | -| `features/` | Feature modules organized by business domains | -| `components/` | Reusable UI components shared across features | -| `lib/` | API clients, environment configurations, utility functions, and constants | -| `store/` | Lightweight cross-page UI state management | -| `types/` | Shared TypeScript type definitions | -| `styles/` | Global stylesheets | -| `tests/` | Frontend unit and integration tests (Vitest, Playwright) | -| `scripts/` | Build and deployment scripts | -| `public/` | Static assets | - -## Relay Modules - -| Module | Responsibility | -| --- | --- | -| `cmd/` | CLI startup entrypoint and main bootstrap functions | -| `internal/config/` | Local configurations parsing and defaults initialization | -| `internal/frps/` | Manages the lifecycle of the frps process, monitoring its status | -| `internal/heartbeat/` | Periodic HTTP heartbeat, status reporting, and update retrievals | -| `internal/httpclient/` | General API client for calling the Server | -| `internal/observability/` | Host and frps metrics collection and pre-aggregation | -| `internal/relay/` | Coordinates the core Relay lifecycle, setup, and cleanup | -| `internal/state/` | Local runtime states, error logs, and persistent caches | -| `internal/updater/` | Relay update check, download installation, and restarts | -| `internal/wsclient/` | Bi-directional real-time WebSocket connection to the Server | - -## OpenFlared (Client) Modules - -| Module | Responsibility | -| --- | --- | -| `cmd/` | CLI startup entrypoint and main bootstrap functions | -| `internal/config/` | Local client configurations loading and parsing | -| `internal/flared/` | Core client scheduling and tunnel lifecycle orchestration | -| `internal/frpc/` | Dynamically generates `frpc.toml` configs for multiple Relays and monitors frpc processes | -| `internal/heartbeat/` | Heartbeat communications with control planes, including token checks | -| `internal/httpclient/` | General API client for Server communication | -| `internal/sync/` | Incrementally pulls latest Tunnel route bindings, generates snapshots, and applies them | -| `internal/updater/` | Client self-update, new version check, and upgrade installation | -| `internal/wsclient/` | Bi-directional WebSocket client for real-time tunnel configuration pushes | diff --git a/docs/en/design/tunnel-design.md b/docs/en/design/tunnel-design.md deleted file mode 100644 index 84955ad7..00000000 --- a/docs/en/design/tunnel-design.md +++ /dev/null @@ -1,130 +0,0 @@ -# Intranet Penetration Tunnel Design Document - -You will learn: The architectural design of the OpenFlare intranet penetration tunnel, the internal principles of the dual-ended control components (Relay and Client), their interaction logics, and the communication flows for the data plane and control plane. - ---- - -## Requirements Analysis - -In typical web application hosting scenarios, many origin servers (Origin Servers) are deployed in local intranet environments (such as local development machines, LAN servers, or firewalled private clusters). These servers typically suffer from: -1. **No Public IP**: Cannot be directly accessed by public internet traffic. -2. **Security Compliance Restrictions**: Creating port mappings (NAT) on border routers is strictly prohibited by security policies. -3. **Dynamic IP Changes**: Traditional DDNS solutions exhibit high latency and are highly unstable. - -To allow internal origin servers to seamlessly integrate into the OpenFlare global data gateway, benefiting from premium features like WAF geographic protection and TLS certificate hosting, OpenFlare designed an end-to-end solution based on a **reverse relay penetration tunnel**. In this architecture, public edge nodes act as reverse proxy entrances and traffic relays, while the intranet side only needs to initiate secure outbound connections to achieve secure and stable reverse penetration of public traffic to internal origin servers. - ---- - -## Core Capabilities - -The intranet penetration tunnel subsystem includes the following core capabilities: - -* **Dynamic Relay Node Management**: The control plane dynamically dispatches relay services (frps), distributing service ports and authentication tokens dynamically. -* **Multi-Tunnel Reverse Proxy Mapping**: Supports mapping multiple internal web ports on a single intranet client, binding multiple domain routes to corresponding relay nodes. -* **Independent Process Lifecycle Control**: Both the relay and client are independent daemon processes written in Go, responsible for spawning, monitoring, self-healing, and hot-upgrading the underlying frp engine. -* **Token-based Independent Authentication**: The relay uses `agent_token` for authorization, whereas the intranet client uses its dedicated `tunnel_token`, enforcing isolation of permissions and routing boundaries. -* **Validation & Incremental Hot Reload**: Config files are rewritten and processes are gracefully reloaded only when tunnel bindings, certificates, or Relay topologies change, reducing runtime overhead. - ---- - -## Intranet Penetration & Tunnel Architecture - -The intranet penetration subsystem is integrated on top of the mature and high-performance `frp` tunnel protocol, divided into the **Control Plane** and the **Data Plane**. - -```mermaid -graph TD - %% Data Flow - Browser[1. Browser / Visitor] -->|HTTPS Request| Agent[2. OpenResty / Agent] - Agent -->|Local proxy_pass| RelayFrps[3. OpenFlare Relay / frps] - RelayFrps -->|Encrypted Tunnel Protocol| FlaredFrpc[4. OpenFlared / frpc] - FlaredFrpc -->|Forward Local Request| LocalOrigin[5. Intranet Origin 192.168.x.x] - - %% Control Flow & Heartbeats - Server[OpenFlare Server Control Plane] <-->|Relay API / Heartbeat| RelayManager[openflare-relay process] - Server <-->|Client API / Heartbeat| ClientManager[openflared process] - - RelayManager -.->|Control Process & Config| RelayFrps - ClientManager -.->|Control Multi-Relay Processes| FlaredFrpc - - style Browser fill:#f9f,stroke:#333,stroke-width:2px - style LocalOrigin fill:#9f9,stroke:#333,stroke-width:2px - style Server fill:#f96,stroke:#333,stroke-width:2px -``` - -* **Control Plane**: The Server maintains the database state. The `openflare-relay` process on relay nodes and the `openflared` process on intranet servers synchronize tunnel configurations via HTTP heartbeats and long-lived WebSocket connections. -* **Data Plane**: Public traffic enters the public edge Agent (OpenResty), where the TLS handshake, HTTPS termination, and WAF filtering are executed. It is then forwarded via `proxy_pass` to the co-located `openflare-relay (frps)` on the loopback address. `frps` encapsulates the HTTP requests into the encrypted TCP tunnel and sends them down to the intranet `openflared (frpc)`. Finally, `frpc` unpacks the requests and forwards them to the actual intranet origin service. - ---- - -## Relay (Server-side) Design - -`openflare-relay` is a relay manager deployed on the public edge, running on nodes of type `tunnel_relay`. - -### 1. Core Architecture & Logic -* **Process Daemon**: The Relay process embeds the `frps` binary, spawning the `frps -c frps.toml` subprocess via `exec.Command` and using goroutines to asynchronously listen to its exit status. If `frps` exits unexpectedly, it automatically restarts using an exponential backoff policy. -* **Dynamic Configuration Rendering**: Periodically synchronizes status with the control plane via HTTP heartbeats to retrieve the active `RelayConfig`, including: - * `bindPort`: The public control port that frps listens to for incoming intranet frpc connections. - * `vhostHTTPPort`: The virtual host HTTP listening port where the Agent's proxy_pass points. - * `authToken`: The security credential used during the client connection handshake. - * `webServer`: Enables the frps dashboard API, which the Relay queries to collect active tunnel counts and traffic metrics. -* **Status Reporting**: In each heartbeat cycle, the Relay reports the active connections, registered clients, individual proxy tunnel statuses, and Relay version back to the Server. - ---- - -## Openflared (Client-side) Design - -`openflared` is the client manager running inside the user's intranet server, authenticated using a dedicated `tunnel_token`. - -### 1. Core Design Mechanisms -* **Multi-Relay Support (Multiplexing)**: - To guarantee high availability and geographical proximity, the control plane may schedule the client to connect to multiple public Relays. `openflared` parses the list of Relays dispatched in the `TunnelConfig`, generating dedicated configurations (`frpc_.toml`) and allocating distinct cancelable contexts for each Relay process locally. -* **Independent Subprocess Monitoring**: - `openflared` maintains a local `processes` map to manage the lifecycles of individual `frpc` subprocesses. When the control plane adds or removes Relays, the client incrementally spawns new processes or gracefully shuts down obsolete ones without affecting other functioning tunnels. -* **Dynamic TOML Generation**: - When rendering TOML configs for each Relay, the client iterates over the Proxies list, writing each intranet service's `LocalAddr`, `LocalPort`, and bound `CustomDomains` into standard `[[proxies]]` blocks. - ---- - -## Interaction Logic & Traffic Model - -The intranet penetration subsystem implements consistent version control and status feedback loops. - -### 1. Control Plane Publishing & Sync Flow - -```text -Admin modifies tunnel/intranet port mappings -> Click Publish -> Generate new Tunnel version & Checksum - | - v (Push or Heartbeat Pull) -+-----------------------------------------------------------------------+-----------------------------------------------------------------------+ -| | -v (Relay Side) v (Client Side) -openflare-relay heartbeat detects frps port/Token change openflared heartbeat detects tunnel_version change -Re-render local frps.toml Request full proxy configuration details -Kill and restart the frps process Re-render frpc_.toml configs -Report health status as healthy Restart or hot-reload changed frpc processes - Report application results (Apply Success/Error) -``` - -1. **Versioned Controls**: All intranet tunnel routes and mapping relationships are version-controlled, dispatching a unique `version` and `checksum` to ensure clients do not repeatedly write files or trigger redundant reloads. -2. **Closed-Loop Application Feedback**: After applying new configurations, the client reports the application result in the next heartbeat. If the intranet port is unreachable or certificate bindings fail, the client intercepts the stdout/stderr of the subprocess to report `LastError` to the Server, providing administrators with transparent error details. - -### 2. Data Plane Traffic Model -1. **Public Entrance (Agent)**: - ```nginx - server { - listen 443 ssl; - server_name intranet.example.com; - # ... TLS certificates & WAF filtering ... - location / { - proxy_pass http://127.0.0.1:18080; # Points to local frps vhost port - proxy_set_header Host $host; # Must preserve the original Host header, which frps relies on to route requests - proxy_set_header X-Real-IP $remote_addr; - } - } - ``` -2. **Relay Node (frps)**: - `frps` listens to the Vhost port `18080`. When an HTTP request arrives, it extracts `Host: intranet.example.com` from the request headers and searches its active registered tunnel registry to locate the matching encrypted TCP connection (initiated by the intranet frpc). -3. **Encrypted Tunnel Transmission (TCP)**: - `frps` encapsulates the HTTP request into the custom TCP tunnel protocol and transmits it down to the intranet `frpc` client. -4. **Intranet Client Distribution (frpc)**: - The `frpc` instance managed by `openflared` receives the payload, resolves it according to local settings (`localIP = "127.0.0.1"`, `localPort = 8080`), initiates a local TCP connection to forward the request to the intranet web service, and returns the response back through the tunnel to the public viewer. diff --git a/docs/en/design/waf-design.md b/docs/en/design/waf-design.md deleted file mode 100644 index ae4fbbe3..00000000 --- a/docs/en/design/waf-design.md +++ /dev/null @@ -1,132 +0,0 @@ -# WAF Design Document - -You will learn: The core architecture of the OpenFlare edge Web Application Firewall (WAF), the dynamic IP group asynchronous differential sync model, the high-performance OpenResty Lua caching scheme, and the complete request filtering and decision logic. - ---- - -## Requirements Analysis - -In public internet environments, web applications face a wide variety of security threats (such as scanner profiling, api scraping, malicious botnets targeted at specific regions, ransomware, and CC attacks). Allowing malicious requests to pass directly to the origin server (Origin Server) results in: -1. **Origin Server Overload**: High-frequency database queries and intensive CPU computations easily exhaust server resources. -2. **Sensitive API Abuse**: APIs like login, registration, and SMS verification codes can be maliciously exploited, leading to financial and computational losses. -3. **Data Exposure Risks**: Malicious common vulnerability probing actions are not intercepted proactively. - -Therefore, OpenFlare needs to build a **high-performance, resiliently scalable WAF filtering engine** at the frontmost data plane layer (OpenResty). This engine is capable of executing deep filtering on malicious requests at the edge layer closest to users with sub-millisecond overhead. This relieves pressure on origin servers and provides core security capabilities like CC protection (PoW challenge), IP whitelisting/blacklisting, and region-level interception. - ---- - -## Core Capabilities - -OpenFlare WAF includes the following core protection dimensions: - -* **IP Interception (IP Whitelist/Blacklist)**: Supports filtering by single IP or CIDR block, and aggregating tens of thousands of IPs into IP groups for highly efficient matching. -* **Geographical Whitelist/Blacklist (GeoIP Limit)**: Integrates MaxMind databases to support precise admission controls based on countries and provinces/regions. -* **Custom Interception Responses**: Supports custom block status codes (e.g., 403, 418) and personalized HTML block pages for different filtering rules. -* **Human-Machine Challenge (PoW CC Protection)**: Supports seamless client-side PoW challenges, calculating Hash collisions to prevent automated scripts and botnets from hitting endpoints concurrently. - ---- - -## IP Group Design & Dynamic Asynchronous Sync - -IP groups are the core containers for highly efficient IP whitelisting and blacklisting. OpenFlare classifies IP groups into three types based on their update frequencies and source channels: - -### 1. IP Group Types -* **Manual**: Manually input by administrators in the control panel. Primarily used for static trusted IPs or long-term blocks. -* **Subscription**: Configured with remote text feeds (one IP/CIDR per line) or standard JSON subscription URLs. Server-side cron jobs periodically fetch and parse the remote subscription sources. Primarily used for integrating open-source threat intelligence feeds, cloud provider IP ranges, etc. -* **Automatic**: **The most resilient dynamic protection channel**. Control plane scanning jobs read access logs from all nodes, performing aggregation and analysis based on configured Expr rules (e.g., "requesting the `/api/login` endpoint over 50 times with a 401 status code in 5 minutes"). Once matched, the source IP is automatically added to a temporary block list for a specified duration. - -### 2. Asynchronous Differential Sync Design (No Nginx Reload) -In traditional Nginx WAF designs, IP blacklist updates typically require writing configurations and executing reloads. If malicious IP blocks occur at high frequencies (seconds or minutes), frequent reloads force Nginx to constantly spawn new worker processes and tear down old ones, severely degrading performance. - -OpenFlare adopts a **dynamic IP group asynchronous differential sync design**: - -```text -WAF IP member updates (Manual/Subscription/Auto-trigger) - | - v -Server updates the database and calculates the new MD5 Checksum of the IP group - | - +----------------------------------------+ - | (WebSocket Real-time Broadcast) | (Heartbeat Fallback Comparison) - v v -Server immediately pushes complete members Agent heartbeats report the local IP groups -of modified groups to all Agents checksum mapping table - | | - | v - | Server detects Checksum mismatch and dispatches - v the modified IP group members -Agent receives member data and writes it as JSON to local disk: waf_ip_groups.json - | - v (Lua Memory Awareness) -OpenResty Lua engine detects file changes via MD5 checksum in seconds and hot-updates its memory, -completely bypassing Nginx process reloads. -``` - -Through this architecture, the persistence and activation of tens of thousands of highly volatile dynamic blacklist IPs **require absolutely no Nginx reloads**, maximally protecting the high-concurrency throughput of the gateway. - ---- - -## Rule Groups & Site Bindings - -* **WAF Rule Group**: The smallest logical collection of WAF filtering policies. A single rule group can contain IP whitelists/blacklists, IP group references, regional restrictions, and CC protection configurations. -* **Global Rule Group**: When a rule group is marked as `is_global = true`, it takes effect on **all website routes** hosted on the node by default. -* **Site Binding**: Website routes (`proxy_routes`) can bind one or more non-global rule groups. During request validation, WAF evaluates the union of `Global Rule Group + Bound Rule Groups`. - ---- - -## Implementation Details & High-Performance Caching - -WAF is triggered in the OpenResty `access_by_lua` phase, implemented primarily through Lua files and local JSON configurations. - -### 1. Physical Structures -* `waf_config.json`: Contains metadata for all rule groups, geographic country/region limits, and website-to-rule-group bindings. -* `waf_ip_groups.json`: Contains all synchronized IP groups and their corresponding IP lists. -* `waf/runtime.lua`: The actual runtime engine responsible for WAF rule comparison. -* `waf/check.lua`: The entry point for the access layer, handling packages inclusion and triggering `check()`. - -### 2. Shared Memory Dictionary (ngx.shared) High-Performance Cache Design -Reading JSON files from the disk and decoding them upon every incoming web request would make disk I/O a severe performance bottleneck. - -OpenFlare leverages the **OpenResty Shared Memory Dictionary (ngx.shared.openflare_waf_config)** to implement a two-level caching mechanism: - -1. **Zero File I/O Path**: - In Lua, every time `check()` executes, it first computes the MD5 hash of the local JSON file using `ngx.md5` (which takes virtually zero time since the file is cached in the OS Page Cache). -2. **Hash Comparison & Hot Loading**: - It compares this against the cached hash key (`_config_hash`) stored in the shared memory dictionary. - * **If the hash is unchanged**: It reads the pre-decoded Lua Table configuration stored directly in shared memory. The entire verification runs purely in **shared memory**, completing in **microseconds**. - * **If the hash is mismatched**: Indicating that the Agent has just updated the WAF rules or IP groups on the disk, the Lua engine automatically reads the disk file, decodes it via `cjson.decode`, writes the decoded data and the new MD5 hash into shared memory, and makes it seamlessly readable by all subsequent worker processes. - ---- - -## Application Flow & Decision Judgment Control Logic - -When an HTTP/HTTPS request arrives at OpenResty, WAF evaluates and intercepts it step-by-step in the `access` phase according to the funnel decision chain below: - -### 1. WAF Decision Flowchart - -```mermaid -flowchart TD - A[Request enters access phase] --> B[Get Site Name of current request] - B --> C[Load all active rule groups bound to this Site in shared memory] - C --> D{Matches IP whitelist or Whitelist IP group?} - D -- Yes (Matched) --> E[Pass request - ALLOW] - D -- No --> F{Matches country/region whitelist?} - F -- Yes (Matched) --> E - F -- No --> G{Matches IP blacklist or Blacklist IP group?} - G -- Yes (Matched) --> H[Block request - BLOCK] - G -- No --> I{Matches country/region blacklist?} - I -- Yes (Matched) --> H - I -- No --> J{Is CC PoW verification enabled?} - J -- Yes --> K[Transfer to CC Protection module] - J -- No --> L[No security risks, pass normally] - - H --> M[Exit and return custom status code and block page HTML configured in the rule group] -``` - -### 2. Decision Step Details -1. **Whitelist Precedence**: - To prevent false positives and guarantee smooth passage of core back-to-source traffic (such as search engine spiders, CDN back-to-source IPs, and office egresses), WAF **prioritizes matching IP whitelists and regional whitelists**. Once a whitelist matches, it immediately bypasses all subsequent blacklist checks and CC challenges. -2. **Blacklist Aggressive Block**: - If a request is not captured by the whitelist evaluation, it enters the blacklist funnel. Once the source IP matches an IP blacklist, a referenced blacklist IP group, or lies within a prohibited country/region, the Lua engine immediately marks `ngx.ctx.openflare_waf_blocked` as `true`. -3. **Response Output**: - Upon hitting the blacklist, Lua extracts the `block_status_code` (defaults to 418 or 403) and `block_response_body` (interception HTML page) configured in the matching rule group. It outputs the response body via `ngx.say()` and gracefully terminates the request using `ngx.exit(status)` to prevent the request from passing upstream. diff --git a/docs/en/guide/credits.md b/docs/en/guide/credits.md deleted file mode 100644 index 0a1fee57..00000000 --- a/docs/en/guide/credits.md +++ /dev/null @@ -1,27 +0,0 @@ -# Credits - -OpenFlare is essentially a solution integration project. During its design and implementation phases, it drew inspiration from the exceptional concepts, architectural designs, and technical achievements of numerous open-source projects. Below are the key upstream open-source projects OpenFlare relies on for its core engine, security mechanisms, and backend/frontend system frameworks, along with our sincere thanks to these projects and their active communities. - ---- - -### 1. OpenResty -* **Project Positioning**: A high-performance Web platform based on Nginx and Lua. -* **Role in OpenFlare**: Acts as the edge gateway for the global Data Plane. All public web traffic is received by OpenResty first, where high-concurrency HTTPS handshakes, WAF security rule evaluations, and PoW CC verification are performed before executing reverse proxies. -* **Project Link**: [OpenResty Official Website](https://openresty.org/) - -### 2. FRP (Fast Reverse Proxy) -* **Project Positioning**: A high-performance reverse proxy application focused on intranet penetration. -* **Role in OpenFlare**: Serves as the underlying tunnel engine for the intranet penetration subsystem. The relay-side manager `openflare-relay` is responsible for running and scheduling the `frps` engine, while the intranet client `openflared` is responsible for generating TOML configurations locally and running the multiplexed `frpc` subprocesses. -* **Project Link**: [fatedier/frp (GitHub)](https://github.com/fatedier/frp) - ---- - -### 3. Anubis (PoW Solution) -* **Project Positioning**: A lightweight human-machine verification and protection solution based on Proof of Work (PoW). -* **Role in OpenFlare**: Provides the core **seamless PoW CC challenge** capabilities for the gateway WAF. - ---- - -### 4. gin-template -* **Project Positioning**: A modern full-stack development boilerplate based on Go Gin and frontend builds. -* **Role in OpenFlare**: Provided the standard, unified backend/frontend system architecture baseline for the OpenFlare control plane (Server). diff --git a/docs/en/guide/first-site.md b/docs/en/guide/first-site.md deleted file mode 100644 index 4412afa3..00000000 --- a/docs/en/guide/first-site.md +++ /dev/null @@ -1,100 +0,0 @@ -# Publishing Your First Site - -You will learn: How to create your first website configuration, bind origins and certificates, publish the configuration version, and verify that the Agent applied it successfully. - -The publishing pipeline of OpenFlare centers on a complete configuration version snapshot. After modifying website configurations in the management console, you need to publish and activate the new version to let the Agent pull and apply it in the next heartbeat. - -## Pre-publish Checks - -Verify that the following conditions are met: - -| Item | Expectation | -| --- | --- | -| Server | Management console is accessible and log-in succeeds | -| Agent | At least one node is online | -| Origin | The Agent node can reach the origin server address | -| Domain | Domain is resolved to the OpenResty node, or prepared to verify via local `hosts` / `curl` Host header | -| HTTPS | If HTTPS is required, the certificate is uploaded or hosted | - -## Create Website Configuration - -A new website configuration requires at least: - -| Field | Description | -| --- | --- | -| Website Name | Business unique identifier; the primary domain is used if left blank | -| Domain | At least one domain, where the first is treated as the primary domain | -| Origin Address | A valid `http://` or `https://` upstream address | -| Enabled Status | Only enabled website configurations will participate in publishing and rendering | - -Example: - -| Field | Example | -| --- | --- | -| Website Name | `app` | -| Domain | `app.example.com` | -| Origin Address | `http://10.0.0.20:8080` | - -A single domain can belong to only one website configuration. Rate limiting, reverse proxy, and caching parameters are shared site-wide. - -## Bind Certificate - -HTTPS certificates are bound by domain. Domains without a bound certificate will not be placed into `443 ssl` server blocks automatically. - -If a website contains multiple domains, the rendering pipeline groups the HTTPS configurations by certificate while ensuring all domains belong to the same site snapshot. - -## Publish & Activate - -Standard Pipeline: - -```text -Modify rules -> Preview / Diff -> Publish -> Generate complete version -> Activate version -> Agent pulls -> Local application -> Report result -``` - -During publication, the Server reads all enabled website configurations, the main OpenResty config templates, performance and cache parameters, rendering the complete OpenResty configuration and calculating its `checksum`, saving to `config_versions`, and switching the active version. - -## Verify Results - -Verify in the management console after publishing: - -| Position | Expected Result | -| --- | --- | -| Node List | Node status is online | -| Node Details | Current version matches active version | -| Apply Logs | Most recent application succeeded | -| Version Page | The new version is currently active | - -Verify Agent logs on the node: - -```bash -journalctl -u openflare-agent -n 100 --no-pager -``` - -Access via domain: - -```bash -curl -I http://app.example.com -``` - -If the domain has not been officially resolved, you can verify by specifying the Host header against the node IP: - -```bash -curl -I -H 'Host: app.example.com' http://NODE_IP -``` - -HTTPS Validation: - -```bash -curl -I https://app.example.com -``` - -## Rollback - -If a target version application fails and triggers a rollback, the Agent blocks repeated synchronization of the same failing `version + checksum` until the active version or checksum changes on the control plane. - -Roll back to an older version: - -1. Open the Configuration Versions page. -2. Locate the last known good historic version. -3. Re-activate that version. -4. Check the node application logs to verify that the Agent successfully applied the rollback. diff --git a/docs/en/guide/index.md b/docs/en/guide/index.md deleted file mode 100644 index e72964d0..00000000 --- a/docs/en/guide/index.md +++ /dev/null @@ -1,43 +0,0 @@ -# Guide Overview - -You will learn: How the OpenFlare documentation is organized, which pages to read when running it for the first time, and where to start for deployment, usage, troubleshooting, and development. - -OpenFlare is a self-hosted OpenResty control plane. It integrates reverse proxy website configurations, configuration version publishing, Agent node synchronization, TLS certificates, and basic observability into a single management console, making it ideal for a single team or organization managing multiple proxy nodes. - -## Recommended Reading Path - -If you are new to OpenFlare, read the documents in the following order: - -1. [Quick Start](./quick-start.md): Start the Server using Docker Compose, log into the management console, and connect your first Agent. -2. [Basic Usage](./usage.md): Learn common operations for website configs, origins, certificates, publishing, rollbacks, and observability. -3. [Tunnel & Intranet Penetration](./tunnel-usage.md): Learn to deploy Relay and Client to achieve secure, public IP-free reverse penetration. -4. [WAF Security Protection](./waf-usage.md): Master IP whitelisting/blacklisting, WAF auto IP group aggregation Expr rules, geographical restrictions, and PoW CC protection. -5. [WAF Auto IP Group Expressions](./waf-ip-group-expr.md): Write auto IP group Expr rules and learn keyword definitions and presets. -6. [Deployment Guide](../deployment/deployment.md): Deploy Server and Agent in closer-to-production environments. -7. [Configurations Reference](../reference/configuration.md): Check Server environment variables, runtime Options, and Agent configurations. -8. [Troubleshooting](./troubleshooting.md): Troubleshoot login, database, node sync, OpenResty application, and frontend build issues. - -## Role-Based Entrypoints - -| What do you want to do? | Recommended Entrance | -| --- | --- | -| Run the console in under 5 minutes | [Quick Start](./quick-start.md) | -| Publish your first reverse proxy configuration | [Publish First Configuration](./first-site.md) | -| Configure intranet penetration mapping | [Tunnel & Intranet Penetration](./tunnel-usage.md) | -| Configure CC protection & IP group blocking | [WAF Security Protection](./waf-usage.md) | -| Write auto IP group aggregation rules | [WAF Auto IP Group Expressions](./waf-ip-group-expr.md) | -| Connect or reinstall a node Agent | [Access Agent](../deployment/agent.md) | -| Start Server from source code | [Launch Server](../deployment/server.md) | -| Configure GitHub or OIDC SSO | [SSO Login Configuration](./sso.md) | -| Upgrade Server or Agent | [Upgrade & Maintenance](../deployment/upgrade.md) | -| Participate in development or bug fixing | [Local Development](../design/development.md) and [Development Constraints](../../guideline/Constraints.md) | -| Understand architecture and publishing | [System Architecture](../design/architecture.md) and [Agent & Publish Model](../design/agent-design.md) | -| View open-source references and credits | [Credits](./credits.md) | - -## Documentation Partitions - -`guide/` is oriented toward users and deployers, providing actionable steps from installation to daily operations. - -`reference/` collects stable facts such as configuration fields, commands, API response structures, and repository layout. - -`design/` is oriented toward maintainers and contributors, describing product boundaries, system architecture, Agent & publishing models, and engineering constraints. Before adding capabilities or changing boundaries, update the corresponding design document first. diff --git a/docs/en/guide/quick-start.md b/docs/en/guide/quick-start.md deleted file mode 100644 index 48277ba6..00000000 --- a/docs/en/guide/quick-start.md +++ /dev/null @@ -1,219 +0,0 @@ -# Quick Start - -You will learn: How to start OpenFlare Server using Docker Compose, complete your first login, connect your first Agent, and verify if a configuration has been published to the node. - -The minimum running unit of OpenFlare consists of: - -| Component | Responsibility | -| --- | --- | -| Server | Admin UI, Admin API, Agent API, configuration rendering, version publishing, and state storage. | -| Agent | Runs on the proxy node, pulls configurations, writes files for OpenResty, executes validations, and triggers reloads. | -| OpenResty | Receives actual traffic and reverse proxies it to origin servers. | - -The Agent manages the runtime through the OpenResty binary. A local deployment requires the `openresty` executable to be already present on the node; a Docker deployment can directly run the Agent image containing built-in OpenResty. - -## Environment Requirements - -| Item | Requirement | -| --- | --- | -| Docker / Docker Compose | Used to start Server and PostgreSQL; also used to run the Agent if using the Docker Agent image | -| OpenResty | Required to have the `openresty` executable when installing the Agent locally, or specify its path in the installation script | -| Reachable Ports | The Server listens on port `3000` by default; the Agent node needs to be able to reach the Server address | -| Browser | Used to access the management console | - -* **Docker**: `20.10.0+` -* **Docker Compose**: `2.0.0+` - -## 1. Start the Server - -Create a `docker-compose.yml` file in an empty directory: - -```yaml -services: - postgres: - image: postgres:17-alpine - restart: unless-stopped - environment: - POSTGRES_DB: openflare - POSTGRES_USER: openflare - POSTGRES_PASSWORD: replace-with-strong-password - volumes: - - postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U openflare -d openflare"] - interval: 10s - timeout: 5s - retries: 5 - - openflare: - image: ghcr.io/rain-kl/openflare:latest - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - ports: - - "3000:3000" - environment: - SESSION_SECRET: replace-with-a-long-random-string - DSN: postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable - GIN_MODE: release - LOG_LEVEL: info - volumes: - - openflare-data:/data - -volumes: - postgres-data: - openflare-data: -``` - -Start the services: - -```bash -docker compose up -d -``` - -Verify that the containers are running: - -```bash -docker compose ps -docker compose logs -f openflare -``` - -Once you see `server listening` in the logs and the `openflare` container status is running, access: - -```text -http://localhost:3000 -``` - -Default credentials: - -| Username | Password | -| --- | --- | -| `root` | `123456` | - -Please change the default password immediately after your first login. - -## 2. Prepare Agent Token - -The Agent can be connected using one of two types of credentials: - -| Credential | Applicable Scenario | -| --- | --- | -| `discovery_token` | Automatically registers a node for the first time, which the Server exchanges for a node-specific Token | -| `agent_token` | Node has already been created/allocated in the management console, directly uses this node-specific Token | - -After preparing one of these credentials in the management console, proceed to the next step. - -* **`discovery_token`** path: "System Settings" -> "Auto Registration" -* **`agent_token`** path: "Node Management" -> "Add Node" - -## 3. Install/Run the Agent - -The recommended Agent deployment method is using Docker (which runs the Agent image with built-in OpenResty); deploying the Agent locally on the host using the installation script is also supported. - -### Option A: Run Agent in Docker (Recommended) - -Run the Agent image directly on the proxy node: - -```bash -docker pull ghcr.io/rain-kl/openflare-agent:latest -docker rm -f openflare-agent 2>/dev/null || true -docker run -d --name openflare-agent --restart unless-stopped \ - -p 80:80 -p 443:443 \ - -v openflare-agent-data:/data \ - -e OPENFLARE_SERVER_URL=http://your-server:3000 \ - -e OPENFLARE_AGENT_TOKEN=YOUR_AGENT_TOKEN \ - ghcr.io/rain-kl/openflare-agent:latest -``` - -### Option B: Execute Installation Script (Local Host Deployment) - -Execute the installation script on the proxy node. - -Using the `discovery_token`: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --discovery-token YOUR_DISCOVERY_TOKEN -``` - -Using the node-specific `agent_token`: - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --agent-token YOUR_AGENT_TOKEN -``` - -The script defaults to: - -| Item | Default Value | -| --- | --- | -| Install Directory | `/opt/openflare-agent` | -| Config File | `/opt/openflare-agent/agent.json` | -| systemd Service | `openflare-agent.service` | -| OpenResty Path | Automatically detects `openresty` if unspecified | - -Verify the Agent service status: - -```bash -systemctl status openflare-agent -journalctl -u openflare-agent -f -``` - -If systemd is not available on the OS, the script outputs manual startup commands instead. - -## 4. Publish Your First Configuration - -Perform the following operations in the management console: - -1. Add a website configuration, filling in the website name, domain, and origin address. -2. Verify that the website configuration is enabled. -3. Check the preview or change summary before publishing. -4. Publish and activate the new version. -5. Wait for the Agent to detect and apply the version in the next heartbeat. - -The version number format is `YYYYMMDD-NNN`. Historic versions are immutable; rollbacks are accomplished by re-activating an older version. - -## 5. Verify Success - -Confirm in the management console: - -| Position | Expected Result | -| --- | --- | -| Node List | Agent node status is online | -| Node Details | Current version matches active version | -| Apply Logs | Most recent application succeeded | -| Version Page | The new version is currently active | - -Confirm on the Agent node: - -```bash -journalctl -u openflare-agent -n 100 --no-pager -``` - -## Common Failures - -| Symptom | Troubleshooting Direction | -| --- | --- | -| Management console fails to load in browser | Verify that the Server is running in `docker compose ps` and port `3000` is not bound by other processes | -| Data fails to save after logging in | Check the health of the PostgreSQL container, and verify the username, password, and database name in `DSN` | -| Agent fails to register | Verify that the Agent node can reach `--server-url`, and verify if the Token is typed correctly or expired | -| Agent is online but configuration is not applied | Verify that the website configuration is enabled and a version has been published and activated | -| OpenResty application fails | Review node application logs and `journalctl -u openflare-agent`, checking domains, certificates, upstreams, and port conflicts | - -For more troubleshooting details, see [Troubleshooting](./troubleshooting.md). - ---- - -## Advanced Deployment Guides - -Once you complete the quick start and familiarize yourself with the basic operations of OpenFlare, you can read the following advanced deployment documents to put components into production: - -* **Server Production Deployment**: Read [Launch Server](../deployment/server.md) to learn how to build the frontend from source, configure system environment variables, and run with Docker Compose. -* **Agent Production Integration**: Read [Deploy Agent](../deployment/agent.md) to learn about systemd-based service management, detailed local configuration parameters, and troubleshooting. -* **Tunnel Relay Deployment**: Read [Deploy Relay](../deployment/relay.md) to learn how to configure public relay nodes (frps) for penetration tunnels. -* **Tunnel Client Deployment**: Read [Deploy OpenFlared](../deployment/openflared.md) to learn how to run the penetration daemon client (frpc) on the intranet server side. -* **Production Deployment Topology**: Read [Deployment Guide](../deployment/deployment.md) to learn about high-availability production topologies and overall network planning. -* **System Upgrades & Maintenance**: Read [Upgrade & Maintenance](../deployment/upgrade.md) to learn how to upgrade the Server and individual node Agents smoothly. diff --git a/docs/en/guide/sso.md b/docs/en/guide/sso.md deleted file mode 100644 index d8d59a27..00000000 --- a/docs/en/guide/sso.md +++ /dev/null @@ -1,106 +0,0 @@ -# SSO Login Configuration - -You will learn: How to configure GitHub OAuth or standard OIDC login portals for OpenFlare, how to fill in callback URLs, and how third-party accounts bind to existing local users. - -OpenFlare supports third-party logins configured via Authentication Sources. Currently, GitHub OAuth and standard OIDC Providers (e.g., Logto, authentik, Keycloak, Casdoor) are supported. - -Once an Authentication Source is configured and enabled, it displays in the third-party login section of the login page. Users can log in using their third-party accounts or bind their third-party accounts to their current local account while logged in. - -## Prerequisites - -Before starting, prepare the following: - -| Item | Description | -| --- | --- | -| OpenFlare URL | The actual URL accessed by user browsers, e.g., `https://openflare.example.com` | -| Auth Source Name | Unique internal identifier in OpenFlare, e.g., `github`, `company-oidc` | -| Client ID | Provided after creating an application in the third-party platform | -| Client Secret | Provided after creating an application in the third-party platform | -| OIDC Discovery URL | Required for OIDC only, e.g., `https://idp.example.com/.well-known/openid-configuration` | - -**Verify that "System Settings -> General Settings -> Server Address" accurately matches your domain name.** - -The Auth Source name can only contain letters, numbers, hyphens, or underscores, and must start with a letter or number. The Auth Source name will appear in the callback URL; if you modify the name after saving, you must simultaneously modify the callback URL on the third-party platform. - -## Callback URL - -The Redirect URI / Callback URL in third-party platforms is formatted as: - -```text -/oauth/ -``` - -Example: - -```text -https://openflare.example.com/oauth/github -https://openflare.example.com/oauth/company-oidc -``` - -When creating or editing an authentication source in the management console, the form automatically generates the callback URL based on your current browser URL and the Auth Source name you entered. - -## Configure GitHub Login - -1. Create an OAuth App in GitHub. -2. Fill `Homepage URL` with your OpenFlare URL. -3. Fill `Authorization callback URL` with the callback URL generated in OpenFlare, e.g., `https://openflare.example.com/oauth/github`. -4. Copy the Client ID and Client Secret provided by GitHub. -5. Log into the OpenFlare management console, go to "Settings -> System Settings -> Configure Authentication Sources". -6. Add an authentication source, choosing `GitHub` as the type. -7. Fill in the Auth Source name, display name, Client ID, and Client Secret. -8. The Scope defaults to `user:email`, which usually requires no modification. -9. Save and enable the authentication source. - -Once enabled, the corresponding GitHub login button will display on the login page. - -## Configure OIDC Login - -1. Create an application or client in your OIDC Provider. -2. Select Web / Confidential Client as the application type. -3. Fill `Redirect URI / Callback URL` with the callback URL generated in OpenFlare, e.g., `https://openflare.example.com/oauth/company-oidc`. -4. Copy the Client ID and Client Secret. -5. Retrieve the Provider's Discovery URL, which usually ends with `/.well-known/openid-configuration`. -6. Log into the OpenFlare management console, go to "Settings -> System Settings -> Configure Authentication Sources". -7. Add an authentication source, choosing `OIDC` as the type. -8. Fill in the Auth Source name, display name, Client ID, Client Secret, and OIDC Discovery URL. -9. Scope defaults to `openid profile email`. If the Provider restricts scopes, adjust to values permitted by the Provider. -10. Save and enable the authentication source. - -Once enabled, the corresponding OIDC login button will display on the login page. - -## Login & Binding Behaviors - -Once a third-party account returns to OpenFlare, it is processed according to the following rules: - -| Scenario | Behavior | -| --- | --- | -| Third-party account is already bound to a local user | Logs in directly | -| User is already logged in and initiates third-party authorization | Binds to the current local user | -| Third-party account is unbound, and registration is enabled | Automatically creates a standard user and binds | -| Third-party account is unbound, and registration is disabled | Prompts to enter an existing local username and password to complete the binding | - -If you want only existing users to use SSO, you can disable user registration. Unbound third-party accounts will then trigger the binding flow. - -## Modify Authentication Source - -When editing an authentication source, leaving the Client Secret field blank retains the existing secret; entering a new value will overwrite the saved secret. - -If you modify the Auth Source name, the callback URL changes accordingly. You must modify the Redirect URI / Callback URL on the third-party platform; otherwise, the third-party platform will deny the callback or return an error. - -## Common Problems - -### Returns `invalid_scope` - -This indicates that the third-party platform does not permit the configured Scope. OIDC defaults to `openid profile email`, and GitHub defaults to `user:email`. Adjust the Scope in the authentication source edit page or configure the third-party platform to permit the scope. - -### Callback Address Mismatch - -Verify if the Redirect URI / Callback URL configured in the third-party platform matches the prompt in the OpenFlare form exactly. The protocol, domain, port, and path must match. - -### Third-party Login Button Not Showing on Login Page - -Verify if the authentication source is enabled and confirm that the Client ID and Client Secret are saved. OpenFlare validates these fields before enabling the source. - -### Client Secret Saved but Not Displayed in Clear Text - -This is expected behavior. OpenFlare does not echo the Client Secret back via API, displaying only whether the secret is configured. diff --git a/docs/en/guide/troubleshooting.md b/docs/en/guide/troubleshooting.md deleted file mode 100644 index 8975e8be..00000000 --- a/docs/en/guide/troubleshooting.md +++ /dev/null @@ -1,249 +0,0 @@ -# Troubleshooting - -You will learn: How to troubleshoot OpenFlare Server, database, login, Agent, OpenResty, configuration publishing, and frontend build issues by symptoms. - -During troubleshooting, first identify which layer the issue occurs in: browser, Server, database, Agent, OpenResty, origin server, or DNS. OpenFlare configurations are not written directly to nodes online; only after the active version changes will the Agent detect and apply it in heartbeats. - -## Quick Diagnostic - -| Symptom | Where to check first | -| --- | --- | -| Admin panel fails to open | Server container or process logs, port listening | -| Login anomalies | Default credentials, Session Secret, browser request payloads, Server logs | -| Data fails to save | Database connection, SQLite file permissions, PostgreSQL health | -| Agent offline | Agent logs, Token, Server URL, network connectivity | -| Node not updated after publishing | Active version, node heartbeat, application logs | -| OpenResty application failed | Application logs, Agent logs, certificates, upstream addresses, port conflicts | -| Observability analytics has no data | OpenResty container status, observability port, Agent retry logs | - -## Server Fails to Start - -1. View logs: - -```bash -docker compose logs -n 200 openflare -``` - -For source-code execution, inspect terminal outputs. - -2. Check port conflicts: - -```bash -lsof -i :3000 -``` - -3. If using PostgreSQL, verify that the database is healthy: - -```bash -docker compose ps postgres -docker compose logs -n 100 postgres -``` - -4. If using SQLite, verify that the database directory is writable: - -```bash -ls -ld "$(dirname /path/to/openflare.db)" -``` - -Common causes: - -| Log or Symptom | Action | -| --- | --- | -| Database connection failed | Check `DSN` username, password, host, port, dbname, and `sslmode` | -| SQLite fails to create files | Check if the parent directory of `SQLITE_PATH` exists and is writable | -| Port is already in use | Change `PORT` or `--port`, or stop the process binding to the port | - -## Admin Console Fails to Load or Shows Blank Page - -1. Verify that the Server is listening: - -```bash -curl -I http://127.0.0.1:3000 -``` - -2. If running from source, verify that the frontend static assets have been built: - -```bash -cd openflare-server/web -pnpm build -``` - -3. Verify if the browser URL matches your reverse proxy domain. - -4. If accessing via the frontend dev server, verify the backend proxy configuration: - -```bash -cd openflare-server/web -NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev -``` - -## Default Credentials Fail to Log In - -The default credentials are `root` / `123456`. If you have modified the password after your first login, use your new password. - -Troubleshooting Steps: - -1. Confirm that you are connecting to the expected database, avoiding `SQLITE_PATH` or `DSN` pointing to a different environment. -2. Check the Server log to see if it is running on `sqlite` or `postgres`. -3. If deployed in multi-replicas or behind a reverse proxy, verify that `SESSION_SECRET` is static and uniform across all instances. -4. Clear browser Cookies and try logging in again. - -### Emergency Reset of Admin Password - -If you forget the password for the `root` account, you can reset it back to `123456` by directly updating the password hash in the database (please change it immediately after logging in): - -#### 1. If using SQLite Database -Stop the Server and open the database file using the `sqlite3` client: -```bash -sqlite3 /path/to/openflare.db -``` -Execute the following SQL statement: -```sql -UPDATE users SET password_hash = '$2a$10$wN9aE3zTz83rO7R1uKlhuehJtA3c604pX4Z12B/9.5c0X337t1L4m' WHERE username = 'root'; -``` -Type `.exit` to exit and restart the Server. - -#### 2. If using PostgreSQL Database -Connect to your PostgreSQL instance using a database tool (e.g., `psql`, `pgAdmin`, or `DBeaver`), select the corresponding `openflare` database, and execute the following SQL: -```sql -UPDATE users SET password_hash = '$2a$10$wN9aE3zTz83rO7R1uKlhuehJtA3c604pX4Z12B/9.5c0X337t1L4m' WHERE username = 'root'; -``` -Once executed successfully, you can log in using the default password `123456`. - -## Agent Fails to Register or Stays Offline - -Execute on the Agent node: - -```bash -curl -I http://your-server:3000 -``` - -Inspect Agent logs: - -```bash -journalctl -u openflare-agent -n 200 --no-pager -``` - -Verify configuration parameters: - -```bash -sed -n '1,160p' /opt/openflare-agent/agent.json -``` - -Key Settings: - -| Configuration | Description | -| --- | --- | -| `server_url` | Must be the Server address reachable by the Agent node | -| `agent_token` / `discovery_token` | At least one must be provided | -| `heartbeat_interval` | Supports integer milliseconds or Go duration strings | -| `request_timeout` | Can be increased for slower network links | - -If the log warns that the Token is invalid, retrieve a new Token in the management console, update `agent.json`, and restart the Agent: - -```bash -systemctl restart openflare-agent -``` - -## Node Fails to Apply New Version after Publishing - -Verify in sequence: - -1. Confirm that the target version is activated on the Versions page. -2. Verify if the node is online and if its last heartbeat time has updated. -3. Check the Application Logs for successful, warned, or failed logs for the target version. -4. Verify if the website configuration is enabled; disabled websites do not participate in rendering. -5. Inspect Agent logs for pulls, validations, reloads, or rollback events. - -Inspect Agent logs: - -```bash -journalctl -u openflare-agent -f -``` - -Note: If a target `version + checksum` fails to apply and triggers a rollback, the Agent blocks repeated synchronization of that failing target in its local state. You must fix the configuration issues and republish to generate a new checksum, or activate an older version to trigger a rollback. - -If this is the Agent's first time applying configurations and no historic `nginx.conf` exists locally to roll back to, the failed version remains blocked but the Agent will attempt to enter the safe fallback runtime. At this point, the application logs and Agent logs will contain `fallback runtime started`. OpenResty will only listen to port `80`, returning a `503` with the body `OpenFlare: No Valid Configuration`, while retaining the local `/openflare/stub_status` health probe. After correcting the configurations and republishing, the Agent overrides the fallback config and restores normal reverse proxies. - -## OpenResty Application Fails - -Common Causes: - -| Cause | Diagnostic | -| --- | --- | -| Domain or server block conflict | Verify if the same domain is used by multiple website configurations | -| Invalid upstream address | Confirm that all upstreams are valid `http://` or `https://` URLs | -| Mismatched multi-upstream format | Multi-upstreams must be pure `scheme://host[:port]` | -| Missing cert or invalid paths | Verify if domains are bound to certs and check if the Agent cert directory is writable | -| Port already in use | Verify ports `80` and `443` on the host | - -OpenResty Configuration Validation: - -```bash -openresty -t -c /path/to/openflare/data/etc/nginx/nginx.conf -``` - -OpenResty Runtime Status: - -```bash -ps aux | grep openresty -``` - -The Agent determines OpenResty survival periodically using the local endpoint `http://127.0.0.1:/openflare/stub_status`, completely bypassing repeated `openresty -t` calls. If a node is marked as unhealthy, confirm if this local observability port is listening. If failures only occur when applying configurations (e.g., `host not found in upstream`), the failure lies in config validation or reload, not the periodic health checks. - -Actual binary paths and main configuration paths are governed by `openresty_path` and `main_config_path` in `agent.json`. - -## HTTPS Fails to Work - -1. Verify that the certificate has been uploaded or hosted. -2. Verify that the website configuration binds the certificate to the domain. -3. Confirm that the configuration version has been published and activated. -4. Check if the Application Logs indicate a success. -5. Check the certificate chain and status code using `curl`: - -```bash -curl -Iv https://your-domain -``` - -Domains without a bound certificate will not be added to the HTTPS configuration automatically; this is expected behavior. - -## Traffic Analytics Has No Data - -1. Confirm that the node has successfully applied configurations carrying observability Lua scripts. -2. Verify that OpenResty is running. -3. Check Agent logs for observability extraction or upload errors. -4. Check if `openresty_observability_port` (default is `18081`) is bound by other processes. -5. Verify if the Server database has purged data inside the time window. - -## Frontend Build Fails - -Execute: - -```bash -cd openflare-server/web -corepack enable -pnpm install -pnpm lint -pnpm typecheck -pnpm test -pnpm build -``` - -Common causes: - -| Symptom | Action | -| --- | --- | -| pnpm version mismatch | Reinstall packages after executing `corepack enable` | -| TypeScript errors | Locate detailed file bugs by running `pnpm typecheck` | -| API type mismatch | Check responses structures in `lib/api/` and `types/` | -| E2E test failures | Confirm that both the Server and frontend dev server are running | - -## Documentation Build Fails - -```bash -cd docs -pnpm install -pnpm build -``` - -If it fails on broken links, check if new pages are added to the `docs/config.ts` sidebar, or if relative markdown links point to existing markdown files. diff --git a/docs/en/guide/tunnel-usage.md b/docs/en/guide/tunnel-usage.md deleted file mode 100644 index 9a643e37..00000000 --- a/docs/en/guide/tunnel-usage.md +++ /dev/null @@ -1,174 +0,0 @@ -# Tunnel & Intranet Penetration - -You will learn: The design principles of OpenFlare intranet penetration tunnels, core concepts (Relay nodes and Tunnel clients), and how to safely and stably publish your intranet development environment or private cloud services to a public domain name from scratch. - -In many practical development and operations scenarios, our origin servers are deployed in local LANs, local development machines, or heavily guarded private VPCs, having no public IP address and no port mapping (NAT) configured on border firewalls or routers. - -OpenFlare provides an end-to-end solution **based on reverse relay penetration tunnels**. You only need to initiate a secure outbound connection from your intranet environment to the public relay node, without configuring any inbound ports, to smoothly route public web traffic into your intranet origin. At the same time, you benefit from automatic TLS certificate hosting and WAF security protection provided by the gateway. - ---- - -## Core Concepts - -Before using the intranet penetration features, you need to familiarize yourself with the following components and core concepts: - -| Concept | Description | Component / Operation | -| --- | --- | --- | -| **Relay Node (Relay)** | Traffic relay services deployed at the public edge, responsible for listening to intranet client persistent connections, acting as the transit bridge between the gateway Agent (OpenResty) and internal traffic. | Node of type `tunnel_relay` running the `openflare-relay` daemon | -| **Penetration Tunnel (Tunnel)** | Logical penetration client instances having a globally unique ID and secure authentication token, used to identify a specific intranet environment. | Globally unique ID generated by Server `tunnel_id` (format: `tun-<32hex>`) | -| **Tunnel Client (Client)** | A lightweight controller running in the intranet environment, automatically managing the underlying frpc tunnel subprocesses according to the configuration dispatched by the Server. | The `openflared` container or independent binary process deployed in the intranet | -| **Tunnel Upstream (Tunnel Upstream)** | A special upstream type in the website configuration. When this type is selected, the gateway forwards public traffic to the Vhost port of the local relay node, eventually reaching the intranet origin. | Upstream of type `tunnel` configured in the website details | - ---- - -## Recommended Operation Sequence - -To publish an intranet service to the public internet, we recommend doing so in the following order: - -1. Register and deploy at least one public **Relay Node (Relay)** and keep it online. -2. Create a **Penetration Tunnel (Tunnel)** in the management console and copy its dedicated Token. -3. Deploy and start the **Tunnel Client (OpenFlared)** on your intranet server. -4. Confirm that the status of the tunnel in the management console shows as "Online". -5. Add a website configuration, selecting **Intranet Penetration** as the upstream type, binding it to the corresponding tunnel, and entering the intranet port (e.g., `127.0.0.1:8080`). -6. Publish and activate the new version. -7. Access via the public domain to verify that the intranet penetration link is established. - ---- - -## Detailed Configuration Steps - -### Step 1: Prepare the Relay Node (Relay) - -Intranet traffic is routed through public relay nodes. Before starting, ensure you have a public relay server available. - -1. Log into the management console and go to **"Node Management"**. -2. Add a new node, selecting **Relay Node (tunnel_relay)** as the **Node Type**. -3. Save and copy the node-specific `agent_token`. -4. Start the `openflare-relay` process on your public server. You can run it quickly using Docker: - - ```bash - docker run -d --name openflare-relay --restart unless-stopped \ - -p 7000:7000 \ - -e OPENFLARE_SERVER_URL=http://:3000 \ - -e OPENFLARE_AGENT_TOKEN= \ - -v openflare-relay-data:/var/lib/openflare-relay \ - ghcr.io/rain-kl/openflare-relay:latest - ``` - - > [!IMPORTANT] - > Make sure to allow port `7000` (the control port for frpc client connections) in your cloud provider's security group. If your Server and Relay are deployed on the same machine, `OPENFLARE_SERVER_URL` should point to the Server's public or internal IP. - -### Step 2: Create a Penetration Tunnel in the Management Console - -1. Navigate to the **"Intranet Penetration"** section in the side navigation bar. -2. Click the **"Create Tunnel"** button and enter: - * **Tunnel Name**: Describes the intranet environment, e.g., `home-lab` or `office-dev`. - * **Description**: Optional, describes the purpose of this tunnel. -3. Click save, and the system will automatically generate a globally unique ID and a dedicated `tunnel_token` (e.g., `tun-xxxx...`). -4. Copy the **Client Deployment Command** generated in the popup window, which will be used in the next step. - -### Step 3: Deploy the Intranet Client (OpenFlared) - -Return to your intranet server and execute the copied deployment command to run the client. - -#### Option A: Deploy with Docker (Highly Recommended) - -The official `openflared` image embeds the master daemon and `frpc` runtime, working out-of-the-box with no extra dependencies: - -```bash -docker run -d --name openflared --restart unless-stopped \ - -e OPENFLARE_SERVER_URL=http://:3000 \ - -e OPENFLARE_TUNNEL_TOKEN= \ - -v openflared-data:/app/data \ - ghcr.io/rain-kl/openflared:latest -``` - -#### Option B: Host Binary Manual Execution - -If you cannot use Docker, you can download or compile the `flared` binary: - -1. Create a `flared.json` configuration file in the same directory as the executable on your intranet machine: - ```json - { - "server_url": "http://:3000", - "tunnel_token": "", - "frpc_path": "/usr/local/bin/frpc", - "data_dir": "./data" - } - ``` -2. Execute the startup command: - ```bash - ./flared -config ./flared.json - ``` - -#### Verify Online Status - -Once started successfully, the intranet client will send heartbeats through outbound networks to synchronize configurations. At this point: -1. Refresh the **"Intranet Penetration"** list in the management console; the tunnel status indicator should turn green and show **"Online"**. -2. Click tunnel details to view which public Relays the intranet client is currently connected to. - -### Step 4: Create a Website and Bind the Tunnel Upstream - -Now you can configure public reverse proxy and domain routing for your intranet service. - -1. Go to the **"Website Configuration"** page and click **"Create Website"**. -2. Enter the **Domain Name** required to access the service publicly, e.g., `nas.example.com`. -3. Critical Configuration: In the **"Upstream Configuration"** section, switch the **Upstream Type** from "Direct" to **"Intranet Penetration"**. -4. In the dropdown list, select your newly deployed **Intranet Tunnel** (e.g., `home-lab`). -5. Enter the **Intranet Target Address** (the local address and port reachable by the intranet client, e.g., `127.0.0.1:8080`) and select the **Intranet Protocol** (usually `http`). -6. Configure other standard website settings (such as TLS certificates) and click save. - -### Step 5: Publish & Activate - -To allow the gateway's OpenResty instance to match and route domain traffic correctly, we need to publish a new configuration version. - -1. Click **"Preview Config"** in the top right corner of the navigation bar to verify the generated configurations. -2. In the popup window, click **"Publish & Activate"**. -3. Now, the public edge Agent pulls the latest routing, forwarding requests for `nas.example.com` to the loopback virtual host port of `openflare-relay (frps)`. -4. The intranet client `openflared (frpc)` receives the relayed packets, securely hands them over to the local `127.0.0.1:8080` service, and returns responses back through the tunnel. -5. Access `nas.example.com` in your browser to confirm that the intranet service displays successfully! - ---- - -## Advanced Application Scenarios - -### 1. Single-Tunnel Multi-Service Multiplexing (Multi-Port Mapping) - -You do not need to deploy an `openflared` container for every single internal service. - -If you want to map multiple different services in the same intranet environment (e.g., `127.0.0.1:80` for a blog, `127.0.0.1:8080` for an API, and `192.168.1.120:9000` for a local network drive): -1. Keep this single `openflared` client online. -2. Create three independent website configurations in the management console (binding their respective public domains). -3. Set the **Upstream Type** to **the same intranet tunnel** for all three website configurations. -4. Fill in their respective "Intranet Target Addresses" (e.g., `127.0.0.1:80`, `127.0.0.1:8080`, and `192.168.1.120:9000`). -5. Publish and activate the new version to achieve single-tunnel multi-service multiplexing. - -### 2. Seamless Integration with Gateway Security Features - -Since all public traffic enters the public Agent node first, completing the HTTPS/TLS handshake and WAF filtering before traveling through the secure tunnel: - -Your intranet services **naturally benefit from the following advanced features without any code changes**: -* **One-Click HTTPS**: Select or issue SSL certificates directly in the management console, encrypting transmission end-to-end. -* **Global/Custom WAF Protections**: Enables SQL injection blocking, XSS prevention, and regional IP filtering. -* **Human-Machine Challenge (PoW CC)**: Instantly blocks brute-force CC API attacks targeting your intranet services. - ---- - -## Common Troubleshooting - -### 1. Tunnel Shows as "Offline" in the Management Console - -* **Check the Token**: Check if the `tunnel_token` configured in `flared` logs or environment variables matches the one generated in the management console. -* **Check Outbound Connectivity**: The intranet server must be able to make outbound requests to the Server address. Ensure the control plane firewall is not blocking HTTP requests from the client. -* **Relay Firewall Port Closed**: Check if port `7000` (or your custom bindPort) on the public Relay node has been allowed in the public security groups. - -### 2. Accessing the Public Domain Returns 502 Bad Gateway / 504 Gateway Timeout - -* **Intranet Service Not Running**: Verify that the service corresponding to the intranet target address is running and listening on the intranet server. -* **Target Address Unreachable**: If the intranet address is set to `127.0.0.1:8080`, ensure the service is running on the exact same host as `openflared`; if set to a LAN IP `192.168.x.x`, test connectivity to that IP inside the `openflared` container. -* **Check Client Application Logs**: View the "Apply Logs" in the management console or inspect local `flared` logs for any `LastError`. When frpc fails to connect to the intranet port, it reports the failure details to the Server. - -### 3. Multiple Relays Network Instability or Retry Failures - -* When the control plane associates multiple Relay nodes, `openflared` spawns independent frpc daemon processes for each Relay and pulls topology states periodically at `sync_interval` (default 30s) configured in `flared.json`. -* If a Relay drops frequently due to network jitter, the system triggers the backoff retry mechanism automatically. You can see `frpc process missing, starting` logs on the host, which is a normal process self-healing action and will recover within 5-10 seconds after network recovery. diff --git a/docs/en/guide/usage.md b/docs/en/guide/usage.md deleted file mode 100644 index d67e8743..00000000 --- a/docs/en/guide/usage.md +++ /dev/null @@ -1,156 +0,0 @@ -# Basic Usage - -You will learn: What website configurations, origins, certificates, versions, nodes, and observability are in OpenFlare, and the recommended sequence of operations during daily usage. - -OpenFlare does not directly modify Nginx/OpenResty configurations on nodes online. What you modify in the management console is control plane data; only after publishing and activating a new version will the Agent pull the complete configuration and apply it to the nodes. - -## Core Concepts - -| Concept | Description | -| --- | --- | -| Website Config | The aggregate object for reverse proxy rules. One website configuration can bind one or more domains. | -| Primary Domain | The first domain in the `domains` list, used as the main display domain for the website. | -| Origin | The upstream address accessed by the reverse proxy, e.g., `http://10.0.0.10:8080`. | -| Config Version | An immutable snapshot of the complete OpenResty configuration generated upon publishing. | -| Active Version | The globally effective configuration version. All nodes consume the same active version by default. | -| Agent | The node-side process responsible for registration, heartbeats, sync, validation, reloads, and rollbacks on failure. | - -## Recommended Operation Sequence - -When publishing a reverse proxy configuration in daily operations, the following sequence is recommended: - -1. Confirm that at least one Agent node is online. -2. Add or select an origin address. -3. Create a website configuration, entering the domain, origin, and site-level configurations. -4. If HTTPS is required, upload or select a certificate and bind it by domain. -5. Preview the configuration or review the change summary. -6. Publish and activate the new version. -7. Verify the application result in the node details and application logs. - -## Create Website Configuration - -A website configuration requires at least: - -| Field | Requirement | -| --- | --- | -| Website Name | Business unique identifier; the primary domain is usually used if left blank | -| Domain | At least one domain, where the first is the primary domain; any domain can belong to only one website globally | -| Origin Address | A valid `http://` or `https://` address | -| Enabled Status | Only enabled website configurations will participate in publishing and rendering | - -Example: - -| Field | Example | -| --- | --- | -| Website Name | `docs` | -| Domain | `docs.example.com` | -| Origin Address | `http://10.0.0.10:8080` | -| Back-to-source Host | `docs.internal.example.com` | - -Upstream Address Rules: - -* A single upstream can carry a base path or query, e.g., `https://app.example.com/base?from=openflare`. -* When multiple upstreams are used for load balancing, each upstream must be a pure `scheme://host[:port]`. -* Multiple upstreams in the same rule must use the same protocol. - -## Manage Origins - -Origins act as a lightweight directory to reuse common upstream addresses. After a website configuration links with an origin, it still stores a renderable snapshot of the `origin_url`, ensuring that historic configuration versions can be re-rendered and rolled back independently. - -Recommended Practices: - -* Maintain internal service addresses that are frequently reused as Origins. -* After modifying an origin directory, check if published website configurations need their origin snapshots updated. -* Use preview or diff to verify rendering results before publishing. - -## Enable HTTPS - -HTTPS is bound by domain rather than being forced across the entire website. - -Operation Sequence: - -1. Upload or host certificates in the Certificate Management section. -2. Edit the website configuration and select certificates for domains requiring HTTPS. -3. Domains without a bound certificate will remain HTTP and will not be automatically placed in a `443 ssl` server block. -4. Publish and activate the new version. - -If a website contains multiple domains, the Server groups and renders the HTTPS configuration by certificate during publishing while keeping these domains within the same website snapshot. - -## Configure WAF & PoW - -Security protection is centrally accessed via the **WAF** link in the side navigation bar: - -* The WAF page maintains global and custom rule groups. Global rule groups always apply to all websites; custom rule groups can bind websites directly in the group settings or inside the `WAF` section of the website details. -* Clicking **Manage IP Groups** on the WAF page opens the independent IP Groups section. Manual IP groups store IPs/CIDR blocks directly; automatic IP groups evaluate Expr rules against request logs periodically to update members; subscription IP groups periodically sync from remote text or JSON feeds. -* The Auto IP Group page provides two presets: requests count > 100 and 404 ratio >= 80% from a single IP; or IP-host direct access count > 50 and direct access ratio > 50% from a single IP. You can click **Test Rule** to preview IPs matching the log window before saving, and click **Execute Now** to update the group members instantly after saving. The syntax is detailed in [WAF Auto IP Group Expressions](./waf-ip-group-expr.md). -* In the blacklist/whitelist settings of a WAF rule group, you can add IPs/CIDR blocks directly or reference existing IP groups. The published version snapshot only contains referenced IP group IDs; the Agent synchronizes IP group members via checksum differentials and WebSocket real-time broadcasts. -* `PoW` is a configuration Tab in the rule group, located between `Blacklist/Whitelist` and `Block Interception`. It reuses the site's existing PoW execution logic, allowing current PoW parameters to apply to all websites or only those bound to the current rule group. -* The website details page no longer edits individual PoW rules; it only displays the global WAF rule group and binds custom WAF rule groups. The PoW enablement scopes and rule parameters must be maintained centrally on the WAF pages. - -After WAF rule groups, site bindings, or PoW configurations are modified, you must republish and activate the configuration version to let the Agent pull and apply them to OpenResty. IP group member changes do not require a new version publication; online Agents update incrementally via WebSockets, while offline or non-WebSocket Agents synchronize via checksum differentials in the next heartbeat. - -For detailed information on WAF security configurations and evaluation principles, see [WAF Security Protection](./waf-usage.md). - -## Publish, Activate & Rollback - -Standard Pipeline: - -```text -Modify config -> Preview / Diff -> Publish -> Generate complete version -> Activate version -> Agent pulls -> Local application -> Report result -``` - -During publication, the Server reads all enabled website configurations, the main OpenResty config templates, performance and cache parameters, and certificate assets, rendering the complete configuration and calculating its `checksum`. - -Rolling back does not modify historic versions; it simply re-activates an older version. Once the Agent detects a change in the active version, it pulls and applies it following the standard sync flow. - -## View Nodes & Observability - -The Nodes section is designed to answer three questions: - -| Question | Where to check | -| --- | --- | -| Is the node online? | Node List or Node Details | -| Which version is currently running? | Current Version in Node Details | -| Did the most recent application succeed? | Application Logs | - -The node IP is automatically filled by Agent registration and heartbeats by default. If you manually enter or modify the IP in the management console, the node edit page defaults to "Lock Node IP"; when enabled, Agent reports will not override this IP. Disabling the lock restores auto-update logic in the next heartbeat or WebSocket state report. - -Traffic Analytics and Resource Snapshots provide basic observability. OpenFlare only retains access details within a controlled time window, and is not positioned as a general logging platform. If you require long-term log indexing, integrate an independent logging system. - -## Common Scenarios - -### Add a Reverse Proxy for an Internal Service - -1. Verify that the origin service is reachable from the Agent node. -2. Add a website configuration in the management console. -3. Enter the domain, e.g., `app.example.com`. -4. Enter the origin, e.g., `http://10.0.0.20:8080`. -5. Publish and activate the version. -6. Verify the domain on the Agent node or from a browser. - -> [!TIP] -> If your origin server is deployed internally without a public IP and is unreachable by the Agent, use the intranet penetration tunnel feature to map your service. For detailed instructions, see [Tunnel & Intranet Penetration](./tunnel-usage.md). - -### Enable HTTPS for an Existing Domain - -1. Prepare a certificate covering the domain. -2. Upload or create a certificate record in Certificate Management. -3. Edit the website configuration and select the certificate for the domain. -4. Publish and activate the version. -5. Verify the certificate chain and status code in a browser or via `curl -I https://your-domain`. - -### Roll Back a Failed Publication - -1. Open the Configuration Versions page. -2. Locate the last known good version. -3. Re-activate that version. -4. Check the node application logs to verify that the Agent applied the old version. -5. Fix the configuration issues before publishing a new version. - -## Recommended Practices - -* Explicitly configure `SESSION_SECRET` and prefer PostgreSQL in production. -* Review the preview or diff after modifying a website configuration before publishing. -* Check the node details and application logs after every publication. -* Maintain a stable network path from Agent to Server in multi-node deployments. -* Never manually modify OpenResty configurations managed by OpenFlare on the node; these files will be overwritten in the next publication. diff --git a/docs/en/guide/waf-ip-group-expr.md b/docs/en/guide/waf-ip-group-expr.md deleted file mode 100644 index ff8d24cf..00000000 --- a/docs/en/guide/waf-ip-group-expr.md +++ /dev/null @@ -1,161 +0,0 @@ -# WAF Auto IP Group Expressions - -Automatic IP groups are used to aggregate metrics from request logs on a per-client-IP basis, using Expr expressions to determine if an IP should be added to the group. Automatic IP groups can be referenced by IP blacklists or whitelists in WAF rule groups; during publication, the Server only writes the referenced IP group ID to `waf_config.json`, while IP group members are synchronized independently by the Agent into the local runtime files. - -## Configuration Structure - -The configuration of an automatic IP group is a JSON object: - -```json -{ - "lookback_minutes": 60, - "rules": [ - { - "name": "Single IP High-Frequency 404 Scanning", - "expr": "request_count > 100 && status_404_ratio >= 0.8" - } - ] -} -``` - -Field Descriptions: - -| Field | Type | Role | -| --- | --- | --- | -| `lookback_minutes` | number | How many minutes of request logs to look back during execution. Defaults to 60 minutes if blank, minimum 5 minutes, maximum 43200 minutes. | -| `rules` | array | List of automatic rules. If any rule matches, the IP is added to the automatic IP group list. | -| `rules[].name` | string | Rule name, used only for UI display and error messages. | -| `rules[].expr` | string | Expr expression, must return a boolean value. | - -## Evaluation Mechanics - -Automatic rules do not evaluate logs request-by-request, but instead aggregate them by client IP first: - -1. The Server reads request logs from the past `lookback_minutes` minutes. -2. Groups them by normalized IP (`remote_addr`). -3. Computes metrics like request count, 404 count, and direct IP host count for each IP. -4. Evaluates `rules[].expr` for each IP. -5. If an IP matches any rule, it is written to the automatic IP group's IP member list. - -Whether a request is "accessing via IP directly" is determined by the `Host` field in the request logs. If the Host header is an IPv4 or IPv6 literal (e.g., `203.0.113.10`, `[2001:db8::10]`, `203.0.113.10:443`), it is counted in `ip_host_count`. - -## Available Metrics - -The following metrics are directly available in Expr expressions: - -| Keyword | Type | Role | -| --- | --- | --- | -| `ip` | string | The client IP currently being evaluated. | -| `request_count` | number | Total request count of the IP in the lookback window. | -| `status_404_count` | number | Number of 404 responses returned to the IP in the lookback window. | -| `status_404_ratio` | number | 404 request ratio, calculated as `status_404_count / request_count`. | -| `ip_host_count` | number | Number of requests from the IP using an IP address directly as the Host header. | -| `ip_host_ratio` | number | Ratio of direct IP address accesses, calculated as `ip_host_count / request_count`. | -| `client_error_count` | number | Number of requests returning 4xx status codes. | -| `server_error_count` | number | Number of requests returning 5xx status codes. | -| `last_seen_unix` | number | Unix timestamp (in seconds) of the last request from the IP in the lookback window. | - -All ratio fields are decimals between `0` and `1`. An 80% ratio should be written as `0.8`, and 50% as `0.5`. - -## Common Expr Syntax - -Automatic IP groups use the Expr syntax. The expression must return a boolean value. - -Common Operators: - -| Operator | Role | Example | -| --- | --- | --- | -| `>`, `>=`, `<`, `<=` | Numeric comparison | `request_count > 100` | -| `==`, `!=` | Equality / Inequality | `ip != "127.0.0.1"` | -| `&&` | Logical AND | `request_count > 100 && status_404_ratio >= 0.8` | -| `||` | Logical OR | `status_404_ratio >= 0.8 || server_error_count > 20` | -| `!` | Logical NOT | `!(ip == "127.0.0.1")` | -| `in` | Value is in list | `ip in ["203.0.113.10", "198.51.100.20"]` | -| `not in` | Value is not in list | `ip not in ["127.0.0.1"]` | -| `()` | Grouping controls operator priority | `(request_count > 100 && status_404_ratio >= 0.8) || server_error_count > 50` | - -## Built-in Presets - -The management console provides two built-in preset rules that can be added directly and adjusted as needed: - -```json -{ - "name": "Single IP High-Frequency 404 Scanning", - "expr": "request_count > 100 && status_404_ratio >= 0.8" -} -``` - -Meaning: A single IP requests more than 100 times in the lookback window, and the 404 status code ratio is at least 80%. - -```json -{ - "name": "Single IP Direct IP Access Mismatch", - "expr": "ip_host_count > 50 && ip_host_ratio > 0.5" -} -``` - -Meaning: A single IP accesses the server directly using an IP address as the Host header more than 50 times, and this type of access represents more than 50% of its total requests. - -## Examples - -High-frequency 404 scanning: - -```json -{ - "lookback_minutes": 60, - "rules": [ - { - "name": "High-Frequency 404 Scanning", - "expr": "request_count > 100 && status_404_ratio >= 0.8" - } - ] -} -``` - -Direct IP access mismatch: - -```json -{ - "lookback_minutes": 30, - "rules": [ - { - "name": "Direct IP Access Mismatch", - "expr": "ip_host_count > 50 && ip_host_ratio > 0.5" - } - ] -} -``` - -Capture both high 4xx and 5xx errors: - -```json -{ - "lookback_minutes": 120, - "rules": [ - { - "name": "Abnormal Error Rates", - "expr": "(client_error_count > 80 && request_count > 100) || server_error_count > 30" - } - ] -} -``` - -Exclude trusted IPs: - -```json -{ - "lookback_minutes": 60, - "rules": [ - { - "name": "404 Scanning Excluding Trusted IPs", - "expr": "ip not in [\"203.0.113.10\", \"198.51.100.20\"] && request_count > 100 && status_404_ratio >= 0.8" - } - ] -} -``` - -## Usage Recommendations - -Start with a shorter lookback window and higher thresholds to monitor matches, then adjust thresholds gradually. The IP Groups page in the management console allows you to click **"Test Rule"** before saving to view matching IPs in the current window immediately. Once an automatic IP group runs, it overwrites the list of IPs. If you want to permanently whitelist or blacklist certain IPs, add them to a manual IP group instead, and reference both manual and automatic groups in your WAF rule groups. - -Updating automatic IP groups does not require publishing configuration versions. Online Agents receive changes via WebSocket and update the local `waf_ip_groups.json` instantly. If WebSocket is unavailable, the Agent reports its local checksum in heartbeats, and the Server syncs only the mismatched IP groups. diff --git a/docs/en/guide/waf-usage.md b/docs/en/guide/waf-usage.md deleted file mode 100644 index 4fb30dbc..00000000 --- a/docs/en/guide/waf-usage.md +++ /dev/null @@ -1,162 +0,0 @@ -# WAF Security Protection - -You will learn: How the OpenFlare edge Web Application Firewall (WAF) works, its protection dimensions, how to manage and reference the three types of IP groups (Manual, Subscription, and Expr-based Automatic IP groups), configure CC protection challenges (PoW human-machine verification) and regional filtering, and achieve sub-second hot updates of IP group members without Nginx reloads. - ---- - -## Core Concepts - -Before configuring security policies, you need to understand the core components of the WAF: - -| Concept | Description | Scope & Activation Method | -| --- | --- | --- | -| **WAF Rule Group (Rule Group)** | A logical collection of security rules, including: IP whitelists/blacklists (direct input or IP group references), country/region limits, CC protection (PoW), and custom block responses. | Supports global enablement or binding to single/multiple websites. **Modifying rule group definitions requires publishing and activating a configuration version**. | -| **IP Group (IP Group)** | A list container storing individual IPs or CIDR blocks. Divided into **Manual**, **Subscription**, and **Automatic** types. WAF rule groups reference IP groups by ID. | Belongs to dynamic resources. **IP group member updates support sub-second WebSocket hot-syncing, completely bypassing Nginx process reloads**. | -| **PoW Challenge (CC PoW)** | A human-machine verification challenge based on Proof of Work. By prompting browsers to solve hash collisions of a specified difficulty, it silently blocks malicious brute-force scripts and bots while keeping legitimate user experience smooth. | A configuration Tab in the rule group. **Modifying PoW parameters requires publishing and activating a configuration version**. | - ---- - -## Recommended Configuration Sequence - -When configuring security protections for your websites, we recommend doing so in the following order: - -1. Navigate to IP Groups, creating the required **Manual IP Groups** (e.g., developer whitelist) or **Automatic IP Groups** (e.g., auto-blocked IPs based on 404 scans). -2. Create or edit a **WAF Rule Group**: - * Bind the IP groups you want to reference or block. - * Configure regional whitelists/blacklists for countries or provinces. - * (Optional) Configure human-machine challenge parameters in the `PoW` Tab. - * Set custom status codes (e.g., 403, 418) and HTML block pages in the `Block Response` Tab. -3. Associate the rule group with the corresponding **Website Configuration**. -4. Publish and activate the configuration version to let the edge node (Agent) apply the WAF rules to filter traffic. - ---- - -## Detailed Step Guide - -### Step 1: Manage and Configure IP Groups - -IP groups are the foundations of large-scale IP filtering. OpenFlare provides three highly resilient types of IP groups: - -#### 1. Manual IP Groups (Manual) -* **Purpose**: Statically maintain a list of verified trusted IPs or long-term blocked IPs/CIDR blocks. -* **Configuration**: Click "Create IP Group" -> select type "Manual" -> enter IPs or CIDRs line-by-line (e.g., `192.168.1.100` or `10.0.0.0/24`). - -#### 2. Subscription IP Groups (Subscription) -* **Purpose**: Integrate third-party threat intelligence databases or IP ranges published by cloud providers. -* **Configuration**: Select type "Subscription" -> enter fetch URL (supports line-separated plain text or standard JSON formats). A background cron job on the Server periodically pulls the subscription source and updates the group members automatically. - -#### 3. Automatic IP Groups (Automatic) -* **Purpose**: **The most aggressive automated defense channel against scans and brute-force attacks**. -* **Configuration**: Select type "Automatic" -> write Expr log aggregation logic. You can directly select built-in presets: - * **Single IP High-Frequency 404 Scanning**: `request_count > 100 && status_404_ratio >= 0.8` (A single IP requesting over 100 times in the past hour with a 404 response ratio of at least 80%). - * **Single IP Direct IP Access Mismatch**: `ip_host_count > 50 && ip_host_ratio > 0.5` (Bypassing domains to hit the server directly using IP address host headers). -* **Test & Run**: Click **"Test Rule"** before saving to preview IPs matching the current log window. Click **"Execute Now"** after saving to aggregate logs immediately and generate the block list. - -> [!TIP] -> For the detailed syntax and available metrics of automatic IP groups, see [WAF Auto IP Group Expressions](./waf-ip-group-expr.md). - ---- - -### Step 2: Create and Configure a WAF Rule Group - -1. Navigate to the **"WAF"** section in the side menu, and click **"Create Rule Group"**. -2. Enter the rule group name (e.g., `production-api-shield`), and select if it is a "Global Rule Group". -3. Enter rule group details, and configure the tabs sequentially below: - -#### 1. Whitelist / Blacklist Configuration (Allow / Block Lists) -* **Direct IPs**: Enter individual IPs or CIDR blocks line-by-line that need temporary whitelisting or blacklisting directly in the text area. -* **IP Group Reference**: Click "Bind IP Groups", selecting the manual, automatic, or subscription IP groups you configured in Step 1. Whitelists permit traffic instantly, whereas blacklists block it. - -#### 2. Regional Restriction (GeoIP) -* **Description**: OpenFlare integrates GeoIP geolocation resolution. -* **Configuration**: Toggle the regional restriction switch, selecting "Allow Only" or "Block". -* * For example, if your service is only intended for domestic users, set the mode to "Allow Only" and check `China` in the country list. -* * Supports refining to specific provinces/regions, enabling you to block malicious traffic originating from targeted geographic zones with one click. - -#### 3. Human-Machine Challenge Configuration (PoW CC Protection) -* **Description**: Enable CC protection human-machine challenges. When a request triggers the CC protection threshold, the browser renders a silent challenge page, solving a mathematical challenge (hash collision) within several hundred milliseconds. Upon passing, it sets a Cookie and allows subsequent visits. This is seamless to actual users but blocks brute-force scripts and CC tools that do not support JS execution or mathematical computations. -* **Core Parameters**: - * **Status**: Enable / Disable. - * **Hash Difficulty**: Controls the computation difficulty (recommending `4` or `5`). - * **Cookie Expiration**: How long the verification remains valid after passing (e.g., `3600` seconds). - * **Custom Challenge HTML**: Customize the Loading page style of the challenge to match your business design. - -#### 4. Block Response (Block Response) -* **Description**: Define the behavior of the WAF when blocking malicious requests. -* **Configuration**: - * **Block Status Code**: Customize the HTTP status code returned, e.g., the standard `403` or a fun `418 (I'm a teapot)`. - * **Block Response Body**: Input custom HTML content shown to blocked attackers (e.g., "WAF Interception: Your request has been logged"). - ---- - -### Step 3: Associate the Rule Group with Websites - -Once configured, the rule group does not automatically take effect; you need to bind it to specific website configurations. - -* **Option A (Recommended)**: In the **"Bind Websites"** Tab of the rule group details, select the websites you wish to apply this rule group to and save. -* **Option B**: Return to **"Website Configuration"**, edit a specific website, and check and bind the rule group in the "Security Protection" section. - -> [!NOTE] -> If a rule group is marked as **"Global Rule Group (is_global)"**, it applies to **all websites** hosted on the gateway automatically, requiring no manual binding. - ---- - -### Step 4: Publish & Activate Configurations - -1. If you modify **rule group definitions**, **GeoIP scopes**, **PoW CC difficulties**, or **website-to-rule-group bindings**: - * Click **"Preview Config"** -> **"Publish & Activate"** in the top right corner. - * Once the Agent pulls and validates the new version, it rewrites local core OpenResty config files (`waf_config.json`, etc.) and gracefully reloads the processes to apply the policies. -2. If you only update **IP group members** (e.g., adding/deleting an IP in a manual IP group, or an automatic IP group aggregates a new set of blocked IPs periodically): - * **No publication or activation is required!** - * The Server calculates the new MD5 Checksum of the IP group immediately after updating the database. - * The control plane **broadcasts the modified IP group members in real-time to all online Agents via WebSocket**. The Agent overwrites the runtime local disk file `waf_ip_groups.json` incrementally. - * The OpenResty Lua engine calculates the file hash in microseconds when processing new requests. If it detects a Checksum change, it reloads it into the memory dictionary (`ngx.shared`) in real-time. **This entire process requires absolutely no Nginx service reloads, having zero impact on online high-concurrency operations**. - * Even if the WebSocket connection drops, the Agent reports its local Checksum in every heartbeat cycle, and the Server syncs the differential updates to guarantee synchronization. - ---- - -## WAF Evaluation Flow (Filtering Funnel) - -When an external request reaches the OpenResty data plane, the WAF runtime evaluates it in the `access` phase according to the funnel decision chain below. Once a match is made, evaluation terminates: - -```text - Request enters access phase - │ - v - Get all active rule groups bound to this site (Global + Bound Custom groups) - │ - v - 1. Matches IP whitelist / Whitelist IP group? ──────(Yes)─────► [ Allow (ALLOW) ] - │ (No) - v - 2. Matches country / province whitelist? ────────(Yes)─────► [ Allow (ALLOW) ] - │ (No) - v - 3. Matches IP blacklist / Blacklist IP group? ──────(Yes)─────► [ Block (BLOCK) ] ──► Return status & HTML block page - │ (No) - v - 4. Matches country / province blacklist? ────────(Yes)─────► [ Block (BLOCK) ] ──► Return status & HTML block page - │ (No) - v - 5. Is PoW CC protection enabled for this site? - ├───(Yes)───► [ Validate PoW Cookie ] ──(Passed)──► [ Allow (ALLOW) ] - │ │ - │ (Not Passed) - │ v - │ [ Render PoW Challenge ] ──(Solved)──► Set Cookie & Allow - v - 6. No rules triggered, legitimate traffic ─────────────────────► [ Allow (ALLOW) ] -``` - ---- - -## Best Practices & Tuning Recommendations - -* **Whitelist Precedence & Protection**: Before deploying strict blacklists or regional blocks, we strongly recommend creating a "Trusted IP Group" containing your team's office egress IPs, local development IPs, and third-party callback server IPs (e.g., WeChat or Alipay payment callback addresses), and prioritizing it in the rule group's **whitelist**. This effectively prevents accidental blockages. -* **Reasonably Fine-tune PoW Difficulty**: Human-machine CC challenge hash difficulty (`challenge_difficulty`) is a double-edged sword: - * Difficulty `3`: Computes almost instantly, providing low protection. - * Difficulty `4`: Normal phones/low-end browsers solve it in 100-300ms, providing good protection. - * Difficulty `5`: Requires 500ms-2s, providing strong protection but low-end client browsers might perceive slight loading delays. - * Difficulty `6` and above: Computes exponentially slower, easily freezing client browser CPUs. **We strongly recommend choosing `4` or `5` in production**. -* **Utilize "Test Rule"**: For automatic IP groups, always click **"Test Rule"** before saving. By inspecting the list of matching IPs in the current window, verify if your Expr expressions thresholds (such as request counts, 404 ratios, etc.) are too broad or too strict, preventing accidental blockages of legitimate users. -* **Isolate Static & Dynamic Blacklists**: Never enter static malicious IPs that require permanent blocks directly into automatic IP groups (since the aggregated list will be overwritten in the next cron cycle). You should add permanent malicious IPs into a dedicated "Manual Blacklist IP Group" and reference both the manual and automatic groups in your rule groups. diff --git a/docs/en/index.md b/docs/en/index.md deleted file mode 100644 index bf4242ba..00000000 --- a/docs/en/index.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: home - -hero: - name: OpenFlare - text: Open-source CDN Orchestration & Edge Security Platform - tagline: Supports reverse proxy, centralized configuration synchronization, secure intranet penetration (Tunnels), dynamic WAF protection, and anti-CC challenges. - actions: - - theme: brand - text: Quick Start - link: /en/guide/quick-start - - theme: alt - text: Design Boundaries - link: /en/design/ - - theme: alt - text: GitHub - link: https://github.com/Rain-kl/OpenFlare - -features: - - icon: 🛰️ - title: Centralized Config Sync - details: Sync configurations across all nodes in real time via WebSockets and heartbeats with sub-second hot reload. Instantly retrieve alerts and statuses. - - icon: 🌐 - title: Distributed CDN Orchestration - details: Orchestrate scattered and independent OpenResty nodes into a highly collaborative CDN fleet with website-level multi-domain aggregation and load balancing. - - icon: 🚇 - title: Secure Intranet Penetration (Tunnels) - details: An open-source alternative to Cloudflare Tunnels. Expose local intranet services securely to the public network without a public IP or open inbound ports. - - icon: 🛡️ - title: Edge WAF Protection - details: Dynamic WAF rules with differential syncing of IP groups to Lua shared memory without Nginx reloads, plus country-level regional access control. - - icon: 🧩 - title: Anti-CC & Bot Defense (PoW) - details: Built-in high-performance client-side cryptographic Proof of Work challenges (similar to Turnstile) to intercept botnets and scrapers at the edge. ---- diff --git a/docs/en/reference/api.md b/docs/en/reference/api.md deleted file mode 100644 index fcdb556d..00000000 --- a/docs/en/reference/api.md +++ /dev/null @@ -1,155 +0,0 @@ -# API Conventions - -You will learn: The response structure, path conventions, authentication methods, and Swagger entrance for the OpenFlare Admin API and Agent API. - -Both the OpenFlare Admin API and Agent API communicate using JSON. - -## Response Structure - -Both successful and failed API responses must return a clear `message`: - -```json -{ - "success": true, - "message": "", - "data": {} -} -``` - -## Path Conventions - -| Category | Convention | -| --- | --- | -| Admin API | Authenticated via the Admin Session | -| Agent API | Located strictly under `/api/agent/*` | -| Relay API | Located strictly under `/api/relay/*`, authenticated via `X-Agent-Token` (reusing the Agent's token) | -| OpenFlared API | Located strictly under `/api/flared/*`, authenticated via `X-Tunnel-Token` (dedicated tunnel_token) | -| Read-only APIs | Use the `GET` method | -| Mutating APIs | Use the `POST` method | - -## WAF IP Group APIs - -The Admin WAF IP Group APIs require Admin Session authentication: - -| Method | Path | Description | -| --- | --- | --- | -| `GET` | `/api/waf/ip-groups` | Query IP groups list | -| `GET` | `/api/waf/ip-groups/:id` | Query a single IP group | -| `POST` | `/api/waf/ip-groups` | Create a new IP group | -| `POST` | `/api/waf/ip-groups/test` | Test automatic IP group Expr rules; returns matching IPs in the lookback window without persisting the config | -| `POST` | `/api/waf/ip-groups/:id/update` | Update an existing IP group | -| `POST` | `/api/waf/ip-groups/:id/delete` | Delete an IP group; denied if currently referenced by any rule group | -| `POST` | `/api/waf/ip-groups/:id/sync` | Manually sync subscription IP groups or execute automatic IP group aggregation | - -The IP group `type` supports `manual`, `automatic`, and `subscription`. The `auto_config` parameter for automatic IP groups is a JSON object: - -```json -{ - "lookback_minutes": 60, - "rules": [ - { - "name": "Single IP High-Frequency 404 Scanning", - "expr": "request_count > 100 && status_404_ratio >= 0.8" - }, - { - "name": "Single IP Direct IP Access Mismatch", - "expr": "ip_host_count > 50 && ip_host_ratio > 0.5" - } - ] -} -``` - -Automatic rules evaluate Expr boolean expressions against metrics aggregated on a per-client-IP basis. The available metrics include `ip`, `request_count`, `status_404_count`, `status_404_ratio`, `ip_host_count`, `ip_host_ratio`, `client_error_count`, `server_error_count`, and `last_seen_unix`. The full syntax is detailed in [WAF Auto IP Group Expressions](../guide/waf-ip-group-expr.md). - -Subscription formats support `text` and `json`: plain text parsing resolves one IP or CIDR per line, ignoring empty lines and comments starting with `#`; JSON parsing decodes arrays, reading the root array by default. - -## Authentication - -The Admin panel continues to reuse the existing login, role, and Session validation. - -Agent requests must carry the node-specific `agent_token` (except for first-time registration, which can use the global `discovery_token`). The header is formatted as: - -```http -X-Agent-Token: -``` - -### Agent WAF IP Group Synchronization - -The Agent heartbeat payload can carry local WAF IP group checksums: - -```json -{ - "waf_ip_group_checksums": { - "1": "sha256..." - } -} -``` - -The Server evaluates the checksums against active configurations, returning mismatched IP groups in the heartbeat response: - -```json -{ - "waf_ip_groups": [ - { - "id": 1, - "name": "Auto Blacklist", - "type": "automatic", - "enabled": true, - "ip_list": ["203.0.113.10"], - "checksum": "sha256..." - } - ] -} -``` - -Alternatively, the Agent can proactively request differential updates upon applying a new configuration version: - -| Method | Path | Description | -| --- | --- | --- | -| `POST` | `/api/agent/waf/ip-groups/sync` | Returns mismatched WAF IP groups based on Agent-supplied `ids` and `checksums` | - -When an IP group is updated on the Server, connected Agents receive a WebSocket push containing `type = "waf_ip_groups"` with the changed IP groups array as payload. The Agent updates only the changed groups incrementally. - -## OpenFlared API - -The OpenFlared client communicates with the Server via a dedicated `tunnel_token`, completely decoupled from the Agent authentication system. All endpoints require `X-Tunnel-Token` authentication; requests are denied with `403` if the token is invalid. - -| Method | Path | Description | -| --- | --- | --- | -| `POST` | `/api/flared/heartbeat` | Client heartbeat, updates online status and retrieves active tunnel config version summaries | -| `GET` | `/api/flared/config/active` | Pulls the complete tunnel routing configuration (relay list + frpc proxy definitions) | -| `POST` | `/api/flared/apply-log` | Reports configuration application results (success / warning / failed) | -| `GET` | `/api/flared/ws` | Upgrades to a WebSocket connection for real-time `active_config` pushes | - -Heartbeat request example: - -```http -POST /api/flared/heartbeat -X-Tunnel-Token: -Content-Type: application/json - -{ - "client_version": "v0.2.0", - "frp_version": "0.61.0", - "tunnel_status": "running", - "connected_relays": [ - { "relay_node_id": "node-relay-1", "status": "healthy", "proxy_count": 3 } - ], - "current_version": "v1", - "current_checksum": "sha256..." -} -``` - -The heartbeat response returns the `active_config` summary and `tunnel_settings` (containing runtime settings like heartbeat intervals and WebSocket upgrade switches). When a new configuration version is published, the Server broadcasts a message `type = "active_config"` with the version summary as payload to all connected Clients over WebSockets, prompting them to fetch and apply the config immediately. - -Full tokens must never be logged. - -## Swagger - -Once logged into the management console, the Swagger page is accessible at: - -```text -/swagger/index.html -``` - -The Swagger definition file is stored in `openflare-server/docs`, generated by `swag init`. diff --git a/docs/en/reference/cli.md b/docs/en/reference/cli.md deleted file mode 100644 index 1e468631..00000000 --- a/docs/en/reference/cli.md +++ /dev/null @@ -1,149 +0,0 @@ -# CLI Commands - -You will learn: Common commands for starting, building, testing, installing, and uninstalling the OpenFlare Server, Admin Frontend, Agent, Swagger, and Documentation site. - -## Server - -Start from source: - -```bash -cd openflare-server -export SESSION_SECRET='replace-with-random-string' -export SQLITE_PATH='./openflare.db' -export LOG_LEVEL='info' -go run . -``` - -Specify listening port and logging directory: - -```bash -go run . --port 3000 --log-dir ./logs -``` - -Run tests: - -```bash -cd openflare-server -GOCACHE=/tmp/openflare-go-cache go test ./... -``` - -## Frontend - -Development: - -```bash -cd openflare-server/web -pnpm install -pnpm dev -``` - -Build static assets: - -```bash -cd openflare-server/web -pnpm build -``` - -Linting and testing checks: - -```bash -cd openflare-server/web -pnpm lint -pnpm typecheck -pnpm test -``` - -## Agent - -Run from source: - -```bash -cd openflare-agent -go run ./cmd/agent -config /path/to/agent.json -``` - -Compile: - -```bash -cd openflare-agent -go build -o openflare-agent ./cmd/agent -``` - -Run tests: - -```bash -cd openflare-agent -GOCACHE=/tmp/openflare-go-cache go test ./... -``` - -## Relay (Server-side) - -Run from source: - -```bash -cd openflare-relay -go run ./cmd -config /path/to/relay.json -``` - -Compile: - -```bash -cd openflare-relay -go build -o openflare-relay ./cmd -``` - -## OpenFlared (Client-side) - -Run from source: - -```bash -cd openflared -go run ./cmd -config /path/to/flared.json -``` - -Compile: - -```bash -cd openflared -go build -o openflared ./cmd -``` - -## Install Agent - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \ - --server-url http://your-server:3000 \ - --agent-token YOUR_AGENT_TOKEN -``` - -## Uninstall Agent - -```bash -curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash -``` - -## Swagger - -Regenerate Swagger documentation: - -```bash -go install github.com/swaggo/swag/cmd/swag@v1.16.4 -cd openflare-server -swag init -g main.go -o docs -``` - -## Docs - -Local preview: - -```bash -cd docs -pnpm dev -``` - -Build: - -```bash -cd docs -pnpm build -``` diff --git a/docs/en/reference/configuration.md b/docs/en/reference/configuration.md deleted file mode 100644 index 4282cc33..00000000 --- a/docs/en/reference/configuration.md +++ /dev/null @@ -1,370 +0,0 @@ -# Configuration Options - -You will learn: What configuration sources are supported by OpenFlare Server, frontend builds, and Agents; what the default configuration values are; and how to configure common deployment combinations. - -This document aggregates the currently supported configuration options for OpenFlare Server and Agent in version `1.0.0`, keeping only running parameters that are currently active. - -## Configuration Sources - -The Server supports three types of configuration sources: - -1. CLI arguments. -2. Environment variables. -3. Runtime configurations in the database `options` table. - -The Agent supports: - -1. The `-config` CLI argument. -2. The `agent.json` configuration file. -3. A small set of environment variables for overriding logs and settings. - -The Relay (Server-side) supports: - -1. The `-config` CLI argument. -2. The `relay.json` configuration file. -3. Persistent environment variables for overriding runtime flags. - -The Client (Intranet Client) supports: - -1. The `-config` CLI argument. -2. The `flared.json` configuration file. -3. Startup overrides and logging environment variables. - -## Configuration File Locations - -| Component | Default Location | Description | -| --- | --- | --- | -| Server SQLite | `openflare.db` | Can be customized via `SQLITE_PATH` | -| Agent Config | `./agent.json` | Can be specified via `-config` | -| One-Click Agent | `/opt/openflare-agent/agent.json` | Generated by the installation script by default | -| Agent Data Dir | `data` in the config folder | Can be customized via `data_dir` | -| Relay Config | `./relay.json` | Can be specified via `-config` | -| One-Click Relay | `/opt/openflare-relay/relay.json` | Generated by the installation script by default | -| Client Config | `./flared.json` | Can be specified via `-config` | -| One-Click Client | `/opt/openflared/flared.json` | Generated by the installation script by default | - -## Server CLI Arguments - -```bash -cd openflare-server -go run . --port 3000 --log-dir ./logs -``` - -| Argument | Description | Default Value | -| --- | --- | --- | -| `--port` | Port the Server listens on | `3000` | -| `--log-dir` | Directory to output logs | Empty (stdout) | -| `--version` | Outputs current version and exits | `false` | -| `--help` | Outputs help information and exits | `false` | - -## Server Environment Variables - -| Environment Variable | Description | Default Value | -| --- | --- | --- | -| `PORT` | Port the Server listens on | `3000` | -| `GIN_MODE` | Gin framework running mode | Defaults to release unless `debug` | -| `LOG_LEVEL` | Logging level | `info` | -| `SESSION_SECRET` | Session signing key | Randomly generated on startup | -| `SQLITE_PATH` | SQLite database file path | `openflare.db` | -| `DSN` | PostgreSQL DSN (takes precedence over SQLite) | Empty | -| `SQL_DSN` | Legacy PostgreSQL DSN (lower priority than `DSN`) | Empty | -| `REDIS_CONN_STRING` | Redis connection string | Empty | -| `AGENT_TOKEN` | Legacy global Agent Token | Empty | - -Notes: - -* If both `DSN` and `SQL_DSN` exist, `DSN` is prioritized. -* If either `DSN` or `SQL_DSN` coexist with `SQLITE_PATH`, PostgreSQL is prioritized. -* If the target PostgreSQL database is empty and a local SQLite file exists at `SQLITE_PATH`, the Server automatically migrates SQLite data table-by-table on startup. -* `SESSION_SECRET` must be explicitly configured in production. -* If `REDIS_CONN_STRING` is unconfigured, co-located features fall back to in-memory implementations. - -## Runtime Options - -The following options are maintained in the admin settings page and support hot reloading: - -| Parameter | Description | Default Value | -| --- | --- | --- | -| `AgentHeartbeatInterval` | Heartbeat interval for Agents (ms) | `10000` | -| `AgentWebsocketUpgradeEnabled` | Toggles WebSocket upgrades after successful HTTP heartbeat | `true` | -| `NodeOfflineThreshold` | Threshold duration to mark a node offline (ms) | `120000` | -| `AgentUpdateRepo` | GitHub repository for Agent self-updates | `Rain-kl/OpenFlare` | -| `GeoIPProvider` | Geolocation resolution provider | `ipinfo` | -| `DatabaseAutoCleanupEnabled` | Toggles daily automatic cleanup of observability logs | `false` | -| `DatabaseAutoCleanupRetentionDays` | Data retention duration in days, minimum 1 day | `30` | -| `GlobalApiRateLimitNum` / `GlobalApiRateLimitDuration` | Global API rate limit count / window | `300` / `180` | -| `GlobalWebRateLimitNum` / `GlobalWebRateLimitDuration` | Global Web rate limit count / window | `300` / `180` | -| `CriticalRateLimitNum` / `CriticalRateLimitDuration` | Sensitive API rate limit count / window | `100` / `1200` | - -Notes: - -* When `DatabaseAutoCleanupEnabled` is enabled, the Server deletes `node_access_logs`, `node_metric_snapshots`, and `node_request_reports` daily at 3:00 AM. -* `DatabaseAutoCleanupRetentionDays` must be greater than or equal to 1. -* Leaving retention days blank during a manual trigger in the console deletes all historic logs instantly. -* The GitHub Release in `AgentUpdateRepo` must contain a matching `.sha256` checksum file for every Agent binary (e.g., `openflare-agent-linux-amd64.sha256`); the Agent validates this checksum before replacing the local executable. -* Third-party logins no longer use `GitHubOAuthEnabled`, `GitHubClientId`, and `GitHubClientSecret` as main configuration entrypoints; these legacy options are used only for migrating default GitHub credentials during upgrades. -* The legacy WeChat login options are kept for backward compatibility, but the option page no longer edits them. -* Legacy Cloudflare Turnstile options and validation logic are retained and will work normally. - -## OpenResty Parameters - -OpenResty performance and caching parameters are managed in the `options` table, including: - -* `OpenRestyWorkerProcesses` -* `OpenRestyWorkerConnections` -* `OpenRestyWorkerRlimitNofile` -* `OpenRestyKeepaliveTimeout` -* `OpenRestyProxyConnectTimeout` -* `OpenRestyProxySendTimeout` -* `OpenRestyProxyReadTimeout` -* `OpenRestyProxyBufferingEnabled` -* `OpenRestyGzipEnabled` -* `OpenRestyCacheEnabled` -* `OpenRestyCachePath` -* `OpenRestyCacheMaxSize` - -These parameters must be validated, saved, and rendered structurally. - -Constraints: - -* The console no longer exposes `resolver` settings. -* Upstreams are rendered uniformly as named `upstream` blocks with keepalive enabled. -* Single upstreams carrying a base path or query have their URI correctly appended in `proxy_pass`. -* Multi-upstreams must be pure `scheme://host[:port]` using the same protocol within a single rule. -* `OpenRestyCacheEnabled` enables cache infrastructure and global defaults; the actual caching matching policies (by URL, suffix, or path) are configured per `proxy_routes`. -* The default cache key is `$scheme$host$request_uri`. -* Default `keepalive_timeout` is `20` seconds; default `proxy_connect_timeout` is `3` seconds. -* The default event model is `epoll` with `multi_accept` enabled. -* HTTPS listeners use the independent `http2 on;` directive to avoid deprecation warnings for `listen ... http2` in newer Nginx/OpenResty versions. - -## Frontend Build Environment Variables - -| Environment Variable | Description | Default Value | -| --- | --- | --- | -| `NEXT_PUBLIC_API_BASE_URL` | Base path for frontend API calls | `/api` | -| `NEXT_PUBLIC_APP_VERSION` | Application version shown in the UI | `dev` | -| `NEXT_DEV_BACKEND_URL` | Target backend proxied by the local dev server | `http://127.0.0.1:3000` | - -## Agent Environment Variables - -| Environment Variable | Description | Default Value | -| --- | --- | --- | -| `LOG_LEVEL` | Logging level for the Agent | `info` | -| `OPENFLARE_SERVER_URL` | Server URL; overrides `agent.json` | Empty | -| `OPENFLARE_AGENT_TOKEN` | Node-specific Token; overrides `agent.json` | Empty | -| `OPENFLARE_DISCOVERY_TOKEN` | Auto-registration Token; overrides `agent.json` | Empty | -| `OPENFLARE_NODE_NAME` | Node name; overrides `agent.json` | Empty | -| `OPENFLARE_NODE_IP` | Node IP; overrides `agent.json` | Empty | -| `OPENFLARE_DATA_DIR` | Agent data directory; overrides `agent.json` | Empty | -| `OPENFLARE_OPENRESTY_PATH` | Path to OpenResty binary; overrides `agent.json` | Empty | -| `OPENFLARE_HEARTBEAT_INTERVAL` | Heartbeat interval; overrides `agent.json` | Empty | -| `OPENFLARE_REQUEST_TIMEOUT` | Request timeout; overrides `agent.json` | Empty | -| `OPENFLARE_OPENRESTY_OBSERVABILITY_PORT` | Local observability port; overrides `agent.json` | Empty | -| `OPENFLARE_MMDB_PATH` | WAF GeoIP mmdb path; overrides `agent.json` | Empty | -| `OPENFLARE_MMDB_UPDATE_INTERVAL` | GeoIP mmdb update interval; overrides `agent.json` | Empty | -| `OPENFLARE_MMDB_DOWNLOAD_URL` | GeoIP mmdb download link; overrides `agent.json` | Empty | - -## Agent CLI Arguments - -| Argument | Description | Default Value | -| --- | --- | --- | -| `-config` | Path to the Agent configuration file | `./agent.json` | - -## Agent Configurations Fields - -| Field | Description | Required | Default Value / Behavior | -| --- | --- | --- | --- | -| `server_url` | Control plane URL | Yes | None | -| `agent_token` | Node-specific access Token | Mutually exclusive with discovery_token | Empty | -| `discovery_token` | Global auto-registration Token | Mutually exclusive with agent_token | Empty | -| `node_name` | Node name | No | Hostname | -| `node_ip` | Node IP | No | Auto-detect, resolves outbound public IP via realip.cc first, falls back to local adapters | -| `openresty_path` | Path to the OpenResty binary | No | `"openresty"` | -| `openresty_observability_port` | Observability port for health checks | No | `18081` | -| `data_dir` | Agent data directory | No | `data` in the config folder | -| `main_config_path` | Write path for Nginx main configuration | No | `data_dir/etc/nginx/nginx.conf` | -| `route_config_path` | Write path for route configurations | No | `data_dir/etc/nginx/conf.d/openflare_routes.conf` | -| `access_log_path` | Write path for OpenResty access logs | No | `data_dir/var/log/openflare/access.log` | -| `cert_dir` | Write directory for SSL certificates | No | `data_dir/etc/nginx/certs` | -| `openresty_cert_dir` | Read directory for certificates in Nginx | No | Same as `cert_dir` | -| `lua_dir` | Write directory for Lua scripts and assets | No | `data_dir/etc/nginx/lua` | -| `openresty_lua_dir` | Read directory for Lua scripts in Nginx | No | Same as `lua_dir` | -| `runtime_config_dir` | Write directory for Agent runtime configs | No | `data_dir/etc/openflare` | -| `mmdb_path` | WAF GeoIP database file path | No | `data_dir/etc/openflare/GeoLite2-Country.mmdb` | -| `mmdb_update_interval` | WAF GeoIP database check interval | No | `86400000` milliseconds | -| `mmdb_download_url` | WAF GeoIP database download URL | No | Built-in GeoLite2 Country URL | -| `observability_buffer_path` | Buffer path for retry metrics logs | No | `data_dir/var/lib/openflare/observability-buffer.json` | -| `observability_replay_minutes` | Lookback window for metric retries | No | `15` | -| `state_path` | Path to store local state JSON file | No | `data_dir/var/lib/openflare/agent-state.json` | -| `heartbeat_interval` | Heartbeat polling interval | No | `10000` milliseconds | -| `request_timeout` | HTTP request timeout duration | No | `10000` milliseconds | - -Notes: - -* `agent_token` and `discovery_token` cannot both be empty. -* `heartbeat_interval` and `request_timeout` support integer milliseconds or Go duration strings. -* If `AgentWebsocketUpgradeEnabled` is enabled on the Server, the Agent upgrades the HTTP heartbeat to WebSocket; it automatically falls back to HTTP heartbeats if it fails or disconnects. -* If `openresty_path` is left blank, the Agent calls `openresty` on the host. -* Periodic health checks query `http://127.0.0.1:/openflare/stub_status` instead of executing `openresty -t`; validation prior to reloads, starts, or rollbacks still runs `openresty -t -c `. -* The Agent initializes and periodically updates `mmdb_path` to support GeoIP region checks; failures to update write warnings and do not disrupt configuration synchronizations. -* The Agent boots normally if `agent.json` is missing but environment variables (`OPENFLARE_SERVER_URL` and a Token) are available; environment variables override JSON settings. -* If `node_ip` is left blank, the Agent resolves its outbound IP via `https://realip.cc` first, which is suitable for Docker/NAT networks. -* If the Agent registers a private `node_ip`, the Server prioritizes saving the public TCP connection IP, preventing NAT adapters from registering internal IPs. -* Enabling "Lock Node IP" in the console retains the manual IP; subsequent Agent registration or heartbeats do not overwrite it. - -## Relay Environment Variables - -| Environment Variable | Description | Default Value | -| --- | --- | --- | -| `LOG_LEVEL` | Logging level for the Relay | `info` | -| `OPENFLARE_SERVER_URL` | Server URL; overrides `relay.json` | Empty | -| `OPENFLARE_AGENT_TOKEN` | Node-specific Token; overrides `relay.json` | Empty | -| `OPENFLARE_DISCOVERY_TOKEN` | Auto-registration Token; overrides `relay.json` | Empty | -| `OPENFLARE_NODE_NAME` | Node name; overrides `relay.json` | Empty | -| `OPENFLARE_NODE_IP` | Node IP; overrides `relay.json` | Empty | -| `OPENFLARE_DATA_DIR` | Relay data directory; overrides `relay.json` | Empty | -| `OPENFLARE_FRPS_PATH` | frps binary path; overrides `relay.json` | Empty | - -## Relay CLI Arguments - -| Argument | Description | Default Value | -| --- | --- | --- | -| `-config` | Path to the Relay configuration file | `./relay.json` | - -## Relay Configuration Fields - -| Field | Description | Required | Default Value / Behavior | -| --- | --- | --- | --- | -| `server_url` | Control plane URL | Yes | None | -| `agent_token` | Node-specific access Token | Mutually exclusive with discovery_token | Empty | -| `discovery_token` | Global auto-registration Token | Mutually exclusive with agent_token | Empty | -| `node_name` | Node name | No | Hostname | -| `node_ip` | Relay listening IP for tunnel traffic | No | Auto-detect, prioritizes outbound public IP | -| `frps_path` | Path to the `frps` binary | No | `frps` (system PATH) | -| `data_dir` | Relay runtime data directory | No | `data` in the config folder | -| `state_path` | Path to store local state JSON file | No | `data_dir/relay-state.json` | -| `heartbeat_interval` | Heartbeat polling interval | No | `10000` milliseconds, supports Go duration strings | -| `request_timeout` | HTTP request timeout duration | No | `10000` milliseconds, supports Go duration strings | - -## OpenFlared (Client) Environment Variables - -| Environment Variable | Description | Default Value | -| --- | --- | --- | -| `LOG_LEVEL` | Logging level for the client | `info` | -| `OPENFLARE_SERVER_URL` | Server URL; overrides `flared.json` | Empty | -| `OPENFLARE_TUNNEL_TOKEN` | Tunnel access Token; overrides `flared.json` | Empty | -| `OPENFLARE_DATA_DIR` | Client data directory; overrides `flared.json` | Empty | -| `OPENFLARE_FRPC_PATH` | frpc binary path; overrides `flared.json` | Empty | - -## OpenFlared (Client) CLI Arguments - -| Argument | Description | Default Value | -| --- | --- | --- | -| `-config` | Path to the client configuration file | `./flared.json` | - -## OpenFlared (Client) Configuration Fields - -| Field | Description | Required | Default Value / Behavior | -| --- | --- | --- | --- | -| `server_url` | Control plane URL | Yes | None | -| `tunnel_token` | Tunnel dedicated access Token | Yes | None | -| `frpc_path` | Path to the `frpc` binary | No | `frpc` (system PATH) | -| `data_dir` | Client runtime data directory | No | `data` in the config folder | -| `state_path` | Path to store local state JSON file | No | `data_dir/flared-state.json` | -| `heartbeat_interval` | Heartbeat polling interval | No | `10000` milliseconds, supports Go duration strings | -| `sync_interval` | Configuration sync interval | No | `30000` milliseconds, supports Go duration strings | -| `request_timeout` | HTTP request timeout duration | No | `10000` milliseconds, supports Go duration strings | - -## Common Configuration Combos - -### Production Server + PostgreSQL - -```bash -export SESSION_SECRET='replace-with-a-long-random-string' -export DSN='postgres://openflare:replace-with-strong-password@postgres:5432/openflare?sslmode=disable' -export GIN_MODE='release' -export LOG_LEVEL='info' -``` - -### Local Server + SQLite - -```bash -export SESSION_SECRET='dev-session-secret' -export SQLITE_PATH='./openflare-dev.db' -export LOG_LEVEL='debug' -go run . -``` - -### Agent + Default OpenResty - -```json -{ - "server_url": "http://your-server:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "/opt/openflare-agent/data", - "openresty_path": "openresty", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -### Agent + Customized OpenResty Paths - -```json -{ - "server_url": "http://your-server:3000", - "agent_token": "replace-with-node-auth-token", - "data_dir": "/var/lib/openflare-agent", - "openresty_path": "/usr/local/openresty/nginx/sbin/openresty", - "main_config_path": "/var/lib/openflare-agent/etc/nginx/nginx.conf", - "route_config_path": "/var/lib/openflare-agent/etc/nginx/conf.d/openflare_routes.conf", - "access_log_path": "/var/lib/openflare-agent/var/log/openflare/access.log", - "cert_dir": "/var/lib/openflare-agent/etc/nginx/certs", - "lua_dir": "/var/lib/openflare-agent/etc/nginx/lua", - "runtime_config_dir": "/var/lib/openflare-agent/etc/openflare", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -### Relay (Server-side) Default Configuration - -`relay.json`: - -```json -{ - "server_url": "http://your-server:3000", - "agent_token": "replace-with-relay-auth-token", - "frps_path": "frps", - "data_dir": "/opt/openflare-relay/data", - "heartbeat_interval": 10000, - "request_timeout": 10000 -} -``` - -### OpenFlared (Client-side) Default Configuration - -`flared.json`: - -```json -{ - "server_url": "http://your-server:3000", - "tunnel_token": "replace-with-tunnel-token", - "frpc_path": "frpc", - "data_dir": "/opt/openflared/data", - "heartbeat_interval": 10000, - "sync_interval": 30000, - "request_timeout": 10000 -} -``` - -## Maintenance Rules - -This document must be updated in sync when any of the following change: - -* Server CLI arguments. -* Server environment variables. -* Agent CLI arguments and configuration parameters. -* Relay CLI arguments and configuration parameters. -* Client CLI arguments and configuration parameters. -* Default values, scopes, or examples of any configuration items. diff --git a/docs/en/reference/index.md b/docs/en/reference/index.md deleted file mode 100644 index 009679cc..00000000 --- a/docs/en/reference/index.md +++ /dev/null @@ -1,13 +0,0 @@ -# Reference Manuals - -You will learn: Which information belongs to stable reference manuals, and where to look up configurations, commands, APIs, and repository structures. - -This section collects stable information at the runtime, API, and repository layers, suitable for rapid lookup during deployment, integration, and troubleshooting. - -| Page | Content | -| --- | --- | -| [Configuration Options](./configuration.md) | Server environment variables, CLI arguments, runtime Options, and Agent configuration parameters | -| [CLI Commands](./cli.md) | Common CLI commands for starting, building, testing, installing, and uninstalling | -| [API Conventions](./api.md) | Response structures, authentication, and routing paths for Admin and Agent APIs | -| [Repository Structure](../design/repository.md) | Scope of responsibilities and folder layering of the Server, Agent, Relay, and Client | -| [Deployment & Upgrade](../deployment/) | Server and Agent deployment, configuration, and upgrade guides (dedicated section) | diff --git a/docs/guide/index.md b/docs/guide/index.md index f9f73f8e..dc513306 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -36,7 +36,6 @@ OpenFlare 是一套自托管的 OpenResty 控制面。它把反向代理网站 | 从源码启动 Server | [启动 Server](../deployment/server.md) | | 配置 GitHub 或 OIDC 登录 | [SSO 登录配置](./sso.md) | | 升级 Server 或 Agent | [升级与维护](../deployment/upgrade.md) | -| 参与开发或修复问题 | [启动 Server](../deployment/server.md) 与 [开发约束](../guideline/Constraints.md) | | 理解架构和发布模型 | [系统架构](../design/architecture.md) 与 [Agent 与发布模型](../design/agent-design.md) | | 查看开源引用与致谢 | [引用与致谢](./credits.md) | diff --git a/docs/plan/20260618-openflare-wavelet-backend-migration.md b/docs/plan/20260618-openflare-wavelet-backend-migration.md index 70c0eeac..514a2be9 100644 --- a/docs/plan/20260618-openflare-wavelet-backend-migration.md +++ b/docs/plan/20260618-openflare-wavelet-backend-migration.md @@ -3,7 +3,6 @@ > **文档类型**:实现计划(Implementation Plan) > **创建日期**:2026-06-18 > **状态**:实施中(阶段 5 收尾;控制台 `/api/v1/d/*` + 新前端已落地,legacy 兼容层已撤销) -> **前置阅读**:[`Wavelet/AGENTS.md`](../../Wavelet/AGENTS.md)、[`docs/guideline/Constraints.md`](../guideline/Constraints.md)、[`docs/design/architecture.md`](../design/architecture.md) --- @@ -822,12 +821,3 @@ curl http://127.0.0.1:3000/api/agent/config-versions/active \ | M6 生产就绪 | 第 12 周 | 迁移脚本 + 部署文档 + Handover | --- - -## 14. 参考文档 - -- [`Wavelet/AGENTS.md`](../../Wavelet/AGENTS.md) -- [`docs/design/architecture.md`](../design/architecture.md) -- [`docs/design/agent-design.md`](../design/agent-design.md) -- [`docs/guideline/Constraints.md`](../guideline/Constraints.md) -- 旧后端源码:`openflare-server/internal/` -- 子智能体分析报告:本计划编制依据(2026-06-18) \ No newline at end of file diff --git a/docs/plan/handover-docs-restructure-update.md b/docs/plan/handover-docs-restructure-update.md new file mode 100644 index 00000000..d90f214a --- /dev/null +++ b/docs/plan/handover-docs-restructure-update.md @@ -0,0 +1,53 @@ +# 文档更新 — AI 接手文档 + +> **状态**:已完成(2026-06-19) +> **背景**:`openflare-server/` 子目录已删除,项目收敛为 monorepo;后端迁移至 Wavelet 框架,前端迁移至 `frontend/` +> **触发**:多智能体并行分析后批量更新文档 + +--- + +## 1. 分析结论摘要 + +| 维度 | 主要变化 | +| --- | --- | +| 仓库形态 | 单 monorepo(`github.com/Rain-kl/Wavelet`),无 `openflare-server/` 子目录 | +| Server 入口 | `main.go` + `internal/cmd/`,非 `cmd/server/` | +| 后端分层 | `internal/apps/*/routers.go` + `logics.go`,非 `controller/service` | +| 管理 API | `/api/v1/d/*`,Session Cookie 鉴权,非 `OPENFLARE_TOKEN` | +| 边缘 API | `/api/v1/agent|relay|tunnel/*` | +| 前端 | `frontend/`,路由共置于 `app/(main)/`,非 `features/store` | +| 配置 | `config.yaml` + `APP_*`/`DB_*` 环境变量,非 `JWT_SECRET`/`DSN` | + +## 2. 已更新文档(P0) + +| 文件 | 更新内容 | +| --- | --- | +| `docs/design/index.md` | 重写 §仓库结构(monorepo、Wavelet 分层、API 前缀、Frontend 结构) | +| `docs/design/architecture.md` | Server 描述、鉴权方式、启动入口 | +| `docs/design/agent-design.md` | Agent API 路径 `/api/v1/agent/*` | +| `docs/reference/cli.md` | 全部命令改为仓库根目录执行 | +| `docs/reference/index.md` | 仓库结构描述 | +| `docs/deployment/deployment.md` | Compose、源码启动、配置变量 | +| `docs/deployment/server.md` | 前端构建路径、启动命令、环境变量 | +| `docs/deployment/openflared.md` | Tunnel API 路径、编译命令 | +| `docs/deployment/relay.md` | 编译命令 | +| `docs/deployment/agent.md` | 源码构建路径 | +| `docs/guideline/Constraints.md` | **新建**,消除全站断链 | +| `AGENTS.md` | 修正 skill/demo 路径 | +| `README.md` | 快速开始指向根目录 compose | + +## 3. 待跟进(P1) + +- [ ] `docs/reference/configuration.md` — 与 `config.example.yaml` / `.env.example` 对齐 +- [ ] `docs/guide/quick-start.md`、`troubleshooting.md` — 鉴权与路径修正 +- [ ] `docs/deployment/server.md` — Docker Compose 示例段落(后半部分仍有过时内容) +- [ ] `docs/DEPLOYMENT.md` — Wavelet 脚手架残留 +- [ ] `docs/design/tunnel-design.md`、`pages-design.md` — API 前缀统一 +- [ ] `docs/changelog/index.md` — JWT_SECRET 声明与代码对齐 +- [ ] `docs/en/**` — 英文镜像同步(低优先级) + +## 4. 文档维护原则 + +1. **单一事实来源**:配置以 `config.example.yaml` + `.env.example` 为准;目录以 `docs/design/index.md` 为准;API 以 `make swagger` 为准。 +2. **禁止再引用**:`openflare-server/`、`OPENFLARE_TOKEN`、`JWT_SECRET`(除非代码重新引入)。 +3. **中英文分工**:功能变更先更新中文文档;英文可标记待同步。 \ No newline at end of file diff --git a/docs/plan/handover-openflare-backend-migration.md b/docs/plan/handover-openflare-backend-migration.md index 0b3dd917..8cb79d45 100644 --- a/docs/plan/handover-openflare-backend-migration.md +++ b/docs/plan/handover-openflare-backend-migration.md @@ -223,6 +223,5 @@ go run . scheduler | [实现计划](./20260618-openflare-wavelet-backend-migration.md) | 模块清单、§12 端点对照 | | [前端迁移计划](./20260618-openflare-wavelet-frontend-migration.md) | UI 迁移与验收 | | [`Wavelet/AGENTS.md`](../../Wavelet/AGENTS.md) | 框架 Guardrails | -| [`docs/guideline/Constraints.md`](../guideline/Constraints.md) | 开发约束 | | 旧后端源码(对照用) | `openflare-server/internal/` | | Changelog | [`docs/changelog/index.md`](../changelog/index.md) `[Unreleased]` | \ No newline at end of file diff --git a/docs/plan/index.md b/docs/plan/index.md index afcd4ce6..808cbd6b 100644 --- a/docs/plan/index.md +++ b/docs/plan/index.md @@ -18,6 +18,7 @@ | [OpenFlare → Wavelet 前端迁移计划](./20260618-openflare-wavelet-frontend-migration.md) | 将 `openflare-server/web` 业务 UI 按 Wavelet 设计风格重写,复用框架组件与 Admin 基建 | | [OpenFlare 前端迁移 — AI 委派](./handover-openflare-frontend-migration.md) | 前端迁移任务队列与验收状态 | | [前端路由验证](./verify-frontend-routes.md) · [Service 验证](./verify-frontend-services.md) · [UI 验证](./verify-frontend-ui.md) · [构建验证](./verify-frontend-build.md) | 多角度迁移验收报告 | +| [文档结构更新 — AI 接手](./handover-docs-restructure-update.md) | 重构后多智能体分析结论与文档批量更新记录 | ## 使用建议 diff --git a/docs/reference/cli.md b/docs/reference/cli.md index d249d12c..06ae84f6 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -1,54 +1,69 @@ # 命令与脚本 -你会学到:OpenFlare Server、管理端前端、Agent、Swagger 和文档站的常用启动、构建、测试、安装与卸载命令。 +你会学到:OpenFlare Server、管理端前端、Agent、Relay、OpenFlared、Swagger 和文档站的常用启动、构建、测试、安装与卸载命令。 + +> 所有命令均在**仓库根目录**执行,除非另有说明。 ## Server 源码启动: ```bash -cd openflare-server cp config.example.yaml config.yaml -go run . all +go run main.go all ``` -指定监听端口与日志目录: +分进程启动: ```bash -go run . --port 3000 --log-dir ./logs +go run main.go api # 仅 HTTP API +go run main.go worker # 仅 Asynq Worker +go run main.go scheduler # 仅定时任务调度 +``` + +编译二进制: + +```bash +make build-server +# 产物:bin/openflare-server ``` 测试: ```bash -cd openflare-server GOCACHE=/tmp/openflare-go-cache go test ./... ``` +质量门禁: + +```bash +make code-check +``` + ## Frontend 开发: ```bash -cd openflare-server/frontend +cd frontend pnpm install pnpm dev ``` -构建静态产物: +构建嵌入产物(供 Go Server 托管): ```bash -cd openflare-server/frontend +cd frontend pnpm build:embed +# 或仓库根目录:make build-embedded ``` 检查: ```bash -cd openflare-server/frontend +cd frontend pnpm lint pnpm typecheck -pnpm test ``` ## Agent @@ -56,57 +71,52 @@ pnpm test 源码运行: ```bash -cd openflare-agent go run ./cmd/agent -config /path/to/agent.json ``` 编译: ```bash -cd openflare-agent -go build -o openflare-agent ./cmd/agent +make build-agent +# 或:go build -o bin/openflare-agent ./cmd/agent ``` 测试: ```bash -cd openflare-agent -GOCACHE=/tmp/openflare-go-cache go test ./... +GOCACHE=/tmp/openflare-go-cache go test ./internal/apps/agent/... ``` -## Relay (中继端) +## Relay(中继端) 源码运行: ```bash -cd openflare-relay -go run ./cmd -config /path/to/relay.json +go run ./cmd/relay -config /path/to/relay.json ``` 编译: ```bash -cd openflare-relay -go build -o openflare-relay ./cmd +make build-relay +# 或:go build -o bin/openflare-relay ./cmd/relay ``` -## OpenFlared (Client 客户端) +## OpenFlared(Tunnel 客户端) 源码运行: ```bash -cd openflared -go run ./cmd -config /path/to/flared.json +go run ./cmd/flared -config /path/to/flared.json ``` 编译: ```bash -cd openflared -go build -o openflared ./cmd +make build-flared +# 或:go build -o bin/flared ./cmd/flared ``` - ## 安装 Agent ```bash @@ -126,11 +136,11 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/unin 重新生成 Swagger 文档: ```bash -go install github.com/swaggo/swag/cmd/swag@v1.16.4 -cd openflare-server -swag init -g main.go -o docs +make swagger ``` +访问:`http://localhost:3000/swagger/index.html` + ## Docs 本地预览: @@ -145,4 +155,4 @@ pnpm dev ```bash cd docs pnpm build:embed -``` +``` \ No newline at end of file diff --git a/docs/reference/index.md b/docs/reference/index.md index 24977b8f..928ead46 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -8,4 +8,4 @@ | --- | --- | | [配置项](./configuration.md) | Server 环境变量、命令行参数、运行时 Option 与 Agent 配置字段 | | [命令与脚本](./cli.md) | 常用启动、构建、测试、安装和卸载命令 | -| [仓库结构](../design/index.md#仓库结构) | `openflare-server`、`openflare-agent`、`openflare-relay`、`openflared` 模块的职责与分层目录说明 | +| [仓库结构](../design/index.md#仓库结构) | monorepo 各目录职责与分层说明(`main.go`、`cmd/`、`internal/apps/`、`frontend/` 等) |