Skip to content
downpipes docs

Backing up and restoring your Cloudflare account configuration

Most backup products treat your Cloudflare account as the place a backup runs, not as a thing that itself needs backing up. But your DNS, your WAF rules, your Access policies and your zone settings are configuration you would have to rebuild by hand if they were lost or wrongly changed. The cf-config source captures that configuration as a first-class source type, alongside your KV, R2, D1 and Secrets Store data and your Worker code, so a snapshot of your account’s posture is part of the same signed, verified archive as your data.

This page is the canonical home for the cf-config source and its tiered restore. It covers what configuration is captured, the read-only credential the backup uses, the separate one-shot edit token a restore needs, and exactly what auto re-applies versus what you must re-create out of band.

The headline scope is one registry of 313 Cloudflare config surfaces. Of those, 60 auto-restore in-band today: the engine diffs your live config against the snapshot and re-applies straight back into your account through the console. The remaining 253 are backup-and-preview only: they are captured in full and verified recoverable, and a restore previews the tier-specific guidance for re-applying each one out of band (dependency order, or a re-provision checklist), rather than a diff against live, which stays specific to the 60 in-band surfaces. The sections below explain why the split falls where it does.

What cf-config captures

A cf-config downpipe snapshots one Cloudflare account, and optionally one zone within it. Each configuration surface backs up as a single archived record, where the record name is the surface id and the value is that surface’s configuration as canonical JSON. The surface registry is deliberately generous: it covers everything configuration-shaped so that an account simply gets a marker for any product it does not use, rather than the snapshot failing.

The surfaces span the configuration you would expect to rebuild after an incident.

DNS and core

DNS records, DNS settings, zone settings, managed transform headers and URL normalisation.

Security and WAF

Zone and account rulesets and WAF, page rules, firewall access rules, the legacy filters and firewall rules, and Page Shield policies.

Traffic and delivery

Workers routes, load balancers, waiting rooms, Spectrum apps, custom hostnames, custom error pages and zone email routing.

TLS and certificates

The certificate-pack and custom-certificate inventory and authenticated origin pulls. Private keys are never captured.

Zero Trust and Access

Access apps, groups, identity providers, service tokens, custom pages and tags, Gateway rules, lists and configuration, tunnels and device posture and settings policies.

Account and alerting

Account settings, rule lists, account members and roles, DNS Firewall, load-balancer pools and monitors, address maps, IP prefixes, mTLS certificates, notification policies and webhooks, and Turnstile.

Configuration is the scope, not data and not runtime. Your KV namespaces, R2 buckets, D1 databases and Secrets Store entries are their own data source types, captured separately. Logs, analytics, Stream and Images content and compute deployments are out of scope. Two things are excluded by design: billing, and the Registrar (which would need the Global API Key, a credential the engine deliberately never holds).

Worker code is a separate source

The cf-config source captures your account’s settings, not your Worker scripts. Worker code, its bindings metadata and a version inventory are the separate Workers source, whose restore is re-provision (you re-deploy from the verified snapshot). For what gets captured per source type, see sources overview.

Choosing what to capture: mode and scope

Two controls decide how much of your Cloudflare configuration a downpipe backs up.

The capture mode is Auto or Manual. Auto, the default, backs up the configuration surfaces actually in use: the engine discovers them, refreshes that set daily, and a run reads only what exists, so it stays cheap as your configuration changes. The downpipe’s drawer shows the current mode, when the surfaces were last discovered and how many are in use, unused or unavailable, with a Rediscover control that forces a fresh probe. Manual instead backs up exactly the surfaces you tick, for when you want a fixed, audited set rather than whatever is live. An existing downpipe with a non-empty surface list reads as Manual; an empty list reads as Auto.

The scope, when you protect a zone, is one of three presets. “Account configuration only” backs up the account-wide settings, the Zero Trust, notifications and rulesets surfaces, about one hundred and ninety-five of them, and no per-zone configuration. “This zone only” backs up just the ticked zone’s DNS, WAF and zone settings. “Account + this zone” backs up both. Choosing a scope when you protect several zones at once avoids duplicating the shared account configuration into every zone’s downpipe.

