简体中文 | English
自托管的 CDN / WAF / 边缘调度控制平面,面向个人自用:一个运营者账户统一管理边缘节点、源站池、缓存、HTTPS、四层转发、访问策略与 DNS 调度。边缘节点见 edgeweir-node。
文档:https://marvinli001.github.io/edgeweir/zh/
| 领域 | 能力 |
|---|---|
| 集群与账户 | 节点组、区域、配置金丝雀、2FA / Passkey、服务账号、审计日志 |
| 网站管理 | 网站标签(按任一 / 全部标签筛选、改名合并、⌘K 搜索)、批量启停 / 清除缓存 / 加减标签 / 删除、把一个网站的设置(15 个部分)预览后复制到其他网站、克隆网站 |
| 源站与缓存 | 源站池与源站组、主动与被动健康检查、会话保持、回源 TLS 校验、S3 签名回源、HTTP/2 回源与 gRPC、WebSocket、表达式缓存规则与浏览器 TTL、缓存键、切片、按 URL / 目录 / Host / Cache-Tag 刷新、按设备与站点地图预热、带密钥的 PURGE 方法、可按集群与节点设置的缓存区、缓存带 Set-Cookie 的响应(Cookie 只发给回源的那次请求)、回源尝试次数与状态码重试、请求体上限、字符编码、对象存储预设、按状态码与 4xx / 5xx 的错误页(HTML 或跳转)、维护模式、WebP / AVIF 格式转换(按 Accept 缓存变体,统计节省的字节数) |
| 四层转发 | 按集群的 TCP / UDP 端口池;L4 应用:权重与备用源站、被动健康检查、连接与空闲超时、向源站发送 PROXY protocol v1 / v2 与接受 PROXY protocol、端口段与同号源站端口、TCP 的 TLS 卸载、放行 / 拦截名单、每节点并发与新建连接上限;与网站共用 DNS 调度(CNAME、解析线路、备用节点组);按分钟统计连接、拒绝、并发峰值与流量;增删端口时已有连接不断开 |
| 域名 | 精确、泛域名、任意层级后缀与正则域名,国际化域名(Punycode);未知域名与节点 IP 访问的处理(平台页、关闭连接、默认网站)与扫描封禁;可重新生成或自定义的 CNAME 前缀 |
| 证书与协议 | 证书上传、ACME HTTP-01 / DNS-01 签发与续期(Let's Encrypt、ZeroSSL、Google Trust Services 或自定义 ACME 目录,ECDSA / RSA 密钥,ACME 账户列表)、HTTPS、每个网站最多 4 张证书(按 SNI 与客户端能力选择)、客户端证书(双向 TLS)、集群内共享票据密钥的 TLS 会话复用、HSTS、HTTP/2、HTTP/3;80 / 443 之外的监听端口与网站绑定端口、跳转状态码与端口;访客 IP 来自 PROXY protocol 或可信代理报头;Zstandard、Brotli、Gzip 压缩(Gzip 级别、最大压缩长度) |
| 访问策略 | IP 名单(全局允许 / 拦截,网站可选本站拦截 / 放行名单)、本地 GeoIP、分阶段规则与内置函数(Cookie、查询参数与请求头按名取值,编码与哈希函数,请求头 / 响应头 / 查询参数的表达式值,含请求体表单与 JSON 字段)、WAF(封禁、自定义响应、断开连接、跳过,CRS 按路径排除与覆盖)、限速与超额封禁、动态重定向与改写、批量重定向、请求头与响应头变换、源站覆盖与压缩规则、按请求覆盖网站设置;访问鉴权(Basic、转发鉴权、URL 鉴权 A–D 与控制台生成签名 URL,缓存命中同样鉴权);访问控制(地区、防盗链、UA 名单、边缘应答 CORS 预检、WebSocket 来源、安全响应头)与 IP 检查;挑战放行已验证的搜索引擎爬虫,挑战失败封禁;秒级下发的 IP 封禁,全局封禁可由 nftables 在内核丢包 |
| 托管规则 | OWASP CRS:仅检测或拦截、paranoia level、异常分数阈值、按规则 ID 排除、请求体检查上限;命中规则的统计与访问日志 |
| 挑战与 CC 防护 | Cookie 跳转、JS 计算、工作量证明、图片验证码四级挑战;网站或全局 Under Attack;节点本地分级 CC 自动升级(站点、单 URL、单 IP 自动封禁、源站错误率);集群内通用的签名通行凭证;JA4 指纹用于规则、限速与访问日志 |
| DNS 与观测 | 独立 DNS 版本、健康节点调度、流量统计去重与汇总、Top URL / IP、告警与订阅 |
| 智能调度 | 区域探针(TCP / HTTP / HTTPS 健康端点)、节点主机指标;调度规则按节点指标与探测结果摘除节点、切换到备用节点组或备用 IP,带预览;运营商解析线路(DNSPod、腾讯云、阿里云、华为云)、备用节点组、多级备用 IP |
| 运维 | 采样访问日志(UA、来源、协议、地区、回源、拦截原因,可强制记录被拦截的请求,11 种筛选,保留期可调)与 CSV 导出、节点上实时查看请求、统计维度(地区、运营商、来源、终端、协议、拦截原因、挑战通过率)、可选 ClickHouse、只读及可吊销 AccessKey、签名灰度升级与回滚、性能基线、备份恢复 |
| 仓库 | 组成 |
|---|---|
| edgeweir(本仓库) | 控制台:Web UI、管理 API(含 OpenAPI /api/v1)、节点通道、pg-boss worker,单进程、单镜像。镜像内含 edgeweir-certd(Go),负责 ACME 证书签发与 DNS 记录管理,由 pg-boss 经有界 stdin/stdout 协议调用,凭据不经进程参数传递。 |
| edgeweir-node | 边缘节点:edgeweir-node Go agent 与 OpenResty 数据面。 |
浏览器、API 调用方 ─:3000──▶ ┌───────────────────────────────────┐
│ 控制台(一个 Node.js 进程) │── PostgreSQL 18(唯一依赖)
│ UI · /rpc · /api/v1 │
│ 节点通道 :8443(mTLS) │
│ pg-boss worker │
└────────────────▲──────────────────┘
│ Connect-RPC over mTLS
┌────────────────┴──────────────────┐
终端用户 ─────▶ │ 边缘节点:edgeweir-node agent │──▶ 源站
│ + OpenResty │
└───────────────────────────────────┘
控制台与节点之间的唯一契约为 proto/ 中的 protobuf(buf 管理)。设计细节见 ARCHITECTURE.md。
- 控制台不保存 SSH 凭据。
- 节点私钥在节点本机生成与保存,不离开节点。
- 内部 CA 私钥、证书私钥、S3 源站密钥、DNS API 凭据经
EDGEWEIR_MASTER_KEY信封加密后入库,密文与所属记录绑定。 - 节点注册 token 单次有效,仅存储 SHA-256;注册完成后节点 RPC 一律使用 mTLS。
/api/v1仅接受x-api-key;/rpc仅接受会话 Cookie 与 CSRF 请求头。- 无厂商回连,无许可证校验,不发送遥测;第三方依赖的遥测强制关闭。
信任基线、漏洞报告与发布物校验见 SECURITY.md。
| 制品 | 地址 | 版本规则 |
|---|---|---|
| 控制台镜像 | ghcr.io/marvinli001/edgeweir(amd64 / arm64) |
master 上通过 CI 的提交发布为 <YYYYMMDD>-<commit>(如 20260929-a1b2c3d);stable(默认)指向验证过的日期 tag,每次移动附 Release;latest 跟随 master。不使用语义化版本号,镜像经 cosign keyless 签名。 |
| 边缘节点 | edgeweir-node Releases | 签名 Release,语义化版本 vX.Y.Z;stable 控制台支持 1.x 全部次版本。 |
生产环境通过 EDGEWEIR_VERSION 固定日期 tag。
环境要求:Docker、Compose v2。
git clone https://github.com/marvinli001/edgeweir.git
cd edgeweir
umask 077
cat > .env <<EOF
EDGEWEIR_MASTER_KEY=$(openssl rand -base64 32)
POSTGRES_PASSWORD=$(openssl rand -hex 24)
EDGEWEIR_PUBLIC_URL=http://localhost:3000
EOF
docker compose pull # 从源码构建:docker compose up -d --build
docker compose up -d --wait
docker compose logs console | grep setupToken访问 http://localhost:3000(3000 默认只监听本机,其他机器经反向代理访问),使用日志中的一次性 setup token 完成初始化向导,创建唯一的运营者账户与默认集群。setup token 在首次初始化成功后失效;无 token 的初始化请求一律拒绝。
必填变量:
| 变量 | 说明 |
|---|---|
EDGEWEIR_MASTER_KEY 或 EDGEWEIR_MASTER_KEY_FILE |
主密钥,或存放主密钥的文件(主密钥文件)。用于信封加密入库的敏感数据(内部 CA 私钥、证书私钥、S3 源站密钥、DNS API 凭据、setup token)并派生会话密钥。须与数据库备份分开保存,丢失后上述数据不可恢复。 |
POSTGRES_PASSWORD 或 DATABASE_URL |
使用 Compose:内置 PostgreSQL 的密码,DATABASE_URL 由它拼出。不用 Compose:PostgreSQL 18 连接串 DATABASE_URL。 |
EDGEWEIR_PUBLIC_URL |
浏览器访问控制台的地址,在反向代理后为代理地址,如 https://cdn-admin.example.com。须与浏览器地址栏一致,否则登录失败;保留 http://localhost:3000 时生成的节点安装命令也指向本机。 |
其余变量均有默认值,完整列表见 .env.example。BETTER_AUTH_SECRET 未设置时由主密钥派生;已设置的部署不得移除,否则控制台拒绝启动。节点发布源与源站地址允许清单在初始化后于 系统设置 配置,封禁、全局防护与 GeoIP 在 防护设置,SMTP 在 告警 页。
| Compose profile | 组件 | 说明 |
|---|---|---|
analytics |
ClickHouse | 配合 EDGEWEIR_ANALYTICS=clickhouse 启用原始访问日志与分钟级统计。访问日志采样默认关闭,保留期在系统设置中调整(默认 7 天,ClickHouse 至多 90 天)。控制台图表与告警使用 PostgreSQL 汇总数据。 |
详见 访问日志与 AccessKey、备份与恢复。
| 端口 | 用途 | 反向代理 |
|---|---|---|
| 3000 | Web 控制台与 API | 支持在前端终结 TLS(如宝塔 nginx)。须将代理地址写入 EDGEWEIR_TRUSTED_PROXIES,否则审计日志与登录限速取不到真实客户端 IP;其他来源的转发头一律忽略。 |
| 8443 | 节点通道 | 直接暴露,或经 nginx stream 四层透传。禁止由代理终结 TLS:控制台自行终结 TLS 并强制 mTLS。平台只转发 HTTP 时,节点经 3000 上的 WebSocket 入口 /node-channel 连接,节点通道的 TLS 在 WebSocket 内,见 节点通道的 WebSocket 入口。 |
| 平台 | 文档 |
|---|---|
Docker Compose / docker run |
Docker Compose 部署 |
| 宝塔面板 / aaPanel | 宝塔面板 / aaPanel、deploy.sh 参考 |
| Railway | Railway |
| Fly.io | Fly.io |
| bunny.net Magic Containers | bunny.net Magic Containers |
| Render | Render; |
| Zeabur | Zeabur; |
交互式安装与升级脚本 deploy.sh 适用于任何装有 Docker 与 Compose v2 的 Linux,支持本机、云端或内置 PostgreSQL:
curl -fsSL -o deploy.sh https://raw.githubusercontent.com/marvinli001/edgeweir/master/deploy.sh
sudo bash deploy.sh install节点要求:Linux(systemd),amd64 / arm64,glibc 2.34 及以上(RHEL / Rocky / AlmaLinux 9+、Debian 12+、Ubuntu 22.04+),可访问控制台 8443 端口。
-
登录控制台,打开 集群与节点,选择集群并生成安装命令。命令包含单次有效 token 与控制台内部 CA 的 SHA-256 指纹。
-
在节点上以具备 sudo 权限的账户执行:
export EDGEWEIR_TOKEN='<一次性 token>' curl -fsSL https://<控制台>/install.sh | sudo --preserve-env=EDGEWEIR_TOKEN bash -s -- \ --server https://<控制台>:8443 --ca-sha256 <CA 指纹>
-
节点上线后,控制台显示其在线状态与已应用的配置 revision。
安装脚本行为:
- token 仅经
EDGEWEIR_TOKEN环境变量或--token-file传递,不出现在进程参数中。 - 安装前校验 checksums 的 cosign 签名(签发身份须为 edgeweir-node release 工作流及待安装的 tag)与每个包的 SHA-256。
- 优先安装 .deb / .rpm,否则使用 tar.gz;配置了控制台
/downloads镜像时从镜像下载,否则从 GitHub Releases 下载。 - 先安装同一发布中为 Edgeweir 构建的 OpenResty(
edgeweir-openresty)与 ModSecurity 模块(edgeweir-openresty-modsecurity,--no-modsecurity跳过),再安装 edgeweir-node。 - agent 先核对 CA 指纹再提交 token,本地生成私钥,此后仅经 mTLS 与控制台通信。
安装参数与发布物镜像见接入节点。
| 入口 | 认证 | 用途 |
|---|---|---|
/api/v1 |
AccessKey(x-api-key 请求头) |
对外 OpenAPI,规范文档位于 /api/v1/openapi.json |
/rpc |
会话 Cookie + CSRF 请求头 | Web UI 专用 |
/mcp |
OAuth 访问令牌(Authorization: Bearer) |
MCP 服务,默认关闭,见 MCP |
三个入口由 packages/contract 中的同一份 oRPC 契约提供。
环境要求:Node.js 24+、pnpm 12、Docker。helpers/certd 与 pnpm e2e 另需 Go 1.27.2。buf 随开发依赖安装。
pnpm install
docker compose -f compose.dev.yml up -d # 本地 PostgreSQL
cp .env.example .env # 填写 EDGEWEIR_MASTER_KEY
pnpm dev # UI 与 API :3000,节点通道 :8443| 命令 | 作用 |
|---|---|
pnpm lint |
Biome 检查与格式校验、buf lint |
pnpm typecheck |
全 workspace TypeScript 类型检查 |
pnpm test |
单元与集成测试(Vitest,PostgreSQL 由进程内 PGlite 提供,无需 Docker) |
pnpm build |
生产构建 |
pnpm proto:lint |
检查 proto/ |
pnpm proto:gen |
由 proto/ 生成 TypeScript 至 packages/proto |
pnpm db:generate |
由 packages/db/src/schema 的变更生成 SQL 迁移 |
pnpm e2e |
端到端测试,见端到端测试 |
提交规范、proto 变更流程与国际化规则见 CONTRIBUTING.md。
docker compose -f compose.e2e.yml up -d --build
pnpm e2e # --up 启动环境;--down 结束后删除环境与卷;--skip-ui 跳过 Playwright依赖:
- curl、jq、Docker(节点容器需要
NET_ADMIN)、Node.js - 与本仓库同级的 edgeweir-node 检出(或
EDGEWEIR_NODE_CONTEXT) - 安装步骤:goreleaser v2、syft、cosign、Go 1.27.2;edgeweir-node 的
out/openresty中有 Docker 架构对应的 edgeweir-openresty 包(make openresty-packages,缺少时由scripts/e2e.sh从缓存取出或构建,需要 Docker Buildx) - G3 / G8 步骤:之前的节点镜像
edgeweir-node:pre-g3、edgeweir-node:pre-g8(E2E_OLD_NODE_IMAGE、E2E_PRE_G8_IMAGE,缺少时由scripts/e2e-g3.mjs/e2e-g8.mjs从 edgeweir-node 提交6da3403/7e1338f构建或从缓存载入) - 构建缓存:旧节点镜像按提交、edgeweir-openresty 包按
packaging/openresty的 git tree 保存在E2E_CACHE_DIR(默认~/.cache/edgeweir-e2e,scripts/e2e-cache.mjs),新的 Docker 虚拟机或清空构建缓存后直接载入,不再编译 - 网络访问:deb.debian.org、openresty.org;首次构建节点镜像或 edgeweir-openresty 包时另需 github.com、download.gnome.org、vault.almalinux.org
覆盖范围:节点注册、配置下发、缓存、刷新与预热、源站与 S3、故障切换、认证路由白名单(better-auth 管理与 api-key 端点关闭,API Key 不转换为会话)、源站地址策略与 CDN-Loop、HTTPS 源站名称校验、1 MiB 切片 Range 请求、install.sh 在干净容器中从控制台镜像安装、节点经终结 TLS 的反向代理以 wss:// 节点通道地址注册(经 mTLS 在线、心跳持续、应用配置版本)、动态封禁(下发延迟 p95 ≤ 5 秒、站点封禁、全局封禁由 nftables 丢包)、挑战与通行凭证(无头浏览器通过 js 与 pow 挑战,凭证在另一节点有效,换网段、换 UA 或伪造后失效)、分级 CC(只升级被攻击的路径、单 IP 自动封禁)、JA4 参与规则匹配、Brotli / Zstandard 按 q 值协商(缓存一份未压缩对象,curl --compressed 解码)、OWASP CRS 检测与拦截(含缓存命中)、旧节点所在集群无法开启这些功能、edgeweir-openresty 包内容、按 Cache-Tag 与 Host 刷新(含过期内容与分片)、按设备与站点地图预热、主动健康检查摘除与恢复、会话保持与故障切换、网站与平台错误页(转义、no-store、请求 ID)、动态重定向与改写及查询参数编辑(无效目标失败关闭)、批量重定向的热更新、源站覆盖规则与回源超时、表达式缓存规则与浏览器 TTL、压缩规则与不绕过缓存的 gzip=false、按规则开关 Under Attack、WebSocket 与日志采样、区域探针(两个探针容器以一次性令牌注册,节点以自身证书兼任探针)、多数探针到不了主地址时切换到备用地址、限定区域的调度规则摘除节点与线路切换到备用节点组、按解析线路写入的记录、四层转发(端口池重叠、端口池外与 UDP PROXY protocol 被拒绝,TCP 与 UDP 经两个节点转发,长连接跨越新增端口引起的 reload,向源站发送 PROXY protocol v1 / v2 与接受 PROXY protocol 的监听,不 reload 更换源站,IP 拦截名单与连接上限,统计与 CNAME)、HTTP/2 回源与 gRPC(只支持 h2c 的源站,经两个节点的 gRPC 单次调用、双向流与错误 trailers,改回 HTTP/1.1 后不再以 HTTP/2 回源)、缓存、源站与内容(集群与节点的缓存区及用量、带 Set-Cookie 的缓存对象只把 Cookie 发给回源的那次响应、排除 utm_* 的缓存键、PURGE 方法、错误页分类与跳转、维护模式、字符编码、请求体上限、Gzip 级别、回源重试、MinIO 预设的 S3 源站)、网站管理(批量加标签与按标签筛选、把规则与缓存设置复制到两个网站后两个节点按新设置服务、缺少源站组的网站复制失败且设置不变、克隆网站、批量停用在一个配置版本内生效)、用量保护(极小上限下的预警与上限告警送达 Webhook、两个节点上开启维护模式与停用网站、调高上限后自动恢复、手动恢复后不再触发)、Playwright 页面流程。
以下变量由 compose.e2e.yml 与 scripts/e2e.sh 共同读取,两侧取值须一致。更换项目名、端口、tag 与子网即可并行运行第二套环境。
| 变量 | 默认值 | 作用 |
|---|---|---|
COMPOSE_PROJECT_NAME |
edgeweir-e2e |
Compose 项目名,同时用于命名安装容器 |
E2E_CONSOLE_PORT |
13000 |
控制台宿主机端口 |
E2E_NODE_PORT |
18080 |
节点 HTTP 宿主机端口 |
E2E_TAG |
e2e |
控制台与节点镜像 tag |
E2E_SUBNET |
172.28.213.0/24 |
默认网络,加入源站地址允许清单 |
E2E_ISOLATED_SUBNET |
172.28.214.0/24 |
允许清单之外的网络,其中的源站须被拒绝 |
E2E_INSTALL_IMAGE |
debian:bookworm-slim(scripts/e2e.sh 中按 digest 固定) |
运行 install.sh 的干净环境 |
EDGEWEIR_NODE_CONTEXT |
../edgeweir-node |
edgeweir-node 检出目录 |
测试环境缩短了时间:控制台每分钟的任务另外每 5 秒运行一次、节点每 5 秒发心跳(在线窗口 15 秒)、节点每 5 秒上报已结束分钟的统计(compose.e2e.yml 中的 EDGEWEIR_E2E_TICK_SECONDS、EDGEWEIR_E2E_HEARTBEAT_SECONDS、EDGEWEIR_STATS_INTERVAL)。设 E2E_TICK_SECONDS=、E2E_HEARTBEAT_SECONDS=(空值)与 E2E_STATS_INTERVAL=1m 后按生产环境的时间运行。
apps/console/ 控制台:单一应用包、单一进程
src/server/ Hono 服务端:API、认证、节点通道、worker
src/web/ React SPA
packages/db/ Drizzle schema 与 SQL 迁移
packages/contract/ oRPC 契约与 zod schema
packages/config-compiler/ 数据库模型 → NodeConfig IR
packages/proto/ 由 proto/ 生成的 TypeScript
proto/ protobuf(buf 管理),与 edgeweir-node 共享的唯一契约
helpers/certd/ edgeweir-certd(Go):lego 负责 ACME,libdns 负责 DNS 记录
scripts/e2e.sh 端到端测试脚本
docs/deploy/ 部署文档
docs/guide/ 使用指南
docs/reference/ 参考:环境变量、命令行、API
doc/ 文档站(Fumadocs),发布至 GitHub Pages
文档站 https://marvinli001.github.io/edgeweir/zh/ 由以下 Markdown 生成。每篇文档另有英文版 *.en.md。
| 分类 | 文档 |
|---|---|
| 入门 | 核心概念 · 快速上手 |
| 部署 | 部署概览 · Docker Compose · 宝塔面板 / aaPanel · deploy.sh 参考 · Railway · Fly.io · bunny.net Magic Containers · Render · Zeabur · 端口、反向代理与可信代理 |
| 站点 | 概览 · 网站管理 · 域名与未知域名 · 源站与缓存 · 分层缓存 · 图片格式转换 · 面向代理的 Markdown · HTTPS 与证书 · 错误页 · L4 转发 · 用量保护 · 统计与访问日志 |
| 访问控制 | 规则、IP 名单与 GeoIP · 访问控制 · 封禁 · 挑战与 CC 防护 · AI 爬虫管理 · OWASP CRS 托管规则 · 攻击与自动缓解 |
| 基础设施 | 集群与节点 · 区域探针与智能调度 · DNS 调度 |
| 系统 | 账户与登录 · 告警 · 系统设置与审计 · 节点扩展 |
| 节点 | 节点概览 · 接入节点 · 节点配置 · 节点升级 · 节点日志 · 节点运维 · 节点排障 |
| 运维 | 版本与升级 · 降级 · 备份与恢复 · 维护 · 故障排查 |
| 参考 | API 概览 · API:网站 · API:访问控制 · API:证书 · API:集群与节点 · API:DNS 与调度 · API:概览、统计与告警 · API:系统与账户 · 环境变量 · 命令行 · 错误码 · 节点扩展契约 |
| 项目 | 架构 · 安全策略 · 开发与贡献 · 许可证 |
AGPL-3.0-only,edgeweir-node 相同。允许在遵守许可证的前提下商用。
开源版是单一运营者的 CDN,不支持多租户;组织与成员等多租户能力、客户门户、套餐计费、财务与分销由独立商业产品提供,不对开源核心附加使用限制。详见 LICENSING.md。