- commit
- cdd249726732c33037e592d6bc975f7d9c5cd06b
- parent
- bbfe3e4718ce79b2f3c96d15a1f3fc6112e39ab2
- author
- Dami <dami.etoile@gmail.com>
| M | docs/ | 6 | ++++++ |
| M | docs/ | 2 | ++ |
| M | docs/ | 31 | ++++++++++++++++++++++++++++++ |
| M | src/ | 1 | + |
@@ -57,6 +57,12 @@ A relay only helps once your clients know about it. On the Identity tab, **Tell
5757 5858 Every relay has a card: `https://<name>.bind.ws/card.svg` is a picture with the name, who may read and write, the fuel state and a QR of the group address, and `/card.json` has the same facts as data. The **Share** block on the Identity tab shows the card, the group naddr with a copy button, and an embed snippet for a profile or a page.5959 60+## Your own domain61+62+Your relay can answer at a hostname you own, such as `wss://relay.example.com`. On the Identity tab, under **Your own domain**, add the hostname. The page shows one record to create at your DNS: a CNAME from your hostname to the address it gives you. Once the record resolves, the certificate is issued on its own and **Check** turns green. Up to three hostnames per relay. Everything else stays the same: same events, same members, same console, reachable by either name.63+64+This needs the host to have switched custom domains on. If they have not, the block says so.65+6066 ## Invite people6167 6268 A new relay accepts writes from its members only. To add someone:@@ -61,6 +61,8 @@ Banner is a wide image for the same document. Posting policy and privacy policy
6161 6262 Join terms are shown to people who open an invite link, and published at `/terms` as the relay's terms of service. The public directory switch decides whether `/people` lists your members to visitors.6363 64+**Your own domain** puts the relay under a hostname you control. Add the hostname; the relay registers it with the host's Cloudflare zone and shows the CNAME to create at your DNS, plus an optional TXT record that activates the hostname before you switch the CNAME. **Check** asks where it stands: the hostname is live when both the hostname and its certificate read active. **Remove** deletes the hostname and its certificate. At most three per relay. Domains are not part of the exported configuration, because they belong to this relay instance rather than to its rules.65+6466 **Export configuration** downloads rules, identity, members, bans, kind rules and retention as one file. **Import** replaces those lists on any relay you own. Events, files and the owner are never touched.6567 6668 **Transfer ownership** hands the relay to a member you pick. You stay on as a moderator. The relay's key, events, files and fuel do not change. You type the relay's name to confirm.@@ -57,6 +57,37 @@ Nothing else is required: no origin, no certificates, no servers. An idle relay
5757 - The `usage` table grows one row per relay per month. No cleanup is needed.5858 - To take a relay down as the operator, use the owner's typed-name `deleterelay` call or the console.5959 60+## Custom domains61+62+Owners can put a relay under a hostname they control, such as `relay.example.com`, through [Cloudflare for SaaS custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/). The feature is off until the one-time setup below is done; the console says so until then.63+64+How it works, from the [docs](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/worker-as-origin/): the customer's hostname CNAMEs to a name in your zone, so their traffic enters your zone, and a Worker route that matches any host sends it to the Worker. The Worker sees the customer's hostname in `Host`, looks it up in the `HOSTS` KV namespace to find the relay name, and forwards to that object exactly as it does for `<name>.<domain>`. Inside the object nothing changes; the URLs it prints already follow the request host. Certificates use [HTTP validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/security/certificate-management/issue-and-validate/validate-certificates/http/), which Cloudflare completes on its own once the CNAME resolves to you, so the owner has one DNS record to create. [Hostname validation](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/hostname-validation/) happens the same way; the optional TXT record the console also shows lets an owner activate the hostname before switching DNS.65+66+One-time setup, in this order:67+68+1. **Enable Cloudflare for SaaS** on the zone: dashboard, your zone, SSL/TLS, Custom Hostnames, Enable. Non-enterprise zones enter payment details; the first 100 hostnames are free ([enable](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/enable/), [plans](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/)).69+2. **Create the fallback origin record**, originless and proxied, in the zone's DNS ([worker as origin](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/worker-as-origin/)):70+71+ | Record | Name | Value | Proxy |72+ |---|---|---|---|73+ | `AAAA` | `fallback` | `100::` | on |74+75+ Then on the Custom Hostnames page set **Fallback Origin** to `fallback.<domain>` and wait for it to read Active. The wildcard placeholder records from the DNS section above are not enough here: the fallback origin must be a record of its own.76+3. **Create the CNAME target** owners will point at, proxied ([getting started, step 2](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#2-optional-create-cname-target)):77+78+ | Record | Name | Value | Proxy |79+ |---|---|---|---|80+ | `CNAME` | `customers` | `fallback.<domain>` | on |81+82+ `CNAME_TARGET` in `wrangler.jsonc` must match: `customers.<domain>`.83+4. **Routes.** `wrangler.jsonc` declares a `*/*` route on the zone next to the wildcard, which is what makes custom hostname traffic reach the Worker. Deploy once after the change and confirm in Workers Routes that the zone lists `*/*` for `bindws-relay`. If wrangler refuses the pattern, add it by hand on that page: route `*/*`, Worker `bindws-relay`.84+5. **KV namespace.** `npx wrangler kv namespace create HOSTS` and put the id in both `kv_namespaces` entries of `wrangler.jsonc` (the repo carries the bind.ws one).85+6. **API token.** My Profile, API Tokens, Create Token, Custom token: permission **Zone, SSL and Certificates, Edit**, zone resources limited to your zone. Store it as a secret: `npx wrangler secret put CF_API_TOKEN`. `ZONE_ID` in `wrangler.jsonc` is the zone the hostnames are created in (the same id the routes use). Without the secret the console reports custom domains as not enabled and the methods answer `unsupported:`.86+87+The Worker calls three endpoints with that token: [create](https://developers.cloudflare.com/api/resources/custom_hostnames/methods/create/), [get](https://developers.cloudflare.com/api/resources/custom_hostnames/methods/get/) and [delete](https://developers.cloudflare.com/api/resources/custom_hostnames/methods/delete/) under `/zones/<zone>/custom_hostnames`. A hostname is ready when the API reports `status: active` and `ssl.status: active` ([check when ready](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#check-when-a-custom-hostname-is-ready)). Deleting a relay removes its hostnames from Cloudflare and KV; transferring keeps them. Do not let an owner add the zone's own apex as a custom hostname; the relay refuses anything under `<domain>`.88+89+Locally, `wrangler dev` has no custom hostname traffic; the KV binding exists so tests can seed a mapping.90+6091 ## Local development6192 6293 ```@@ -114,6 +114,7 @@ export function landing(req: Request, env: Env): Response {
114114 ["GET / (accept nostr+json)", "NIP-11", "none", "limitation, retention, payments_url, self"],115115 ["POST /", "NIP-86", "NIP-98, owner", "claim and the management methods"],116116 ["POST /lease", "lease", "optional NIP-98", `A temporary relay for ${leaseDays(env)} days. A signature reserves the claim for that key.`],117+ ["wss://relay.example.com", "custom domain", "owner", `A hostname you own, CNAME to customers.${domain}. Set on the Identity tab; up to three per relay.`],117118 ["POST /events /query /count", "HTTP bridge", "NIP-98", "The signer has the same access as an authenticated socket."],118119 ["PUT /upload, GET /<sha256>", "Blossom", "kind 24242", "Stored in R2. Counted as files. HEAD /upload checks first; PUT /mirror copies from a URL; PUT /report files a report."],119120 ["POST /nip96, GET /.well-known/nostr/nip96.json", "NIP-96", "NIP-98", "Same bucket and file list as Blossom. NIP-94 tags in every answer."],