The credential model

Backup and restore use two different credentials, and the asymmetry is the point.

Backup reads the Cloudflare REST API with the engine’s existing read-only discovery token, the same token a self-hoster widens to the “Read all resources” template for full per-zone coverage. There is no per-downpipe key and no edit scope on the backup path. The account and zone a downpipe covers are fixed for its life; only the surface selection is editable.

Restore needs a separate, edit-scoped Cloudflare API token, and you supply it in the restore request itself. That token is never stored, never written to a log, and never folded into the dual-control approval hash. Only the non-secret account id and optional zone id are bound into the approval. So a restore approval can be shown, copied and recorded without ever leaking the edit credential.

Not being stored has one practical consequence worth planning for. The token lives only in the restore form you typed it into. Reload that screen, or come back to it later, and the field is empty; enter the token again and build the plan again. That costs you nothing beyond the rebuild, because the token is not part of the plan hash: the same request hashes identically, so an approval already granted against it still matches (restorePlanHash, console/src/lib/api/helpers.ts, recomputed server-side in engine/src/admin/approvals.ts).

The account id and zone id are non-secret Cloudflare identifiers, each a 32-character hexadecimal string. Your account id is on the Cloudflare dashboard as the Account ID in the right-hand column of an account’s overview; a zone id is on that zone’s own overview page in the API panel. Supply the account id that the config was backed up from. The zone id is required only for zone-scoped surfaces such as DNS and page rules, so leave it blank for an account-only restore.

Why a one-shot edit token

The no-custody model means the engine holds no standing write access to your Cloudflare account. An in-band config restore is the one moment write access is needed, so you hand the engine a scoped edit token for that single restore and rotate it afterwards. The backup discovery token stays read-only at all times.

Which permissions the edit token needs

You create this token the same way as any Cloudflare API token: My Profile, then API Tokens, then Create Custom Token. The scopes it needs follow directly from the surfaces that write back in-band, because each one calls a specific Cloudflare API. Grant each permission below at the Edit access level, and only for the surfaces you actually intend to restore.

In-band surface Permission to grant (Edit) Level
DNS records DNS Zone
Zone settings, and the six individually written zone settings Zone Settings Zone
Page rules Page Rules Zone
Zone firewall access rules Firewall Services Zone
Account firewall access rules Account Firewall Access Rules Account
Zone rulesets and WAF Zone WAF Zone
Account rulesets and WAF Account WAF Account

This table covers seven families, and 60 surfaces restore in-band

The permissions above are the ones the most commonly restored surfaces need. They are not the full set the 60 in-band surfaces call between them, which reaches into Zero Trust, Email Routing, Magic, AI Gateway, Page Shield, Zaraz and more, each with its own Cloudflare permission.

This matters because of how the apply fails. A surface your token cannot write is skipped, not refused, so a token built from this table alone and pointed at a whole-account config restore will silently skip most of the in-band surfaces, and the restore reports normally. A partial config restore that reads as a complete one is worse than one that stops.

Build the token from the dry run rather than from this table. The dry run writes nothing, needs only read scope, and names every surface it could not read or write with a per-surface reason, so it tells you exactly which further Edit permissions the apply will want. Then grant those, and read the apply’s own per-surface outcomes before you call the restore done.

You do not have to grant all of them. The apply works surface by surface and fails open per item, so a surface your token cannot write is skipped with a coarse “the token was rejected or lacks the edit scope” reason rather than failing the rest of the restore. Scope the token to the surfaces you are restoring, to the one account, and to the specific zone for the zone-level permissions, then delete it once the restore is done.

The rulesets surface spans more than WAF. The WAF permissions above cover your security rulesets; if your account also keeps other ruleset-based configuration, such as transform rules or configuration rules, grant the edit permission for those ruleset products too, since the engine re-applies each changed ruleset by its own id.

A dry run is different: it only reads your live config to compute the diff and writes nothing, so a read-scoped token is enough to preview a config restore. The Edit scopes above are needed only for the apply. The single console field is labelled an edit token because the apply is what it is there for.

