flareover

module
v0.1.28 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: AGPL-3.0

README

flareover

flareover

Move your site off the orange cloud onto your own EU servers, without changing how it behaves.

CI Release Go Docs

Leaving the big managed edge means rebuilding, by hand, everything the dashboard quietly does for you: DNS, TLS certificates, redirects, firewall/WAF rules, caching, and hoping you didn't miss something that silently breaks the site.

flareover does that rebuild for you. Point it at a Cloudflare zone; it reads every setting and generates the equivalent configuration for an open-source, self-hosted stack (Caddy, PowerDNS, CertMate, …) on EU infrastructure. Its one rule: never emit config that silently changes behavior.

  • Where it can prove an exact equivalent, it applies it.
  • Where a choice is genuinely ambiguous, it asks you one yes/no.
  • Where nothing maps faithfully, it flags the item for you, and never guesses.

That last part is the whole point: a migration you can trust, because the tool is honest about exactly what it can and can't carry over.

Contents: The contract · How it works · Target stack · Install · Usage · Status · Architecture · Contributing

📖 Full documentation lives at flareover.com/docs: Quick Start, Coverage Matrix, DNS Targets, and the FAQ.

The contract: no silent surprises

Every setting on the source gets exactly one verdict:

Verdict Meaning
AUTO There's a proven exact equivalent on the target → config is generated automatically.
ASK A faithful mapping exists, but one detail is genuinely ambiguous → you answer one yes/no (saved in decisions.lock), then it's treated as AUTO.
MANUAL Nothing maps faithfully (Workers code, ML bot-scoring, proprietary DDoS) → documented and left for you, never guessed.

Behavior-changing configuration is emitted only for AUTO and answered-ASK items; everything else is surfaced, never silently applied. Classification and artifact generation are a pure function of snapshot + decisions.lock: run it twice, get byte-identical config (this is golden-tested), so the result is reviewable in git before anything goes live. (Runtime state a target assigns later, e.g. a MinIO lifecycle-rule id, is outside that function and noted where it differs.)

How it works: five phases

assess → prepare → present → execute → guard
  1. Assessment (assess): read-only extract of the source zone → provider-agnostic intent model (CF-IR) → classify every element AUTO/ASK/MANUAL. Output: an honest coverage report (+ cost).
  2. Preparation (prepare): resolve ASK items; generate artifacts; auto-provision a staged target.
  3. Presentation (present): parity gate: probe the live edge vs the staged edge and diff status/redirects/headers/body. HARD divergences block; SOFT ones are surfaced.
  4. Execution (execute): gated cutover, orchestrated live up to the DNS flip. Requires explicit confirmation.
  5. Failguards (guard): health monitoring, automatic rollback/failover, fail-closed egress, idempotent re-runs.

Target stack (EU-sovereign)

Concern Tool
Authoritative DNS PowerDNS self-hosted, or managed via --dns: EU-owned bunny.net · Scaleway · OVHcloud · Gandi · Leaseweb · Hetzner, or Route 53 · Cloud DNS · Azure DNS (AWS/Google/Microsoft: honestly tiered US-operator, not sovereign)
Reverse proxy / CDN / TLS Caddy (native ACME, HTTP/3)
Edge cache souin (Caddy module)
WAF caddy-waf (OWASP/rate-limit/IP·ASN·country/blocklists)
Certificates CertMate: DNS-01, wildcard, Let's Encrypt or Actalis (EU CA)
Object storage (R2/S3 →) MinIO self-hosted, or managed EU S3: Scaleway (storage --dest scaleway) / OVHcloud (--dest ovh) / Contabo (--dest contabo, EU region eu2) / Aruba (--dest aruba, IT, endpoint from your account): buckets + versioning + lifecycle + CORS; rclone data copy
Egress shield (optional) secure-proxy-manager (default-deny + allowlist, fail-closed)
Sovereign origin link WireGuard mesh (replaces the Cloudflare Tunnel; origin stays inbound-free)
Blocklists blacklists feeds
Landing zone one-command deploy/ docker-compose, bare-metal / Proxmox, or any EU provider: flareover providers

Every target is tagged with its jurisdiction so the migration provably stays EU-scoped. Edge providers carry an honest sovereignty tier: EU-owned operators (Hetzner, OVH, Contabo, Aruba, Scaleway, Leaseweb) are labelled sovereign; a hyperscaler's EU region (AWS/GCP/Azure in Milan) is offered too, but labelled for what it is: EU residency under a US operator (CLOUD Act reach), never "sovereign". The engine never touches your source provider or your registrar: the DS publish and the final NS move stay explicit human steps.

