fabriziosalmi/flareover

GitHub: fabriziosalmi/flareover

flareover 是一款确定性的基础设施迁移引擎,帮助用户将站点从 Cloudflare 无缝迁移到基于开源组件的欧洲主权自托管架构上。

Stars: 2 | Forks: 0

# flareover **将你的站点从橙色云(Cloudflare)迁移到你自己的 EU 服务器上 —— 无需改变其行为。** [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/99/993938d8ce5e902ccfb9d6747725c320d855dea3235ed9a304cedf0d94c9321f.svg)](https://github.com/fabriziosalmi/flareover/actions/workflows/ci.yml) [![Release](https://img.shields.io/github/v/release/fabriziosalmi/flareover?sort=semver)](https://github.com/fabriziosalmi/flareover/releases) [![Go](https://img.shields.io/github/go-mod/go-version/fabriziosalmi/flareover)](go.mod) [![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)](LICENSE)

flareover — assess, cost, providers, prepare (real output, honest numbers)

离开大型托管边缘意味着你需要手动重建控制面板默默为你处理的一切: DNS、TLS 证书、重定向、防火墙/WAF 规则、缓存 —— 并且祈祷你没有遗漏 那些会悄无声息破坏站点的设置。 `flareover` 会为你完成这项重建工作。将它指向一个 Cloudflare zone;它会读取每一项设置,并为 EU 基础设施上的开源、自托管技术栈(Caddy、PowerDNS、 CertMate 等)生成等效的配置。它的唯一准则是:**绝不生成会静默改变行为的配置。** - 当它能证明存在完全一致的等效项时,它会自动应用。 - 当选择确实存在歧义时,它会向你询问一个是/否问题。 - 当没有任何配置能忠实映射时,它会为你标记该项 —— 并且**绝不盲目猜测**。 最后一点是核心所在:这是一次你可以信任的迁移,因为该工具会如实告知它究竟能 迁移什么以及不能迁移什么。 **目录:** [契约](#the-contract-no-silent-surprises) · [工作原理](#how-it-works--five-phases) · [目标技术栈](#target-stack-eu-sovereign) · [安装说明](#install) · [使用方法](#usage) · [状态](#status) · [架构](docs/architecture.md) · [贡献指南](CONTRIBUTING.md) ## 契约:没有隐藏的意外 源站上的每个设置都会得出确切的判定结果: | 判定 | 含义 | |---------|---------| | **AUTO** | 目标上存在经过验证的完全等效项 → 自动生成 config。 | | **ASK** | 存在忠实的映射,但有一个细节确实存在歧义 → 你回答一个是/否问题(保存在 `decisions.lock` 中),然后它将被视为 AUTO。 | | **MANUAL** | 没有忠实的映射(Workers 代码、ML 机器人评分、专有 DDoS) → 记录文档并留给你处理,绝不盲目猜测。 | 会改变行为的配置**仅**针对 AUTO 和已回答的 ASK 项目生成 —— 其他所有内容 都会被明确展示,绝不会被静默应用。分类和生成物(artifact)的生成是 `snapshot + decisions.lock` 的**纯函数**:运行两次,就会得到逐字节相同的配置(经过了黄金测试),因此可以在正式上线前在 git 中对结果进行审查。(由*目标*稍后分配的运行时状态 —— 例如 MinIO lifecycle-rule id —— 位于该函数之外,并在存在差异的地方予以注明。) ## 工作原理 —— 五个阶段 ``` assess → prepare → present → execute → guard ``` 1. **评估** (`assess`) —— 对源 zone 进行只读提取 → 生成与提供商无关的意图模型 (CF-IR) → 将每个元素分类为 AUTO/ASK/MANUAL。输出:一份如实的覆盖率报告(+ 成本)。 2. **准备** (`prepare`) —— 解决 ASK 项目;生成生成物;自动准备一个**预部署**目标。 3. **展示** (`present`) —— 一致性校验门:探测实时边缘与预部署边缘,并对 status/redirects/headers/body 进行差异比对。严重的 (HARD) 差异将被拦截;轻微的 (SOFT) 差异将被展示。 4. **执行** (`execute`) —— 门槛控制的割接,编排直至 DNS 切换的上线过程。需要明确的确认。 5. **故障防护** (`guard`) —— 健康监控、自动回滚/故障转移、故障闭锁出口, 幂等的重新运行。 ## 目标技术栈(EU 主权) | 关注点 | 工具 | |---------|------| | 权威 DNS | 自托管 PowerDNS(zone + 记录 + DNSSEC → 用于域名注册商的 DS),或通过 `--dns` 使用托管的 EU 提供商:**bunny.net**、**Scaleway**、**OVHcloud**、**Gandi** 或 **Leaseweb** (`provision --dns `) | | 反向代理 / CDN / TLS | Caddy(原生 ACME、HTTP/3) | | 边缘缓存 | souin(Caddy 模块) | | WAF | caddy-waf(OWASP/速率限制/IP·ASN·国家/封禁列表) | | 证书 | CertMate — DNS-01、泛域名、Let's Encrypt 或 **Actalis**(EU CA) | | 对象存储 (R2/S3 →) | 自托管 MinIO,或托管 EU S3 —— **Scaleway** (`storage --dest scaleway`) / **OVHcloud** (`--dest ovh`) —— 桶 + 版本控制 + 生命周期 + CORS;rclone 数据拷贝 | | 出口防护(可选) | secure-proxy-manager(默认拒绝 + 允许列表,故障闭锁) | | 主权源站链接 | WireGuard mesh(替代 Cloudflare Tunnel;源站保持无入站流量) | | 封禁列表 | blacklists feeds | | 落地区域 | 裸金属 / Proxmox,或任何 EU 提供商 —— `flareover providers` | 每个目标都标有其司法管辖区,因此迁移在可验证的程度上保持在 EU 范围内。边缘提供商 带有如实的**主权层级**:EU 自有的运营商(Hetzner、OVH、Contabo、Aruba、Scaleway)被 标记为主权;同时也提供超大规模云服务商的 EU 区域(位于米兰的 AWS/GCP/Azure),但会如实 标记其本质 —— 即美国运营商下的 EU *驻留*(受 CLOUD Act 管辖),**绝不是**“主权”。引擎 永远不会触及你的源提供商或域名注册商 —— DS 的发布以及最终的 NS 迁移始终是 明确的人工步骤。 ## 安装说明 ``` # macOS (Homebrew) brew install fabriziosalmi/flareover/flareover # Linux/macOS — 验证过的 installer(为你的 OS/arch 下载对应的 release,检查其 sha256) curl -fsSL https://raw.githubusercontent.com/fabriziosalmi/flareover/main/install.sh | sh # …或者从 source 构建(单一 static binary,纯 Go,零 external deps) go install github.com/fabriziosalmi/flareover/cmd/flareover@latest ``` 从源码构建需要 **Go 1.25+**。发行的二进制文件(linux/macOS/windows · amd64/arm64)附带 SBOM 和 `checksums.txt`,**通过 Sigstore/cosign 进行无密钥签名** —— 使用每个发行版 说明中的命令进行验证。`flareover version` 会打印构建标签。 ## 使用方法 ``` flareover [args] ``` | 阶段 | 功能描述 | |-------|--------------| | `zones` | 列出只读 token 能看到的每个 zone。 | | `extract ` | 将实时 Cloudflare zone(只读 API)读取为快照 JSON。 | | `assess ` | 分类生成 AUTO/ASK/MANUAL 覆盖率报告 (`--md`、`--json`、`--html`)。 | | `resolve ` | 遍历 ASK 问题并生成 `decisions.lock` (`--defaults`、`--merge`)。 | | `cost ` | 比较 Cloudflare 层级/附加组件成本与固定 EU 技术栈成本 (`--vps `)。 | | `prepare ` | 生成生成物(Caddyfile、caddy-waf 规则、PowerDNS zone、出口、mesh)**外加一份 `MIGRATION.md` 报告** —— 包含发现的每个 Cloudflare 元素及其确切结果的表格(1:1 AUTO / ASK / MANUAL)。`--validate` 验证它们能被正确解析;`--edge-provider ` 输出边缘 cloud-init(并且,对于 **Scaleway**/**OVHcloud**,还会生成一个脚本以据此创建并启动边缘实例)。 | | `doctor …` | 只读的预检 —— 确认每个目标是否可连接/已授权/已配置?在配置前给出 GO/NO-GO 决议。 | | `providers` | 列出 EU 边缘提供商及其真实的主权层级(EU 自有 vs 美国运营商/EU 区域)。 | | `provision …` | 通过 API 启动目标 (`--pdns-url`、`--certmate-url`)。 | | `present …` | 一致性校验门:实时边缘 vs 预部署边缘 (`--after-addr`)。 | | `execute …` | 编排直至受控割接的各个上线阶段。 | | `storage …` | 迁移对象存储 → MinIO + rclone 计划 (`--extract-r2`、`--extract-s3`)。 | | `guard --url …` | 故障防护看门狗:健康监测 + 回滚/故障转移 (`--on-unhealthy`、`--interval`、`--once`)。 | ``` # 1. 将 zone snapshot 评估为一份 honest coverage report flareover assess zone.snapshot.json # 2. 为 AUTO + answered-ASK surface 生成 target-stack artifacts flareover prepare zone.snapshot.json \ --decisions decisions.lock --edge-ip 203.0.113.10 --ca actalis \ --egress-deny --egress-allow api.example.com,10.0.0.0/8 \ --mesh-edge 203.0.113.10:51820 --out ./out # 2b. 证明 artifacts 能够 parse,并在触碰 target 之前进行 pre-flight flareover prepare zone.snapshot.json --edge-ip 203.0.113.10 --out ./out --validate flareover doctor --pdns-url http://pdns:8081 --pdns-key "$PDNS_KEY" \ --certmate-url http://certmate:8000 --certmate-token "$CM_TOKEN" \ --spm-url http://spm:5001 --check-caddy # GO / NO-GO, exit 0 only when ready # 3. 搭建 live target(PowerDNS zone + DNSSEC,通过 DNS-01 实现的 CertMate wildcard) flareover provision --snapshot zone.snapshot.json --decisions decisions.lock \ --edge-ip 203.0.113.10 \ --pdns-url http://pdns:8081 --pdns-key "$PDNS_KEY" --nameservers ns1.example.eu,ns2.example.eu \ --certmate-url http://certmate:8000 --certmate-token "$CM_TOKEN" \ --certmate-dns cloudflare # pre-cutover: NS still at the source → solve DNS-01 there # 4. 在你改变任何东西之前的 parity gate flareover present --snapshot zone.snapshot.json --after-addr 203.0.113.10:443 ``` `--decisions` 是一个包含 ASK 问题 ID → 答案的 JSON 映射。任何仍未回答的内容都 不会被生成(并在 `assess` 中保持为可见的 ASK 状态) —— 绝不盲目猜测。默认的技术栈配置是 `caddy`。 ## 状态 **端到端且经实时验证。** 全部五个阶段均已实现,并且每个目标适配器都已在 **真实运行的服务**上进行了测试,而不仅仅是使用模拟 —— 每个适配器都捕获到了模拟无法 发现的真实 bug: | 适配器 | 实时验证 | |---------|-----------| | PowerDNS | zone + rrsets + DNSSEC 已部署在实时 PowerDNS 上 | | CertMate | 通过 DNS-01 签发了真实且受公众信任的**泛域名证书** | | MinIO | 完整的提取 → 生成 → 部署 → 重新提取的往返测试 | | WireGuard mesh | 真实的加密 边缘↔源站 链接,源站保持无入站流量 | | secure-proxy-manager | 将生成的出口脚本应用于实时 API,并已验证状态 | 手动实现的协议代码(AWS SigV4、PowerDNS rrsets、WireGuard X25519 密钥、CertMate DNS-01)均已 通过真实端点验证。 免费层 WAF 的主要功能**确实被映射**为 AUTO,适用于 caddy-waf:**国家和 ASN 封禁** (`block_countries` / `block_asns`,L3 源作用域)以及**速率限制** —— 基于单个 IP 的限制 → `rate_limit`;基于客户端 IP 以外内容的规则 → 视为一次 ASK。关于速率 限制的一个真实警告是*全局*计数:Cloudflare 在其整个 anycast 边缘执行阈值,因此 几个独立托管的边缘节点各自在本地进行计数(有效限制随节点 数量增加而缩放),除非它们共享一个计数器 —— 这是一个分布式系统的限制,已明确注明而非掩盖伪造。 被刻意**排除在外**,因为不存在忠实且确定性的映射:地理流量 *引导*(按区域将用户发送到不同的源站 —— 这是一项付费的负载均衡功能,与上面的国家/地区封禁不同)以及缓存命中率一致性 —— 已如实呈现,绝无虚假伪造。 请参阅 [`docs/deploy-hardened.md`](docs/deploy-hardened.md) 获取强化的落地区域蓝图以及 总结出的经验教训。 ## 许可证 Copyright (C) 2026 Fabrizio Salmi。基于 [AGPL-3.0-only](LICENSE) 许可 —— 你可以自由 使用、学习、修改和重新分发它,但网络使用同样被视为分发行为,因此衍生服务必须在 相同的条款下提供其源代码。
标签:Caddy, CDN迁移, EVTX分析, PowerDNS, Web基础设施, 数据主权, 日志审计, 自动化配置, 运维工具