How backup works

A cf-config run produces one signed, encrypted record per in-scope surface, written through the same unchanged seal pipeline as every other source, so a config snapshot carries the same integrity guarantees as your data backups.

The backup is fail-open per surface. A surface the discovery token cannot read, because of a missing scope, a product not on your plan or a deprecated endpoint, becomes an explicit unavailable marker rather than failing the whole snapshot. The archive stays complete, with one record per attempted surface, and it honestly distinguishes “unavailable, and why” from a genuinely empty surface. Only if every attempted surface fails does the run fail loudly, because that means a broken token or the wrong account, not a per-surface gap.

List-shaped surfaces are paginated to exhaustion, so a zone with thousands of DNS records or firewall rules is captured in full rather than truncated at the first page. There is a hard ceiling on pages followed, so a buggy endpoint can never spin forever. If a surface still has more pages at that ceiling, the backup does not silently drop the tail: it records a visible truncated marker carrying how many pages and records it did read, and logs it. Each surface also has a per-surface buffered-size cap of 64 MiB, far above any realistic config surface; a surface whose serialised JSON exceeds it is marked unavailable rather than risking the Worker’s memory.

A truncated or unavailable surface is refused for restore

A restore decodes each verified config record before diffing or writing it. If a record carries a truncated or unavailable marker rather than real configuration, the restore refuses that surface with an explicit “snapshot incomplete” reason and re-run-a-backup guidance, never diffing or writing a partial snapshot against your live account.

The three restore tiers

Every surface in the registry carries a restore tier that describes how it can be restored. The tier is the honesty contract: it is surfaced in the restore plan so you see, per surface, whether an apply re-applies it for you or hands you a checklist. The split across the registry is idempotent 176, ordered 76 and re-provision 61.

Tier Behaviour on restore Example surfaces What you do
Idempotent The 60 with an in-band write function preview a live diff (the engine reads live config, diffs the snapshot and writes only the differing items, one at a time) and re-apply through the console. The rest replay cleanly in principle but have no in-band write function yet: captured and verified recoverable, replayed out of band via the Cloudflare API from the snapshot, with no diff preview. DNS records, zone settings, page rules, firewall access rules, zone and account rulesets and WAF, Turnstile, Gateway lists For an in-band surface, preview the live diff, then approve and apply it in the console. For the rest, replay it out of band from the verified snapshot via the Cloudflare API.
Ordered Cannot be replayed by a flat item-by-item apply, because the items have dependencies and server ids that a fresh account will not have. Access apps, groups and Gateway rules, load balancers, pools and monitors, custom hostnames, logpush jobs, notification policies Re-create in dependency order out of band, from the verified snapshot, via the Cloudflare API.
Re-provision Carries write-only values that the backup never captured, so a restore can only emit a checklist of what to re-provision, never replay it. Certificate packs and custom certificates, Access identity providers and service tokens, tunnels, mTLS certificates, account members and roles Re-provision the secrets or keys from the checklist; the snapshot holds everything around them.

Secrets and private keys are never captured

Certificate private keys, Access service-token secrets, identity-provider client secrets and tunnel secrets are write-only values that the Cloudflare API never returns on read, so the backup never holds them. The re-provision tier exists precisely because these surfaces cannot be replayed: the snapshot captures their surrounding configuration and names, and you re-provision the secret material yourself. Do not read the re-provision tier as “these secrets are recoverable”.

Exactly which surfaces auto-restore today

Auto-restore in-band means the engine re-applies the surface straight back into your live account, through the console, as part of a restore apply. Today that is 60 of the 313 surfaces, and they are the idempotent surfaces that have a diff-driven write function:

They span far more of Cloudflare than the DNS and WAF surfaces this page used to name. By family:

DNS and core, 13. DNS records, DNS settings, zone settings, managed transform headers, URL normalisation, account DNS settings, secondary DNS ACLs, and six single zone settings that Cloudflare exposes only at their own endpoints and omits from the aggregate settings response: automatic origin TLS key exchange, fonts, origin maximum HTTP version, origin TLS compliance, Speed Brain and automatic SSL mode.

