Skip to content

Cloudflare Tunnel and Access Setup

This page defines the one-time Cloudflare setup for Anuva Development-stage Web and documentation previews. It covers the two Windows development machines, their remotely managed tunnels, published application routes, Cloudflare Access policy, local connector credentials, and verification.

It does not configure Early Users or Production infrastructure. The canonical documentation publisher remains a separate manual workflow.

Phase 6 machine replication verifies the existing machine-two tunnel, token file boundary, twelve published routes, certificates, and Access behavior read-only. It does not authorize creating or changing a Cloudflare object. A missing or incorrect tunnel, route, DNS record, Access application, policy, certificate, or token is a stop condition requiring a focused amendment. See the Windows Development Machine Bootstrap.

Target architecture

flowchart LR
    User["Approved developer\nbrowser + email OTP"]
    Access["Cloudflare Access\nself-hosted applications"]
    DNS["Cloudflare DNS\npublished hostnames"]
    T1["anuva-machine1\nremote-managed tunnel"]
    T2["anuva-machine2\nremote-managed tunnel"]
    M1["Machine 1\nloopback services"]
    M2["Machine 2\nloopback services"]
    Canonical["anuva.girishd.com\ncanonical aggregate"]

    User --> Access --> DNS
    DNS --> T1 --> M1
    DNS --> T2 --> M2
    Access --> Canonical

Use one tunnel per machine. Never run both machines as replicas of the same tunnel: replicas are interchangeable origins, while the two Anuva machines may serve different working trees.

The tunnel configuration and hostname routes are remotely managed in Cloudflare. cloudflared runs as an interactive Anuva-managed process rather than an always-on Windows service. This is deliberate: working-tree previews should be exposed only while the corresponding development session is active.

Ownership boundaries

Concern Owner
Domain, DNS, tunnel creation, routes, certificates Cloudflare Dashboard
Access applications, identity provider, policies, sessions Cloudflare Zero Trust Dashboard
Tunnel token creation and rotation Cloudflare Dashboard plus the developer
Token file and non-secret machine configuration Each Windows development machine
Local service startup, connector process, health checks, logs Anuva CLI
MkDocs content and URL calculation Repository docs and Anuva CLI
Canonical documentation build and push Explicit anuva docs publish workflow

The Anuva CLI must not create or delete tunnels, DNS routes, Access applications, policies, identity providers, certificates, or tunnel tokens.

Prerequisites

Before configuring a machine, confirm:

  • girishd.com is an active zone managed by Cloudflare DNS;
  • a Cloudflare Zero Trust organization exists;
  • the approved developer email address is known;
  • cloudflared is installed from an official Cloudflare distribution and cloudflared version succeeds;
  • each local origin can listen on 127.0.0.1 at its configured port; and
  • outbound traffic to Cloudflare Tunnel endpoints on port 7844 is permitted.

Certificate coverage

All Development preview routes use single-level hostnames under girishd.com, such as main1.girishd.com and anuva2.girishd.com. This keeps them within the normal *.girishd.com wildcard depth instead of requiring multi-level wildcard coverage.

Before enabling the routes, confirm Cloudflare shows active edge-certificate coverage for every configured hostname. Do not bypass certificate validation or switch a route to plain public HTTP to work around a certificate problem.

Configure Cloudflare Access first

Create Access protection before publishing tunnel routes. A published application without an Access application is reachable from the Internet.

Enable email one-time PIN

The current Anuva login method is email OTP. New Cloudflare Zero Trust accounts do not add OTP automatically.

In the Cloudflare Dashboard:

  1. Go to Zero Trust > Integrations > Identity providers.
  2. Select Add new identity provider.
  3. Select One-time PIN and save it.
  4. Confirm the approved mailbox can receive mail from noreply@notify.cloudflare.com.

Do not store email credentials or OTP codes in Anuva configuration or Codex chat.

Create the reusable allow policy

Create a reusable policy named Anuva solo developer:

Field Value
Action Allow
Include selector Emails
Value The exact approved developer email address

Do not use Everyone, Emails ending in for a public mail domain, or Login Methods = One-time PIN. The last option accepts any valid OTP identity unless a separate identity condition narrows it.

Test the exact email address with Cloudflare's policy tester before attaching the policy to applications.

Create Access applications

Create these self-hosted applications and attach the reusable allow policy:

Application Public hostname Suggested session duration
Anuva Development machine1 anuva1.girishd.com, main1.girishd.com, bento1.girishd.com, web1.girishd.com, python1.girishd.com, unity1.girishd.com 24 hours
Anuva Development machine2 anuva2.girishd.com, main2.girishd.com, bento2.girishd.com, web2.girishd.com, python2.girishd.com, unity2.girishd.com 24 hours
Anuva Canonical Docs anuva.girishd.com 24 hours

Add all six exact hostnames as public application domains for each Development application. Do not replace them with *.girishd.com, which would also match the canonical docs and unrelated first-level subdomains.