Already behind a Cloudflare Tunnel? The lowest-risk path is to keep your origin exactly where it is and just re-tunnel it: flareover stands up your own edge node(s) and a WireGuard tunnel, and the origin only swaps cloudflared for wg-quick. Add --mesh-edge (repeat it for an HA edge front). See docs/scenario-edge-mesh.md, and terraform/hetzner/ for a Terraform module that boots the edge on Hetzner (EU-owned) straight from the generated cloud-init.

Install

# macOS (Homebrew)
brew install fabriziosalmi/flareover/flareover

# Linux/macOS: verified installer (downloads the release for your OS/arch, checks its sha256)
curl -fsSL https://raw.githubusercontent.com/fabriziosalmi/flareover/main/install.sh | sh

# …or from source (single static binary, pure Go, zero external deps)
go install github.com/fabriziosalmi/flareover/cmd/flareover@latest

Building from source requires Go 1.25+. Release binaries (linux/macOS/windows · amd64/arm64) ship with an SBOM and a checksums.txt signed keyless via Sigstore/cosign. Verify it with the command in each release's notes. flareover version prints the build tag.

Usage

flareover <phase> [args]
Phase What it does
zones List every zone the read-only token can see.
extract <domain|zone-id> Read a live Cloudflare zone (read-only API) into a snapshot JSON.
assess <snapshot.json> Classify into an AUTO/ASK/MANUAL coverage report (--md, --json, --html).
resolve <snapshot.json> Walk the ASK questions into a decisions.lock (--defaults, --merge).
cost <snapshot.json> Cloudflare tier/add-on cost vs a flat EU stack (--vps <eur/mo>).
prepare <snapshot.json> Generate the artifacts (Caddyfile, caddy-waf rules, PowerDNS zone, egress, mesh) plus a MIGRATION.md report: a table of every Cloudflare element found and exactly what it became (1:1 AUTO / ASK / MANUAL). --validate proves they parse; --edge-provider <key> emits an edge cloud-init (and, for Scaleway/OVHcloud, a script that creates and boots the edge instance from it).
doctor … Read-only pre-flight: every target reachable/authorized/configured? GO/NO-GO before you provision.
providers List EU edge providers with their honest sovereignty tier (EU-owned vs US-operator/EU-region).
provision … Stand the target up via APIs (--pdns-url, --certmate-url).
present … Parity gate: live edge vs staged edge (--after-addr).
execute … Orchestrate the phases live up to the gated cutover.
storage … Migrate object storage → MinIO + rclone plan (--extract-r2, --extract-s3).
guard --url … Failguards watchdog: health-watch + rollback/failover (--on-unhealthy, --interval, --once).
# 1. Assess a zone snapshot into an honest coverage report
flareover assess zone.snapshot.json

# 2. Generate the target-stack artifacts for the AUTO + answered-ASK surface
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

# Secrets are read from the environment only, never passed on argv (so they
# can't leak via ps / /proc / shell history):
export PDNS_API_KEY=… CERTMATE_TOKEN=…

# 2b. Prove the artifacts parse, and pre-flight the target before touching it
flareover prepare zone.snapshot.json --edge-ip 203.0.113.10 --out ./out --validate
flareover doctor --pdns-url http://pdns:8081 \
  --certmate-url http://certmate:8000 \
  --spm-url http://spm:5001 --check-caddy   # GO / NO-GO, exit 0 only when ready

# 3. Stand up the live target (PowerDNS zone + DNSSEC, CertMate wildcard via DNS-01)
flareover provision --snapshot zone.snapshot.json --decisions decisions.lock \
  --edge-ip 203.0.113.10 \
  --pdns-url http://pdns:8081 --nameservers ns1.example.eu,ns2.example.eu \
  --certmate-url http://certmate:8000 \
  --certmate-dns cloudflare   # pre-cutover: NS still at the source → solve DNS-01 there

# 4. Parity gate before you flip anything
flareover present --snapshot zone.snapshot.json --after-addr 203.0.113.10:443

--decisions is a JSON map of ASK question id → answer. Anything still unanswered is simply not generated (and stays visible as ASK in assess), never guessed. The default stack profile is caddy.

Status

End-to-end and proven live. All five phases are implemented, and every core target adapter has been exercised against a real running service, not just mocks. Each one caught real bugs a mock could not:

Adapter Live proof
PowerDNS zone + rrsets + DNSSEC provisioned on a live PowerDNS
CertMate a real, publicly-trusted wildcard certificate issued via DNS-01
MinIO full extract → generate → provision → re-extract round-trip
WireGuard mesh a real encrypted edge↔origin link, origin inbound-free
secure-proxy-manager generated egress script applied against the live API, state verified

The hand-rolled protocol code (AWS SigV4, PowerDNS rrsets, WireGuard X25519 keys, CertMate DNS-01) is verified against the real endpoints.