Security and WAF, 8. Zone rulesets and WAF, page rules, firewall access rules, Zone Lockdown rules, User Agent Blocking rules, Page Shield settings, Leaked Credential Checks status and Bot Management.

Zero Trust, 13. Access tags, Gateway lists, Gateway configuration, Gateway logging settings, Zero Trust device settings, Zero Trust connectivity settings, device managed networks, device IP profiles, the global WARP resilience override, the WARP device policy, DLP email rules, tunnel virtual networks and the zone Zero Trust organisation.

Account settings and rules, 6. Account rulesets and WAF, account rule lists (the named IP and ASN lists that WAF and Gateway rules reference), account firewall access rules, Workers account settings, and both the account and zone custom page assets.

Everything else, 20. Email routing, its catch-all rule and the DMARC report configuration; Workers Observability saved queries; Universal SSL, Origin TLS client auth and cache origin post-quantum encryption; the Zero Trust organisation and Access key configuration; Certificate Transparency alerting; the zone RUM toggle, Smart Tiered Cache, Smart Shield and Zaraz configuration; Magic Network Monitoring rules, Magic BGP settings and Magic BGP filter profiles; AI Gateway gateways and AI Search namespaces; and KV namespace configuration, meaning the namespace itself and its title, not its contents.

For the per-surface inventory, with each surface’s scope and restore tier and an explicit not-captured list, read the config surface reference. That table is generated from the same registry the backup adapter and the restore sink consume, so it is the list to check a specific surface against.

Each of those has been proven against a real Cloudflare account rather than inferred from the API schema: an object is created, captured, deleted, restored from the snapshot, and the restore is then run a second time to confirm it converges instead of creating a duplicate.

A further 25 surfaces carry a write path that is not in that 60. Those writers were generated from Cloudflare’s published schema, which fixes the endpoint and the method but not which field identifies an item, and that is what decides whether a restore writes to the right object. They are off by default, so a restore that does not name a scope will not touch them. Naming one puts it in the approval hash, so an approver sees exactly which unproven surface they are authorising.

The remaining 253 surfaces are backup-and-preview only. They are captured in full and verified recoverable, and you re-apply them out of band: ordered surfaces re-created in dependency order, and re-provision surfaces rebuilt from their checklist, both from the verified snapshot. None of the 253 carry a diff preview against live today; that is specific to the 60 in-band surfaces. The console is explicit about this: it offers in-band re-apply for DNS, page rules, rulesets and firewall, and says plainly that other configuration stays out of band for deliberate re-provisioning.

In-band re-apply is additive, not a wholesale sync

The in-band surfaces re-apply by diffing live against the snapshot and writing only the differing items, each one created or updated on its own. The engine never writes a whole collection in one call, and it never deletes a live item the snapshot happens to omit. A live-only item is reported as left in place, not as a deletion. This is deliberate: deleting live records a backup does not contain would be destructive, so the pruning behaviour is hard-coded off.

The restore workflow and its guarantees

A cf-config restore rides the same restore path as a data restore, with the same dry-run default, the same dual-control gate and the same additive discipline. You opt into the cf-config part by supplying an edit token and the account (and zone for zone-scoped surfaces) in the restore request; leave them blank and config records stay out of band exactly as a data-only restore would treat them.

  1. Build the dry-run plan

    The dry-run is the default and writes nothing. For each in-band surface in scope, the engine reads your current live config and diffs it against the verified snapshot, then returns a per-surface summary of what an apply would change, for example “2 to add, 1 to change”, with any live-only items reported as left in place. A read or diff that fails for one surface is reported out of band with a coarse reason rather than failing the plan.

  2. Raise a request

    To apply, a requester with the request capability raises a restore request bound to the plan. The engine recomputes the plan hash server-side, binding the run, the selectors and the cf-config account and zone, but never the token. A changed plan yields a different hash and re-arms the gate.

  3. A distinct approver signs it

    A second authorised person with the approve capability approves that exact plan hash. The approver must differ from the requester on stable identity, the engine refuses a self-approval, and the approval is single-use with a fixed 24-hour expiry. Holding the apply role is never enough on its own.

  4. Apply

    Have your authenticator to hand for this step. Confirming the apply demands a fresh passkey assertion: the engine’s step-up gate reads the request’s own confirm flag, so the dry run passes freely and the write does not. It is checked after the role gate and before anything is reserved or written, so an unfresh apply is refused before any byte lands. A caller on the break-glass token or arriving through Cloudflare Access is exempt, each carrying its own possession check.

    With a usable approval in place, the apply re-verifies every record’s plaintext hash before any write, then re-applies each in-band surface to your live account with the edit token, additively. A surface write that fails is recorded as a per-surface failure so the result reflects it, never a silent drop.