Use a shorter session if the device is shared or less trusted. Do not add Bypass policies for health checks or static assets. An unauthenticated Access redirect is a valid remote route-health result for CLI diagnostics.

Create one remotely managed tunnel per machine

In the Cloudflare Dashboard:

  1. Go to Networking > Tunnels.
  2. Create anuva-machine1 for Machine 1.
  3. Create anuva-machine2 for Machine 2.
  4. Do not add either machine as a replica of the other tunnel.
  5. Confirm each tunnel has its own UUID and token.

The dashboard may offer a Windows service-install command. Do not use the always-on service for these Development tunnels. Install the cloudflared binary, then let the Anuva CLI start the selected tunnel with its token file.

Store the tunnel token on Windows

A remotely managed tunnel token is a secret: anyone holding it can run a connector for that tunnel.

For each machine:

  1. Open the tunnel in Networking > Tunnels.
  2. Select Add a replica and copy the tunnel token from the generated command.
  3. Open PowerShell and create the secrets directory outside every Git repository:
New-Item -ItemType Directory -Force "$env:LOCALAPPDATA\Anuva\secrets"
  1. Open the Machine 1 token file in Notepad. This avoids putting the token in PowerShell history:
notepad "$env:LOCALAPPDATA\Anuva\secrets\cloudflared-anuva-machine1.token"
  1. Paste only the token as one line, without quotes, a variable name, or the surrounding cloudflared command. Save and close Notepad. The path expands to:
C:\Users\Girish\AppData\Local\Anuva\secrets\cloudflared-anuva-machine1.token

On Machine 2, use cloudflared-anuva-machine2.token instead.

  1. Restrict the Machine 1 file ACL to the interactive Windows developer account and local administrators:
icacls "$env:LOCALAPPDATA\Anuva\secrets\cloudflared-anuva-machine1.token" /inheritance:r /grant:r "$($env:USERNAME):(R,W)" "Administrators:F"
  1. Run icacls with only the file path and confirm no other account or group has access. Delete any temporary clipboard or text-file copy used to transfer the token.

Do not put the token itself in %APPDATA%\Anuva\development.yaml, an environment file, PowerShell command, Git, logs, issue descriptions, documentation, process arguments, or Codex chat. Do not use Set-Content, echo, or another command that would place the token in terminal history. The CLI receives only the token-file path and invokes:

cloudflared tunnel run --token-file <configured-token-file>

cloudflared version 2025.4.0 or later is required for --token-file.

Configure published application routes

For a full Cloudflare DNS setup, adding a published application route in the Dashboard also creates the required DNS record. Configure each route on its own machine tunnel and enable Protect with Access where the route UI provides it.

Machine 1 routes

Public hostname Service URL Purpose
anuva1.girishd.com http://127.0.0.1:3000 CMS Web development app
main1.girishd.com http://127.0.0.1:4001 Product Main docs
bento1.girishd.com http://127.0.0.1:4005 Bento docs
web1.girishd.com http://127.0.0.1:4002 CMS docs
python1.girishd.com http://127.0.0.1:4013 Python server docs
unity1.girishd.com http://127.0.0.1:4004 Unity docs

Machine 2 routes

Public hostname Service URL Purpose
anuva2.girishd.com http://127.0.0.1:3000 CMS Web development app
main2.girishd.com http://127.0.0.1:4001 Product Main docs
bento2.girishd.com http://127.0.0.1:4005 Bento docs
web2.girishd.com http://127.0.0.1:4002 CMS docs
python2.girishd.com http://127.0.0.1:4013 Python server docs
unity2.girishd.com http://127.0.0.1:4004 Unity docs

Do not publish PostgreSQL, the Python API, Unity control ports, Docker, remote desktop, file shares, or arbitrary local ports. The Web app talks to the Python server and database locally; those dependencies are not public Tunnel routes.

Run the Machine 1 connector manually

This is the current manual procedure until the Anuva CLI development-environment commands are implemented. Start the local origins that you want to expose first:

Local origin Expected route
http://127.0.0.1:3000 https://anuva1.girishd.com
http://127.0.0.1:4001 https://main1.girishd.com
http://127.0.0.1:4005 https://bento1.girishd.com
http://127.0.0.1:4002 https://web1.girishd.com
http://127.0.0.1:4013 https://python1.girishd.com
http://127.0.0.1:4004 https://unity1.girishd.com

In PowerShell, verify the installed version and start the connector:

cloudflared version
cloudflared tunnel run --token-file "$env:LOCALAPPDATA\Anuva\secrets\cloudflared-anuva-machine1.token"

Keep that PowerShell window open while the Development environment is in use. Stop the connector with Ctrl+C.

Run only one connector command for the machine. The token identifies the remotely managed anuva-machine1 tunnel, and cloudflared receives all published route mappings assigned to that tunnel from Cloudflare. Do not run one connector per hostname and do not run cloudflared tunnel route dns for routes already created in the Dashboard.

