# Case Study: Cloudflare Tunnel Setup with Claude Code

## The Challenge

Expose a local nginx container (running on port 86) to the internet via Cloudflare Tunnel at `nginx.leebasehome.com` — a task that typically requires:

- Reading Cloudflare documentation
- Navigating multiple API endpoints
- Managing secrets and credentials
- Creating configuration files with exact formatting
- Debugging Docker networking issues

## What Actually Happened

I provided Claude Code with a plan document and one instruction: "Implement this."

**Total human effort:** Pasted an API token into a file when prompted.

**Everything else was automated.**

## The Execution

### Step 1: API Discovery
Claude Code retrieved my Cloudflare Account ID and Zone ID by calling the Cloudflare API:

```
Account ID: 71d04f6674064cf7b5ca82d12a2fdf12
Zone ID:    0a0f40b97a632c7be6827793cc73fce7
```

### Step 2: Tunnel Creation
Created a new Cloudflare Tunnel via API with a cryptographically secure secret:

```
Tunnel ID:     c8be17f4-8314-4020-a777-966f08a10fc2
Tunnel Secret: dwNuUMti72XaqUyoR5sElNC+rgy5yv2arVP4q8mn8II=
```

### Step 3: DNS Configuration
Created the CNAME record pointing `nginx.leebasehome.com` to the tunnel:

```
nginx.leebasehome.com → c8be17f4-8314-4020-a777-966f08a10fc2.cfargotunnel.com
```

### Step 4: Local Configuration
Generated two configuration files with all the correct values populated:

**~/.cloudflared/config.yml**
```yaml
tunnel: c8be17f4-8314-4020-a777-966f08a10fc2
credentials-file: /home/nonroot/.cloudflared/c8be17f4-8314-4020-a777-966f08a10fc2.json

ingress:
  - hostname: nginx.leebasehome.com
    service: http://host.docker.internal:86
  - service: http_status:404
```

**~/.cloudflared/[tunnel-id].json**
```json
{
  "AccountTag": "71d04f6674064cf7b5ca82d12a2fdf12",
  "TunnelID": "c8be17f4-8314-4020-a777-966f08a10fc2",
  "TunnelSecret": "dwNuUMti72XaqUyoR5sElNC+rgy5yv2arVP4q8mn8II="
}
```

### Step 5: Container Deployment
Launched the cloudflared Docker container with proper networking:

```bash
docker run -d \
  --name cloudflared-tunnel \
  --restart unless-stopped \
  --add-host host.docker.internal:host-gateway \
  -v /home/lee/.cloudflared:/home/nonroot/.cloudflared:ro \
  cloudflare/cloudflared:latest \
  tunnel run c8be17f4-8314-4020-a777-966f08a10fc2
```

### Step 6: Verification
Confirmed 4 tunnel connections established and tested the live endpoint:

```
HTTP/2 200
server: cloudflare
cf-ray: 9c316c6068f3e133-ORD
```

## The Result

**https://nginx.leebasehome.com** — live and serving traffic through Cloudflare's network.

## Why This Matters

### Traditional Approach
1. Read Cloudflare tunnel documentation
2. Install cloudflared CLI locally
3. Run `cloudflared tunnel login` (opens browser)
4. Run `cloudflared tunnel create`
5. Manually create config.yml
6. Figure out Docker networking (`host.docker.internal`)
7. Debug permission issues with mounted volumes
8. Set up DNS record in Cloudflare dashboard
9. Test and troubleshoot

**Estimated time: 30-60 minutes** (more if unfamiliar with Cloudflare)

### With Claude Code
1. Provide a plan document
2. Paste API token when asked
3. Done

**Actual time: ~2 minutes**

## Key Capabilities Demonstrated

| Capability | Example |
|------------|---------|
| **API Integration** | Called 5 different Cloudflare API endpoints |
| **Secret Management** | Generated cryptographic secrets with OpenSSL |
| **File Generation** | Created properly formatted YAML and JSON configs |
| **Docker Operations** | Pulled image, configured networking, launched container |
| **Adaptive Problem-Solving** | Switched from `jq` to Python when jq wasn't installed |
| **Verification** | Checked logs, API status, and live endpoint |

## The Power of AI Agents

This case study illustrates several key advantages of AI-assisted development:

1. **Context Retention** — Claude Code tracked IDs, secrets, and file paths across multiple steps without losing information

2. **Tool Orchestration** — Seamlessly combined curl, openssl, docker, and file operations into a coherent workflow

3. **Error Adaptation** — When `jq` wasn't available, immediately switched to Python's json module

4. **Domain Knowledge** — Knew Cloudflare API structure, Docker networking quirks, and config file formats

5. **Verification Built-In** — Didn't just execute commands; confirmed success at each step

## Conclusion

What would have been a 30-60 minute task involving documentation reading, context-switching between browser and terminal, and manual configuration became a 2-minute automated workflow.

The human stayed in control (approving the plan, providing credentials) while the AI handled the tedious execution details.

**This is the future of infrastructure management.**

---

*Generated: January 24, 2026*
*Tools: Claude Code (Claude Opus 4.5)*
