Standing up a Cloudflare One stack means a tunnel, an Access policy, an Access app, a DNS record, and a few Gateway rules. The pieces are simple. Getting the syntax right is not.
ZTNA Kit turns a short form into ready-to-run Terraform and API scaffolding, with the version traps and escaping quirks already handled. It never asks for your API token.
The capability was never missing. The time goes somewhere else.
Provider v4 and v5 examples sit side by side with no signpost. Copy the wrong one and you get resource names that no longer exist.
Each resource is documented on its own page. Nothing shows a tunnel, an Access app, and a Gateway rule working together.
A missing catch-all ingress rule, a snake_case field where the API wants camelCase, a $ that Terraform interpolates. All quiet until they are not.
Three steps, no token at any point.
Account and zone IDs, the public hostname, and the local service behind it. Add extra hostnames to serve several apps from one tunnel.
An identity provider, a service token, Gateway DNS filtering, a private network route, remote state. A panel counts every resource before you create anything.
Copy any file, or download setup.sh to write the whole folder at once. Then terraform apply or ./deploy.sh.
chmod +x setup.sh && ./setup.sh # writes every file export TF_VAR_cloudflare_api_token="<scoped-token>" terraform init && terraform apply terraform output -raw tunnel_run_token # to run the connector
Every item on the left cost real time to find. Every item on the right is now automatic.
cloudflare_tunnel and cloudflare_record no longer exist in v5.
Pins ~> 5 and emits the current resource names.
http_status:404 as the last rule.
$ in a Gateway list expression.
Uses format() so the literal $ survives.
content, not value, pointing at the tunnel.
Writes the CNAME to <tunnel_id>.cfargotunnel.com.
.gitignore so it never reaches a commit.
A complete folder, not a snippet.
Tunnel, ingress, identity provider, Access policy and app, DNS, Gateway rules, and optional remote state in R2 or Terraform Cloud.
A pure API path with curl and jq if you would rather not use Terraform, plus environment setup and a README with the token scopes.
The configurator never asks for an API token and makes no network calls. Terraform reads the token from TF_VAR_cloudflare_api_token and the script reads CLOUDFLARE_API_TOKEN, both from your shell. Your profile is saved in your browser and encoded into the share link, so no server ever sees it.