docs: write operator README
Repo had a 0-byte README. New one covers: - Single-service inventory with the load-bearing cloudflared-mcp container name (vault-mcp's legacy network aliases depend on it) - Token-mode + dashboard-managed ingress contract - .env contract (TUNNEL_TOKEN) - Token rotation flow + how to map a new public hostname - Cross-reference to homelab-ansible's roles/cloudflared README for the redirect-loop gotcha on Traefik backends - No-ports / one-tunnel / :latest gotchas Working tree has an in-flight docker-compose.yml → compose.yml rename (D docker-compose.yml + ?? compose.yml). Intentionally not part of this commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
722b0a130c
commit
2f4fc25543
74
README.md
74
README.md
@ -0,0 +1,74 @@
|
||||
# cloudflared
|
||||
|
||||
Token-mode Cloudflare tunnel that fronts the homelab's MCP services and
|
||||
admin UIs. Outbound-only from the host — no inbound ports.
|
||||
|
||||
Routes `*.herbylab.dev` hostnames (e.g. `vault.herbylab.dev`,
|
||||
`auth.herbylab.dev`, `trellis.herbylab.dev`) to in-network services on
|
||||
the shared `homelab` Docker network. **Ingress rules live in the
|
||||
Cloudflare Zero Trust dashboard**, not in this repo.
|
||||
|
||||
## Service
|
||||
|
||||
| Service | Image | Container name |
|
||||
|---------------|----------------------------------|---------------------|
|
||||
| `cloudflared` | `cloudflare/cloudflared:latest` | `cloudflared-mcp` |
|
||||
|
||||
The `cloudflared-mcp` container name is **load-bearing**: it's the same
|
||||
hostname the legacy network aliases on `vault-mcp` (`homelab-mcp`,
|
||||
`herbydev-mcp`) expect, so renaming the container breaks dashboard
|
||||
ingress until the tunnel config is repointed.
|
||||
|
||||
## Run it
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker compose logs -f cloudflared
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| File | Purpose |
|
||||
|----------------|---------------------------------------------------------|
|
||||
| `compose.yml` | Single-service definition + external `homelab` network |
|
||||
| `.env` | `TUNNEL_TOKEN` (from Cloudflare Zero Trust dashboard) — gitignored |
|
||||
|
||||
To create / rotate the tunnel:
|
||||
|
||||
1. Cloudflare Zero Trust dashboard → Networks → Tunnels.
|
||||
2. Create a new tunnel (or rotate the token on the existing one).
|
||||
3. Paste the connector token into `.env` as `TUNNEL_TOKEN=...`.
|
||||
4. Restart: `docker compose up -d`.
|
||||
|
||||
To map a new public hostname to a backend:
|
||||
|
||||
1. Cloudflare dashboard → tunnel → Public Hostnames → Add a public
|
||||
hostname.
|
||||
2. Origin = `http://<container>:<port>` (the backend must be on the
|
||||
`homelab` Docker network so this `cloudflared-mcp` container can
|
||||
reach it by service name).
|
||||
3. No restart needed — the connector reloads dashboard config on its own.
|
||||
|
||||
For HTTPS-only backends (Traefik et al.), use
|
||||
`https://<container>:443` with "No TLS Verify" — see the
|
||||
`roles/cloudflared` README in `homelab-ansible` for the redirect-loop
|
||||
gotcha when targeting `:80`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Token-mode = no `ports:` block.** This is outbound-only by
|
||||
construction. If you find yourself adding a `ports:` entry, you're
|
||||
misconfiguring — backends are reached *outbound* from the connector,
|
||||
not inbound.
|
||||
- **External `homelab` network must exist** before this stack starts.
|
||||
Backends must also be on the `homelab` network (or a network shared
|
||||
with it) for `cloudflared-mcp` to resolve them by container name.
|
||||
- **One container, one tunnel.** Multiple tunnels = multiple compose
|
||||
stacks (or a parameterized invocation pattern — see the
|
||||
`roles/cloudflared` Ansible role in `homelab-ansible` for that
|
||||
approach).
|
||||
- **`:latest` image tag.** No pinning. If a connector upgrade breaks
|
||||
ingress, pin to the last-known-good tag and re-deploy.
|
||||
- The repo also contains some leftover uv-init artifacts (`main.py`,
|
||||
`pyproject.toml`, `uv.lock`, `.python-version`). These are not part
|
||||
of the deployment.
|
||||
Loading…
Reference in New Issue
Block a user