The step-up is worth planning around rather than meeting by surprise, because the approver step in front of it routinely takes longer than the freshness window the engine allows. Get the approval first, then re-authenticate, then apply, rather than re-authenticating and waiting on an approver.

An account-scope config restore hits the in-account record ceiling

An in-account restore is bounded at 200 records over the combined in-scope window, and a cf-config source produces one record per surface. So a restore selecting a whole 313-surface account snapshot is refused outright rather than trimmed. Restore a bounded slice by naming the surfaces you need, or recover the full run offline with the downpipe reader, which runs on your own machine with no Worker limits. The refusal names both routes.

The additive guarantee is the load-bearing safety property. An in-band apply creates or updates only the items that differ, one at a time, so one item the Cloudflare API rejects skips itself rather than failing the rest. It never replaces a whole collection, and it never deletes a live item the snapshot omits. A re-run converges: items that already match are skipped, and matching by a natural key rather than only by server id means a re-run does not duplicate.

Two refusals bound the path further. A truncated or unavailable snapshot is refused for restore, so a partial backup is never diffed or written against live config. And in the strict break-glass-only posture, where the engine holds no in-account read-back key, the console still restores: your browser supplies the break-glass key locally to open the one run you are restoring, and only a 32-byte per-run master, never the break-glass private key itself, reaches the engine. Only when neither an operational key nor a browser-supplied master is available does a restore return not-ok and write nothing, leaving offline recovery as the fallback.

cf-config restore is supervised-first, and not on the live demo

In-band config write-back is wired on engine main, but it is not deployed to the live demo today. The engine does guard against a wrong or drifted account: it compares the account (and zone) you supply at restore time against the signed origin recorded on the archive, warns on a dry run when they differ or the origin cannot be verified, and refuses the apply outright unless you explicitly confirm the target account. That guard makes a cross-account restore a deliberate choice rather than a silent mistake, but it does not replace care: treat the first live in-band config restore as a supervised operation against a known account and zone, with an edit token scoped only to the configuration you are restoring. Do not read this as cf-config restore being a hands-off feature on the demo yet.

How the engine orders config writes against data writes

A restore can mix data records and cf-config records in one run. The engine keeps the verify-everything-before-write discipline across both. In a dry-run, the data records are verified read-only and the cf-config diffs are computed read-only; nothing is written. In an apply, the engine first verifies every in-scope record’s plaintext hash, then writes the data records back, and only then re-applies the cf-config surfaces, re-verifying each config record’s hash immediately before it is parsed and written. So a cf-config write can never land before the data set has been proven, and a tampered config record is caught before any production write.

The cf-config write itself is per-surface and fail-open per item. The zone-settings write patches each changed setting individually, so an un-settable setting (an ACM-gated cipher, for example) skips itself. The list surfaces (DNS, page rules, firewall access rules) read the current live list, match items to the snapshot by a stable natural key, and create or update only the differences. The rulesets surfaces update each existing ruleset’s rule list in place by its own id; a phase entrypoint that does not yet exist live is reported in the preview but never blind-created, because creating an entrypoint is a re-provision concern.

Every reason the engine returns on the cf-config path is coarse and secret-free. The token, the account id and any field value never appear in a reason or a log; you get an enumerated bucket such as “the token was rejected or lacks the edit scope” or “the snapshot for this surface is incomplete”.

Last updated .