# Cloudflare Tunnel Setup Guide

## Prerequisites

- A Cloudflare account (free at cloudflare.com)
- A domain on Cloudflare (see "Getting a domain on Cloudflare" below)

### Getting a domain on Cloudflare

The tunnel needs a domain managed by Cloudflare. There are two paths:

**Option A: Buy a new domain through Cloudflare**
Cloudflare sells domains at cost (no markup). Navigate to cloudflare.com, go to Domains, and buy a domain. The domain is automatically set up — no further DNS configuration needed.

**Option B: Add an existing domain**
If the user already owns a domain through another registrar (GoDaddy, Namecheap, etc.):
- The agent adds the domain via `cf-add-zone` (official Cloudflare API) — no dashboard navigation needed
- Cloudflare scans existing DNS records and imports them — the user should review to ensure everything is present (website, email, etc.)
- Cloudflare provides two nameservers — the user replaces the existing nameservers at their registrar with these
- Propagation is usually minutes but can take up to 24 hours
- Cloudflare shows the domain as Active once propagation is complete

**Will my website go down?** No. Cloudflare imports all existing DNS records, so traffic continues to reach the same servers as before. The only thing that changes is which nameservers answer DNS queries.

Once the domain is active on Cloudflare, the tunnel setup creates two subdomains (`admin.{domain}` and `public.{domain}`) automatically. Any domain works.

## Setup Flow

The entire setup is done through conversation with the admin agent. All Cloudflare-side operations (authentication, zone creation, tunnel setup, DNS) use the official Cloudflare SDK — no browser automation needed. The VNC browser is only used for registrar nameserver changes and URL verification.

### Authentication

The path is `tunnel-login` — browser-based OAuth:

The agent calls `tunnel-login`, which opens a Cloudflare authorization URL in the VNC browser. The user signs in and clicks Authorize. `cloudflared` derives API credentials automatically. The specialist only navigates to the URL and reports page state — it never interacts with forms or solves challenges.

**Auth validation:** `tunnel-status` reports `hasToken` (key file exists) and `tokenValid` (key tested against Cloudflare API). Only `tokenValid: true` means the connection is valid.

### Tunnel creation

After authentication, the agent calls `tunnel-create` with the domain. This creates the tunnel and routes DNS for both subdomains automatically:

- `admin.{domain}` — remote access to the admin interface (requires a remote password)
- `public.{domain}` — public chat for customers

No manual Cloudflare dashboard interaction is needed — DNS records (CNAMEs) are created automatically.

### Remote password

Before the tunnel can be enabled, a remote password must be set. This protects the admin interface when accessed from the public internet. It is separate from the local PIN.

Password requirements: at least 8 characters, must contain a number and a special character, no leading/trailing spaces.

### Enabling the tunnel

Once the remote password is set, the agent calls `tunnel-enable` to start the tunnel process. The tunnel runs with automatic health monitoring and restart on failure.

After enabling, the agent verifies the tunnel process survives for 5 seconds and then tests the public URL via personal-assistant. URLs are not reported as working until verified. If verification fails, the agent reports the failure and possible causes (DNS propagation delay, domain not configured in Cloudflare, etc.).

After verified:
- Admin interface is live at `https://admin.{domain}` (requires remote password)
- Public chat is live at `https://public.{domain}`
- Local network access continues to work with the PIN as before

## After Setup

Check tunnel status at any time by asking the agent. The `tunnel-status` tool reports whether the tunnel is running, the configured domain, uptime, and restart count.

### Alias domains

An alias domain (e.g. `maxy.chat`) serves the public chat directly — the URL stays as the alias domain in the browser bar, no redirect. This is the primary method for attaching a custom domain to the public chat.

**How it works:** The `tunnel-add-hostname` tool adds the alias hostname to the tunnel ingress (so Cloudflare routes traffic for that hostname through the tunnel), creates a CNAME record in the alias domain's zone pointing to the tunnel, and registers the alias in `~/{configDir}/alias-domains.json` so the web server treats it as a public hostname.

**Requirements:**
- The alias domain must be an Active zone on the same Cloudflare account
- The tunnel must already be created (the tool needs a tunnel ID)