After startup:

  1. Open Networking > Tunnels > anuva-machine1 and confirm the tunnel is Healthy.
  2. Confirm all six Machine 1 published application routes are assigned to this tunnel.
  3. Open each HTTPS hostname and confirm Cloudflare Access challenges an unauthenticated request.
  4. Authenticate and confirm each route shows the intended local application or documentation site.

The connector can be Healthy while an individual route returns a Cloudflare 502. That normally means its mapped local origin is stopped, unhealthy, or listening on a different port; it does not require another tunnel process.

Machine-local Anuva configuration

Store non-secret configuration at %APPDATA%\Anuva\development.yaml:

schemaVersion: 1
machine: machine1
devRoot: C:\\Anuva\\dev

tunnel:
  name: anuva-machine1
  tokenFile: C:\\Users\\<user>\\AppData\\Local\\Anuva\\secrets\\cloudflared-anuva-machine1.token

services:
  webapp:
    repository: anuvax-cms
    port: 3000
    url: https://anuva1.girishd.com

docs:
  anuva-main-video-creator: { port: 4001, url: https://main1.girishd.com }
  anuva-bento: { port: 4005, url: https://bento1.girishd.com }
  anuvax-cms: { port: 4002, url: https://web1.girishd.com }
  anuva-python-server: { port: 4013, url: https://python1.girishd.com }
  anuva-unity-video-creator: { port: 4004, url: https://unity1.girishd.com }

Machine 2 uses machine2, anuva-machine2, its token-file path, and the corresponding anuva2, main2, bento2, web2, python2, and unity2 hostnames. The YAML contains the secret file path, not the secret value.

Start and stop behavior

The normal entry points are:

anuva dev start --with-docs --with-tunnel
anuva dev start --docs-only --with-tunnel
anuva dev status --json
anuva dev logs cloudflared
anuva dev stop --all --confirm

On start, the CLI must:

  1. verify cloudflared and its minimum version;
  2. validate the configured tunnel name and absolute token-file path;
  3. verify that the token file exists and is readable without printing its content;
  4. start the required loopback origins;
  5. start one fingerprinted cloudflared process with --token-file;
  6. verify local origins before checking their public hostnames;
  7. accept an Access 302 or login page as proof that an unauthenticated route is alive; and
  8. return safe URLs, PIDs, health, and log locations without credentials.

The CLI must not attempt to automate OTP login. Authenticated content verification remains a user/browser action unless a separate service-auth design is approved.

On stop, terminate only the connector and services started and fingerprinted by the current Anuva environment. Do not stop an unrelated cloudflared process or delete any Cloudflare resource.

Verification checklist

Run this checklist independently on both machines:

  • [ ] cloudflared version meets the documented minimum.
  • [ ] The configured token file exists outside Git and its contents never appear in logs.
  • [ ] All expected origins respond on 127.0.0.1 before the tunnel starts.
  • [ ] The correct tunnel becomes Healthy in Networking > Tunnels.
  • [ ] Every published hostname reaches the Cloudflare Access login flow when unauthenticated.
  • [ ] The exact approved email receives an OTP and can authenticate.
  • [ ] A different email does not receive access.
  • [ ] Authenticated pages show content from the intended machine and repository.
  • [ ] No origin is reachable through a machine LAN address solely because of this setup.
  • [ ] Stopping the Anuva environment disconnects the connector and leaves Dashboard resources intact.
  • [ ] anuva.girishd.com remains Access-protected and independent of both machine tunnels.

Troubleshooting

Symptom Likely cause Check
Tunnel is Inactive or Down Connector not running, invalid token, or blocked egress Token file, process log, outbound port 7844
Cloudflare 502 Route is healthy but the local origin is down or has the wrong port Loopback URL and Dashboard service URL
DNS name does not resolve Published route or DNS record is missing Tunnel Routes and Cloudflare DNS
Browser reports certificate mismatch Edge certificate is not active for the hostname Edge Certificates and the exact published hostname
Access login is not shown Access application does not match the hostname or a Bypass exists Application hostname and policies
OTP is never delivered Email is not explicitly allowed or mail scanning/filtering interferes Reusable policy, OTP IdP, allowed sender
Correct login shows the wrong working tree Hostname is routed to the wrong tunnel or the machines share a tunnel Route-to-tunnel mapping and tunnel UUID
CLI remote check reports 302 Expected unauthenticated Access challenge Authenticate in a browser for content verification

Do not weaken Access, add a public bypass, expose a LAN listener, or create a shared cross-machine tunnel merely to clear a health check.

Token rotation and machine retirement

Rotate a tunnel token immediately if it appears in a log, screenshot, issue, repository, command argument, or chat transcript.

For planned rotation:

  1. Stop the affected Anuva environment.
  2. Rotate the token in the Cloudflare Dashboard.
  3. replace the local token file without changing its ACL;
  4. restart the environment and verify every route; and
  5. confirm the previous token no longer connects.

When retiring a machine, stop its connector, revoke its token, remove its published routes and Access application after review, then delete the tunnel. These are manual Cloudflare operations and are outside normal Anuva CLI scope.

References