Honest tiering of the managed adapters. The five above are live-proven (Tier A). The managed DNS backends beyond PowerDNS, Scaleway · OVH · Gandi · Leaseweb · Hetzner (EU-owned) and Route 53 · Cloud DNS · Azure (US-operated), and the managed S3 destinations (Scaleway · OVH · Contabo · Aruba), plus the terraform/hetzner/ edge module, are Tier B: verified against each vendor's documented API and httptest/terraform validate, not yet exercised against the live service. They are flagged as such and promoted to Tier A only after a real run (see docs/live-proof.md); nothing claims a live proof it hasn't earned.

The free-tier WAF mainstays are mapped, AUTO, to caddy-waf: country and ASN blocking (block_countries / block_asns, L3 source scoped) and rate limiting: a per-IP limit → rate_limit; a rule keyed on something other than the client IP → one ASK. The one honest caveat on rate limits is global counting: Cloudflare enforces a threshold across its whole anycast edge, so several independent self-hosted edge nodes each count locally (the effective limit scales with the node count) unless they share a counter: a distributed-systems limit, noted rather than faked.

Deliberately out of scope because no faithful deterministic mapping exists: geographic traffic steering (sending users to different origins by region: a paid load-balancing feature, distinct from country blocking above) and cache-hit-ratio parity, surfaced honestly, never faked.

See deploy/ for the one-command docker-compose landing zone, and docs/deploy-hardened.md for the hardened bare-metal blueprint and the gotchas learned the hard way.

License

Copyright (C) 2026 Fabrizio Salmi. Licensed under AGPL-3.0-only: you may use, study, modify, and redistribute it, but network use counts as distribution, so derivative services must offer their source under the same terms.

Directories