**Do not use a CNAME pointing to `public.{primary domain}`.** The tunnel ingress only accepts hostnames it was configured with. A CNAME preserves the original `Host` header, so the tunnel sees the alias hostname and returns 404. The correct CNAME target is `{tunnelId}.cfargotunnel.com`, and the alias must be added to the tunnel's ingress rules — both of which `tunnel-add-hostname` handles automatically.

## Troubleshooting

### Tunnel won't start
- Ask the agent to check `tunnel-status` for details
- If the connection has expired or has insufficient permissions, call `tunnel-login` with `force=true` to delete stored credentials and restart authentication
- If the key file is missing (`~/{configDir}/cloudflare/api-token`), run `tunnel-login` to authorize via browser and derive credentials
- Tunnel state is stored at `~/{configDir}/cloudflared/tunnel.state` (e.g. `~/.maxy/cloudflared/tunnel.state`). Each brand has its own state directory — on multi-brand devices, tunnels are independent

### Token has insufficient permissions
- Cert-derived tokens (`cfut_*` prefix) have Zone:Zone:Read but NOT Zone:Zone:Edit or Zone:DNS:Edit via the SDK
- DNS routing automatically falls back to `cloudflared tunnel route dns` CLI command (which uses cert.pem auth directly and has sufficient permissions for CNAME creation)
- Zone creation (`cf-add-zone`) may fail with cert-derived tokens — if the domain is not yet on Cloudflare, the user must add it via the Cloudflare dashboard at cloudflare.com
- `tunnel-login` with `force=true` clears stored credentials and restarts the OAuth flow if re-authentication is needed

### DNS not resolving (most common issue)

**The #1 cause of "tunnel running but URLs dead" is wrong nameservers.** The domain must use Cloudflare's nameservers, not the registrar's defaults (e.g. Namecheap's `dns1.registrar-servers.com`). `tunnel-status` checks this automatically and emits a CRITICAL warning when nameservers are wrong.

To fix:
1. Sign in to Cloudflare dashboard
2. Confirm the domain shows as **Active** (not Pending)
3. If Pending or not listed: add the domain, select the Free plan, then change nameservers at the registrar to Cloudflare's (shown in the dashboard)
4. Wait for propagation (usually minutes, up to 24 hours)

Other DNS issues:
- Use `dns-lookup` to check whether subdomains resolve — never use `dig`, `nslookup`, or other system DNS binaries (they are not installed on the Pi)
- DNS propagation can take 1-5 minutes after tunnel creation
- Verify the tunnel is running via `tunnel-status`
- Check the Cloudflare dashboard to confirm the CNAME records exist for both `admin.{domain}` and `public.{domain}`

### Remote login issues
- After 5 failed login attempts, there is a 15-minute lockout — wait for it to expire
- The remote password can be reset by asking the agent on the local network

### Changing domain
- Ask the agent to disable the tunnel
- Re-authenticate with Cloudflare using the new domain
- Create a new tunnel — new DNS records are generated automatically
- Old DNS records can be removed from the Cloudflare dashboard

## Agent Tools

Eleven MCP tools provide full tunnel and zone lifecycle management:

| Tool | Purpose |
|------|---------|
| `tunnel-login` | Default auth — spawns `cloudflared tunnel login`, returns auth URL, derives API credentials automatically |
| `cf-set-token` | Fallback auth — store and validate a Cloudflare API token (Zone:DNS:Edit, Account:Cloudflare Tunnel:Edit, Zone:Zone:Edit) |
| `cf-add-zone` | Add a domain to the Cloudflare account via official API. Idempotent — returns existing zone if already present |
| `cf-zone-status` | List domains on the account with activation status and nameservers |
| `tunnel-status` | Full status: installed, token valid, running, domain, URLs, uptime |
| `tunnel-install` | Install the cloudflared binary |
| `tunnel-create` | Create tunnel and route DNS for admin/public subdomains |
| `tunnel-add-hostname` | Add an alias domain for direct serving (no redirect). Handles tunnel ingress, DNS CNAME, and web server registration. Idempotent |
| `tunnel-enable` | Start the tunnel process with health monitoring |
| `tunnel-disable` | Stop the tunnel, preserve config for re-enabling |
| `dns-lookup` | Resolve DNS records (A, AAAA, CNAME, MX, TXT, NS, SOA) without system binaries. Use this for all DNS diagnostics — `dig` and `nslookup` are not available on the Pi |
