diff --git a/.gitbook/assets/cf-tunnel-create.png b/.gitbook/assets/cf-tunnel-create.png new file mode 100644 index 00000000..06e2898b Binary files /dev/null and b/.gitbook/assets/cf-tunnel-create.png differ diff --git a/.gitbook/assets/cf-tunnel-route.png b/.gitbook/assets/cf-tunnel-route.png new file mode 100644 index 00000000..0c2c909f Binary files /dev/null and b/.gitbook/assets/cf-tunnel-route.png differ diff --git a/SUMMARY.md b/SUMMARY.md index 4088ffa7..4a14eef5 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -112,6 +112,7 @@ * [Quickstart](obol-stack/quickstart.md) * [Build a Profitable Obol Stack](obol-stack/build-a-profitable-stack.md) * [Selling Agent Services](obol-stack/selling-services.md) +* [Set up a Permanent URL](obol-stack/permanent-url.md) * [Installing Networks](obol-stack/installing-networks.md) * [Installing Apps](obol-stack/installing-apps.md) * [FAQ](obol-stack/faq.md) diff --git a/obol-stack/README.md b/obol-stack/README.md index 97b8fa47..7127f2f5 100644 --- a/obol-stack/README.md +++ b/obol-stack/README.md @@ -41,7 +41,7 @@ The cluster runs entirely on your machine via [k3d](https://k3d.io/) (Kubernetes | `obol network list / install / sync / delete` | Manage blockchain networks | | `obol sell demo / inference / http / list / status / register` | Create payment-gated services and register on ERC-8004 | | `obol app install / sync / list / delete` | Install arbitrary Helm charts | -| `obol tunnel status / login / provision` | Manage Cloudflare tunnels | +| `obol tunnel status / setup / restart` | Manage the Cloudflare tunnel (`setup` creates a permanent URL) | | `obol kubectl / helm / helmfile / k9s` | Kubernetes tool passthroughs (auto-configured `KUBECONFIG`) | ## Default infrastructure diff --git a/obol-stack/build-a-profitable-stack.md b/obol-stack/build-a-profitable-stack.md index b0f9f2ed..aea65166 100644 --- a/obol-stack/build-a-profitable-stack.md +++ b/obol-stack/build-a-profitable-stack.md @@ -102,7 +102,24 @@ obol sell agent my-quant \ Buyers pay per reply, not per token — and pay for the answer, not the inference. -## Step 5: get listed +## Step 5: get a permanent URL + +So far your service has been reachable on a temporary quick-tunnel URL (`https://.trycloudflare.com`) that changes on every restart. Before you register and start attracting buyers, give it a stable home — otherwise anyone who bookmarked or registered the old URL hits errors after a restart. + +```shell +# 1. In the Cloudflare dashboard: Networks → Tunnels → Create a tunnel. +# 2. Add a Public Hostname: +# Subdomain/Domain: stack.example.com +# Service: http://traefik.traefik.svc.cluster.local:80 +# 3. Copy the connector token and hand it to Obol: +obol tunnel setup --hostname stack.example.com +``` + +You can paste the whole `cloudflared tunnel run --token …` line the dashboard shows — Obol strips the prefix and keeps the token. This uses a least-privilege, single-tunnel **connector token**, not an account-wide API key, so the credential can only run this one tunnel. + +Confirm it's live with `obol tunnel status`. For the full dashboard walkthrough with screenshots, see [Set up a permanent URL](permanent-url.md). + +## Step 6: get listed Register your agent on [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004) so buyers can find it: @@ -121,7 +138,7 @@ Registration writes to the on-chain Identity Registry. From there, multiple mark You don't need to pick one marketplace; registering once gets you indexed by all of them. See [Selling agent services](selling-services.md#get-discoverable-erc-8004-and-marketplaces) for the longer marketplace orientation. -## Step 6: tell your agent to ping you on Telegram +## Step 7: tell your agent to ping you on Telegram By the time you have an archive node syncing in the background, an index updating, and a paid agent live on a tunnel — you probably don't want to sit and watch a terminal. `obol hermes setup` wires Hermes to a Telegram bot (or Discord, Slack, etc.) so it can message you when things change. @@ -134,7 +151,7 @@ The Telegram bot flow involves talking to two other Telegram bots: Test it: ask the agent to ping you when the next sync milestone hits. If you get a Telegram message, you're done — you can close the laptop and let the agent work. -## Step 7: iterate +## Step 8: iterate The compounding loop: diff --git a/obol-stack/permanent-url.md b/obol-stack/permanent-url.md new file mode 100644 index 00000000..cfbb57f6 --- /dev/null +++ b/obol-stack/permanent-url.md @@ -0,0 +1,85 @@ +--- +description: Give your stack a permanent public URL with a Cloudflare tunnel, so buyers can reliably reach the services you sell. +--- + +# Set up a permanent URL + +By default `obol stack up` brings up a **temporary** Cloudflare quick tunnel. Its `https://.trycloudflare.com` address is great for local testing, but it **changes on every restart** — so anyone who bookmarked it, or any ERC-8004 registration that points at it, breaks the next time your stack comes back up. + +Once you're ready to attract buyers, give your stack a **permanent URL** on a hostname you control. Obol does this with a Cloudflare **connector token**: a least-privilege, single-tunnel credential — *not* an account-wide API key. You create the tunnel in the Cloudflare dashboard, and Obol runs the connector for you. + +{% hint style="info" %} +**Prerequisite — a Cloudflare account with a domain.** You need a [Cloudflare](https://dash.cloudflare.com) account (the free plan is fine) with a domain that lives as a **zone** in that account — either bought through Cloudflare Registrar or transferred/added in. The hostname you expose has to live on that domain. + +**No domain yet?** You have two options, whichever is easier: + +- **In the Cloudflare dashboard** (recommended if you're more comfortable there) — buy a domain via [Registrar](https://dash.cloudflare.com/?to=/:account/registrar) or add an existing one as a zone, then come back here. +- **From the CLI** (optional convenience) — `obol domain search `, `obol domain check `, and `obol domain register ` wrap Cloudflare Registrar so you never leave the terminal. `obol domain list` shows domains you already own. + +Either way, **registering a domain is billable**, so your Cloudflare account needs a saved payment method. The CLI path also needs a scoped Cloudflare **API token** (Account → Domain permission) — note this is a *different* credential from the tunnel connector token below. +{% endhint %} + +## 1. Create the tunnel and copy its token + +Open the [Cloudflare Zero Trust dashboard](https://one.dash.cloudflare.com) → **Networks → Tunnels → Create a tunnel**, and choose the **Cloudflared** connector type. On the **Create a Tunnel** screen, give it a name (e.g. `Obol Agent Storefront`), pick your operating system under **Setup Environment**, and copy the token from the **Install and Run** commands — it's the long `eyJ…` value. + +
Cloudflare Create a Tunnel screen: tunnel name, OS selector, and install commands containing the connector token, with a security notice.

Name the tunnel, then copy the eyJ… token from the install commands.

+ +{% hint style="warning" %} +You do **not** run any of the commands Cloudflare shows — Obol runs the connector inside your cluster, so you don't install `cloudflared` yourself. You only need the token. The easiest is to copy the whole `cloudflared tunnel run --token eyJ…` line and paste it into Obol; it strips the prefix and keeps the token. Treat the token like a password. +{% endhint %} + +## 2. Publish your stack on a hostname + +Next, on **Add published application** (the "Route tunnel" / Public Hostname step), choose the **Subdomain** and **Domain** you want (e.g. `demo` + `obol.org` → `demo.obol.org`), leave **Path** empty, and set the **Service URL** to your cluster's Traefik ingress. + +
Cloudflare Add published application screen: subdomain and domain fields making demo.obol.org, and a Service URL field pointing at the in-cluster Traefik address.

Pick your hostname, then point Service URL at the in-cluster Traefik address.

+ +{% hint style="warning" %} +**Set the Service URL to exactly this** — it's the in-cluster address of your stack's Traefik ingress, and it's the same for every Obol Stack: + +``` +http://traefik.traefik.svc.cluster.local:80 +``` + +Don't use `localhost`, `obol.stack`, or your machine's IP — the connector runs *inside* the cluster, so it must reach Traefik by its Kubernetes service name. Then click **Add route**. +{% endhint %} + +Saving this creates the DNS record and forwards traffic for your hostname into the cluster automatically. + +## 3. Hand the token to Obol + +```shell +obol tunnel setup --hostname stack.example.com +``` + +You can paste the bare token, pass it with `--token`, or paste the whole `cloudflared tunnel run --token …` line. If you run `obol tunnel setup` with no token, it walks you through these dashboard steps interactively and prompts for it. + +Obol stores the token as an in-cluster secret and runs the connector. Confirm it's live: + +```shell +obol tunnel status +``` + +You should see a **permanent** mode, your hostname, and a connected connector. Your services are now reachable at `https://stack.example.com/...` and survive `obol stack down` / `obol stack up`. + +{% hint style="success" %} +With a stable URL in place, register on-chain so buyers can discover you — see [Build a Profitable Obol Stack](build-a-profitable-stack.md#step-6-get-listed) and [Selling Agent Services](selling-services.md). +{% endhint %} + +## Alternative: browser login (no dashboard) + +If you'd rather not use the dashboard, Obol can authenticate a locally-managed tunnel through a browser login instead. This needs the [`cloudflared`](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) binary installed on your machine: + +```shell +obol tunnel setup --hostname stack.example.com --management local +``` + +This opens a browser to authorize cloudflared against your Cloudflare account, then creates the tunnel and DNS route for you. It produces the same kind of permanent URL — the only difference is how the tunnel is managed. + +## Troubleshooting + +- **`obol tunnel status` shows `waiting_for_connections`** — the connector started but hasn't established a connection yet. Give it a few seconds, or check `obol tunnel logs`. +- **Public check fails / 5xx** — confirm the dashboard Public Hostname's Service is exactly `http://traefik.traefik.svc.cluster.local:80` and that the hostname matches the one you passed to `obol tunnel setup`. +- **`Invalid format for Authorization header`** — you pasted a Cloudflare **API token** or Global API Key instead of the **connector token** from the tunnel's install screen. Use the connector token. +- **Need a fresh quick tunnel instead** — `obol tunnel restart` rotates the temporary URL; `obol tunnel setup` is only for the permanent one. diff --git a/obol-stack/quickstart.md b/obol-stack/quickstart.md index 822e8d00..b7bfe4de 100644 --- a/obol-stack/quickstart.md +++ b/obol-stack/quickstart.md @@ -195,6 +195,10 @@ obol sell list # services you're selling obol sell status # ServiceOffer reconciliation state ``` +{% hint style="info" %} +`obol stack up` gives you a **temporary** tunnel URL that changes on every restart. When you're ready to sell, give your stack a stable hostname — see [Set up a permanent URL](permanent-url.md). +{% endhint %} + ## Stopping and cleaning up ```shell