Path Synopsis
cmd
flareover command
Command flareover is the CLI for the deterministic Cloudflare → EU-self-hosted migration engine.
Command flareover is the CLI for the deterministic Cloudflare → EU-self-hosted migration engine.
internal
cfexpr
Package cfexpr holds the small, shared interpreters for Cloudflare's rules language and action parameters.
Package cfexpr holds the small, shared interpreters for Cloudflare's rules language and action parameters.
classify
Package classify is the verdict engine.
Package classify is the verdict engine.
cloudflare
Package cloudflare's extractor turns a live zone into a Snapshot by calling the Cloudflare REST API v4 read-only.
Package cloudflare's extractor turns a live zone into a Snapshot by calling the Cloudflare REST API v4 read-only.
cost
Package cost estimates the monetary picture of a migration: which Cloudflare paid tiers/add-ons the captured configuration implies, versus a flat EU-stack cost.
Package cost estimates the monetary picture of a migration: which Cloudflare paid tiers/add-ons the captured configuration implies, versus a flat EU-stack cost.
docsgen
Package docsgen renders documentation straight from the engine, so the docs can never claim coverage the code does not deliver.
Package docsgen renders documentation straight from the engine, so the docs can never claim coverage the code does not deliver.
doctor
Package doctor is the pre-flight: before you provision, it checks (read-only) that every target service is reachable, authorized, and configured the way the provisioning step will need it.
Package doctor is the pre-flight: before you provision, it checks (read-only) that every target service is reachable, authorized, and configured the way the provisioning step will need it.
guard
Package guard is the Failguards muscle as a running loop.
Package guard is the Failguards muscle as a running loop.
ir
Package ir defines the provider-agnostic Intermediate Representation of a migration.
Package ir defines the provider-agnostic Intermediate Representation of a migration.
objstore
Package objstore migrates object storage off a hyperscaler (Cloudflare R2 or AWS S3) onto EU-sovereign MinIO.
Package objstore migrates object storage off a hyperscaler (Cloudflare R2 or AWS S3) onto EU-sovereign MinIO.
parity
Package parity is the Failguards muscle: it proves the new edge behaves like Cloudflare before any cutover is allowed.
Package parity is the Failguards muscle: it proves the new edge behaves like Cloudflare before any cutover is allowed.
plan
Package plan builds the provider-agnostic ir.Plan from a Cloudflare snapshot plus the answers to any ASK questions.
Package plan builds the provider-agnostic ir.Plan from a Cloudflare snapshot plus the answers to any ASK questions.
provider
Package provider is the honest catalogue of places to put an edge node.
Package provider is the honest catalogue of places to put an edge node.
render
Package render turns the engine's reports into terminal output that reads at a glance: colored verdict badges, boxed summaries, aligned columns.
Package render turns the engine's reports into terminal output that reads at a glance: colored verdict badges, boxed summaries, aligned columns.
report
Package report holds the verdict vocabulary and the honest coverage report that the Assessment phase produces.
Package report holds the verdict vocabulary and the honest coverage report that the Assessment phase produces.
runbook
Package runbook renders the human-facing migration document: the assessment summary, the generated artifacts, the ordered cutover steps (as flareover commands), and the rollback.
Package runbook renders the human-facing migration document: the assessment summary, the generated artifacts, the ordered cutover steps (as flareover commands), and the rollback.
stack
Package stack assembles concrete StackProfiles from the target generators.
Package stack assembles concrete StackProfiles from the target generators.
target
Package target defines the adapter contracts that turn a provider-agnostic ir.Plan into concrete configuration for a specific EU-stack tool.
Package target defines the adapter contracts that turn a provider-agnostic ir.Plan into concrete configuration for a specific EU-stack tool.
target/azuredns
Package azuredns renders and provisions the authoritative zone on Azure DNS.
Package azuredns renders and provisions the authoritative zone on Azure DNS.
target/bunnydns
Package bunnydns renders the authoritative zone for bunny.net's managed EU DNS: the alternative to self-hosting PowerDNS.
Package bunnydns renders the authoritative zone for bunny.net's managed EU DNS: the alternative to self-hosting PowerDNS.
target/caddy
Package caddy renders an ir.Plan into a Caddyfile for the default flareover stack profile (Caddy + caddy-waf + souin cache).
Package caddy renders an ir.Plan into a Caddyfile for the default flareover stack profile (Caddy + caddy-waf + souin cache).
target/caddywaf
Package caddywaf renders the caddy-waf rule corpus (rules.json) from the plan's WAF policy.
Package caddywaf renders the caddy-waf rule corpus (rules.json) from the plan's WAF policy.
target/certmate
Package certmate is the certificate adapter: it drives a CertMate instance to issue certs via DNS-01, which is what unlocks the two things Caddy's built-in HTTP-01 cannot do: wildcard certificates and an EU certificate authority (Actalis).
Package certmate is the certificate adapter: it drives a CertMate instance to issue certs via DNS-01, which is what unlocks the two things Caddy's built-in HTTP-01 cannot do: wildcard certificates and an EU certificate authority (Actalis).
target/clouddns
Package clouddns renders and provisions the authoritative zone on Google Cloud DNS.
Package clouddns renders and provisions the authoritative zone on Google Cloud DNS.
target/gandidns
Package gandidns renders and provisions the authoritative zone on Gandi LiveDNS (EU-owned, France).
Package gandidns renders and provisions the authoritative zone on Gandi LiveDNS (EU-owned, France).
target/hetznerdns
Package hetznerdns renders and provisions the authoritative zone on Hetzner DNS (EU-owned, Germany: a sovereign option, unlike the US-operated Route 53 / Cloud DNS / Azure DNS bridges).
Package hetznerdns renders and provisions the authoritative zone on Hetzner DNS (EU-owned, Germany: a sovereign option, unlike the US-operated Route 53 / Cloud DNS / Azure DNS bridges).
target/leasewebdns
Package leasewebdns renders and provisions the authoritative zone on Leaseweb DNS (EU-owned, Netherlands).
Package leasewebdns renders and provisions the authoritative zone on Leaseweb DNS (EU-owned, Netherlands).
target/mesh
Package mesh generates a sovereign WireGuard link between one or more public edge nodes and the isolated origin: the substitute for a Cloudflare Tunnel, which would route a leave-Cloudflare migration back through Cloudflare.
Package mesh generates a sovereign WireGuard link between one or more public edge nodes and the isolated origin: the substitute for a Cloudflare Tunnel, which would route a leave-Cloudflare migration back through Cloudflare.
target/ovhdns
Package ovhdns renders and provisions the authoritative zone on OVHcloud's managed DNS (EU-owned, France).
Package ovhdns renders and provisions the authoritative zone on OVHcloud's managed DNS (EU-owned, France).
target/powerdns
Package powerdns renders the authoritative zone from the plan's DNS intent.
Package powerdns renders the authoritative zone from the plan's DNS intent.
target/route53
Package route53 renders and provisions the authoritative zone on AWS Route 53.
Package route53 renders and provisions the authoritative zone on AWS Route 53.
target/scalewaydns
Package scalewaydns renders and provisions the authoritative zone on Scaleway's managed DNS (Domains and DNS, EU / France): an EU-owned alternative to self-hosting PowerDNS.
Package scalewaydns renders and provisions the authoritative zone on Scaleway's managed DNS (Domains and DNS, EU / France): an EU-owned alternative to self-hosting PowerDNS.
target/spm
Package spm generates the egress-shield configuration for secure-proxy-manager: the outbound counterpart almost no migration touches.
Package spm generates the egress-shield configuration for secure-proxy-manager: the outbound counterpart almost no migration touches.
target/zonefile
Package zonefile is the shared BIND rendering used by every DNS target.
Package zonefile is the shared BIND rendering used by every DNS target.
validate
Package validate proves that generated artifacts actually parse, turning "faithful by construction" into "faithful and checked".
Package validate proves that generated artifacts actually parse, turning "faithful by construction" into "faithful and checked".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL