From e0e8bb6b7d6dab7a75358a2e694ae3ecd9e217e8 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Thu, 11 Jun 2026 10:12:40 +1000 Subject: [PATCH 1/4] Point Fly console UI at public.meshllm.cloud Prepares the apex cutover: the console build now targets the API at public.meshllm.cloud instead of the apex meshllm.cloud, so the console stops depending on the apex before meshllm.cloud becomes the static site. --- fly/Dockerfile | 2 +- fly/console/fly.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fly/Dockerfile b/fly/Dockerfile index 44d1bea074..3fa405fc82 100644 --- a/fly/Dockerfile +++ b/fly/Dockerfile @@ -7,7 +7,7 @@ # syntax=docker/dockerfile:1.7 FROM node:24-alpine AS ui-builder -ARG VITE_API_URL=https://meshllm.cloud +ARG VITE_API_URL=https://public.meshllm.cloud ARG VITE_APP_VERSION= ARG VITE_STORAGE_NAMESPACE=mesh-llm-ui-production ARG NODE_ENV=production diff --git a/fly/console/fly.toml b/fly/console/fly.toml index 2aeb974558..becd444748 100644 --- a/fly/console/fly.toml +++ b/fly/console/fly.toml @@ -6,7 +6,7 @@ primary_region = "syd" [build.args] NODE_ENV = "production" - VITE_API_URL = "https://meshllm.cloud" + VITE_API_URL = "https://public.meshllm.cloud" VITE_STORAGE_NAMESPACE = "mesh-llm-ui-production" [env] From 933b49d8fa5a829fac9a1dd04d9c878cb374428e Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Thu, 11 Jun 2026 10:19:40 +1000 Subject: [PATCH 2/4] Add missing workspace crates to Fly Dockerfile copy list The console image build was failing because 9 crates added since the last copy-list update (mesh-llm-cli, mesh-llm-commands, mesh-llm-embedded-runtime, mesh-llm-events, mesh-llm-hardware-profile, mesh-llm-native-runtime, mesh-llm-runtime-install, mesh-llm-sdk, mesh-llm-tui) were never COPYed into the build context, so cargo could not resolve the workspace manifest. --- fly/Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fly/Dockerfile b/fly/Dockerfile index 3fa405fc82..d7b81835ec 100644 --- a/fly/Dockerfile +++ b/fly/Dockerfile @@ -80,6 +80,15 @@ COPY crates/llama-spec-bench/ crates/llama-spec-bench/ COPY crates/skippy-bench/ crates/skippy-bench/ COPY crates/skippy-prompt/ crates/skippy-prompt/ COPY crates/mesh-mixture-of-agents/ crates/mesh-mixture-of-agents/ +COPY crates/mesh-llm-cli/ crates/mesh-llm-cli/ +COPY crates/mesh-llm-commands/ crates/mesh-llm-commands/ +COPY crates/mesh-llm-embedded-runtime/ crates/mesh-llm-embedded-runtime/ +COPY crates/mesh-llm-events/ crates/mesh-llm-events/ +COPY crates/mesh-llm-hardware-profile/ crates/mesh-llm-hardware-profile/ +COPY crates/mesh-llm-native-runtime/ crates/mesh-llm-native-runtime/ +COPY crates/mesh-llm-runtime-install/ crates/mesh-llm-runtime-install/ +COPY crates/mesh-llm-sdk/ crates/mesh-llm-sdk/ +COPY crates/mesh-llm-tui/ crates/mesh-llm-tui/ COPY tools/xtask/ tools/xtask/ COPY scripts/prepare-llama.sh scripts/build-llama.sh scripts/ COPY third_party/llama.cpp/upstream.txt third_party/llama.cpp/upstream.txt From 6058fdaf3cc2df2d449da090660290e19451e439 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Thu, 11 Jun 2026 10:59:31 +1000 Subject: [PATCH 3/4] Move marketing site to apex meshllm.cloud Repoint the public website's custom domain and canonical URLs from docs.meshllm.cloud to the apex meshllm.cloud, ahead of the DNS cutover: - website/src/CNAME -> meshllm.cloud (GitHub Pages custom domain) - site.js canonical url -> https://meshllm.cloud - funding.json wellKnown + .well-known/funding-manifest-urls -> apex - fly/README.md: console is at public.meshllm.cloud, not the apex docs.meshllm.cloud will become a Cloudflare 301 redirect to meshllm.cloud/docs/ (see DOMAIN_CUTOVER.md). --- fly/README.md | 2 +- website/src/.well-known/funding-manifest-urls | 2 +- website/src/CNAME | 2 +- website/src/_data/site.js | 2 +- website/src/funding.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fly/README.md b/fly/README.md index 96753b9ce3..fbfac9a31b 100644 --- a/fly/README.md +++ b/fly/README.md @@ -6,7 +6,7 @@ Fly app running mesh-llm in `--client` mode — no GPU, just QUIC tunnels to mes |---|---|---| | **console** | [mesh-llm-console.fly.dev](https://mesh-llm-console.fly.dev) | `fly/console/fly.toml` | -Also available at [www.mesh-llm.com](https://www.mesh-llm.com) and [meshllm.cloud](https://meshllm.cloud). +Also available at [public.meshllm.cloud](https://public.meshllm.cloud). ## Architecture diff --git a/website/src/.well-known/funding-manifest-urls b/website/src/.well-known/funding-manifest-urls index abf31868c2..a4983a0764 100644 --- a/website/src/.well-known/funding-manifest-urls +++ b/website/src/.well-known/funding-manifest-urls @@ -1 +1 @@ -https://docs.meshllm.cloud/funding.json +https://meshllm.cloud/funding.json diff --git a/website/src/CNAME b/website/src/CNAME index 1bcac675e5..155c22fb25 100644 --- a/website/src/CNAME +++ b/website/src/CNAME @@ -1 +1 @@ -docs.meshllm.cloud +meshllm.cloud diff --git a/website/src/_data/site.js b/website/src/_data/site.js index 531aef969b..2a171e686c 100644 --- a/website/src/_data/site.js +++ b/website/src/_data/site.js @@ -1,7 +1,7 @@ const site = { title: 'Mesh LLM', description: 'Mesh serves large local models across multiple machines through one OpenAI-compatible endpoint.', - url: 'https://docs.meshllm.cloud', + url: 'https://meshllm.cloud', publicMeshUrl: 'https://public.meshllm.cloud', githubUrl: 'https://github.com/Mesh-LLM/mesh-llm', githubRepo: 'Mesh-LLM/mesh-llm', diff --git a/website/src/funding.json b/website/src/funding.json index 30212bfd7d..4a7833754c 100644 --- a/website/src/funding.json +++ b/website/src/funding.json @@ -21,7 +21,7 @@ }, "repositoryUrl": { "url": "https://github.com/Mesh-LLM/mesh-llm", - "wellKnown": "https://docs.meshllm.cloud/.well-known/funding-manifest-urls" + "wellKnown": "https://meshllm.cloud/.well-known/funding-manifest-urls" }, "licenses": [ "spdx:Apache-2.0" From 75f4af5dd412eb32927fb4cdedd0f51f631f3449 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Thu, 11 Jun 2026 11:00:14 +1000 Subject: [PATCH 4/4] Add domain cutover runbook for meshllm.cloud reshuffle Documents the sequenced steps to move the console to public.meshllm.cloud (done), flip the apex meshllm.cloud to the GitHub Pages marketing site, redirect docs.meshllm.cloud to meshllm.cloud/docs/ via Cloudflare, and decommission the apex cert on Fly. Includes verification curls and rollback. --- fly/DOMAIN_CUTOVER.md | 184 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 fly/DOMAIN_CUTOVER.md diff --git a/fly/DOMAIN_CUTOVER.md b/fly/DOMAIN_CUTOVER.md new file mode 100644 index 0000000000..d65572d787 --- /dev/null +++ b/fly/DOMAIN_CUTOVER.md @@ -0,0 +1,184 @@ +# Domain cutover runbook — meshllm.cloud + +Goal: reshuffle the three public hostnames without breaking live inference or +the public site. + +| Hostname | Today | Target | +|---|---|---| +| `meshllm.cloud` (apex) | Console (Fly) | **Marketing site** (GitHub Pages) | +| `docs.meshllm.cloud` | Marketing + docs (GH Pages via Cloudflare) | **301 redirect → `meshllm.cloud/docs/`** | +| `public.meshllm.cloud` | — | **Console** (Fly) ✅ done | + +Three control planes are involved: + +- **Fly** — runs the console app `mesh-llm-console` (`fly/console/fly.toml`). +- **GitHub Pages** — builds/serves the static site from `website/` via + `.github/workflows/website-pages.yml`; custom domain driven by + `website/src/CNAME`. Pages origin host for this repo is `mesh-llm.github.io`. +- **Cloudflare** — DNS + proxy for the `meshllm.cloud` zone. + +--- + +## Status + +- [x] **Step 1 — Console on `public.meshllm.cloud`** (DONE) + - `fly certs add public.meshllm.cloud -a mesh-llm-console` — issued + verified. + - Cloudflare DNS: `CNAME public -> mesh-llm-console.fly.dev`, **DNS only (grey)**. + - `fly/console/fly.toml` + `fly/Dockerfile`: `VITE_API_URL=https://public.meshllm.cloud`. + - Console redeployed; `https://public.meshllm.cloud/api/status` + `/v1/models` verified. +- [x] **Repo edits for apex** (DONE, committed on branch `console-public-domain`) + - `website/src/CNAME -> meshllm.cloud` + - `website/src/_data/site.js` canonical `url -> https://meshllm.cloud` + - `website/src/funding.json` + `.well-known/funding-manifest-urls -> apex` + - `fly/README.md` updated. +- [ ] **Step 2 — Flip apex to GitHub Pages** (BELOW) +- [ ] **Step 3 — `docs.` redirect** (BELOW) +- [ ] **Step 4 — Decommission apex on Fly** (BELOW) +- [ ] **Step 5 — Follow-up: UI anchor links** (BELOW, no urgency) + +--- + +## Pre-flight + +Record current apex DNS so rollback is instant: + +``` +meshllm.cloud A 66.241.124.167 (Fly) <-- rollback target +``` + +Merge branch `console-public-domain` to `main` before triggering the Pages +build (the build deploys from `main`). The console redeploy already shipped; the +website CNAME change only takes effect once Pages rebuilds from `main`. + +--- + +## Step 2 — Flip apex `meshllm.cloud` to the marketing site + +Order matters: set the Pages custom domain first, then DNS, then build. + +1. **GitHub → repo Settings → Pages** + - Set **Custom domain** to `meshllm.cloud`. Save. + - Leave **Enforce HTTPS** unchecked until the cert provisions (GitHub issues + it after DNS resolves to Pages), then enable it. + +2. **Cloudflare → DNS** for the `meshllm.cloud` zone — repoint the **apex**: + - Remove the existing apex `A 66.241.124.167` (Fly). + - Add the four GitHub Pages A records (Name = `@` / `meshllm.cloud`), + **Proxied (orange) is fine** with Cloudflare: + ``` + A @ 185.199.108.153 + A @ 185.199.109.153 + A @ 185.199.110.153 + A @ 185.199.111.153 + ``` + - (Optional IPv6) AAAA records: + ``` + AAAA @ 2606:50c0:8000::153 + AAAA @ 2606:50c0:8001::153 + AAAA @ 2606:50c0:8002::153 + AAAA @ 2606:50c0:8003::153 + ``` + - Alternative: a single Cloudflare CNAME-flattened `@ -> mesh-llm.github.io` + (Cloudflare flattens apex CNAMEs automatically). Pick A-records OR the + flattened CNAME, not both. + +3. **Trigger the Pages build** so `CNAME` = `meshllm.cloud` is published: + - Merge `console-public-domain` to `main` (touches `website/**`), or + - Run the **Public Website Deploy** workflow via `workflow_dispatch` on `main`. + +4. **Verify** + ```bash + dig +short meshllm.cloud # expect 185.199.108-111.153 (or CF proxy IPs) + curl -sI https://meshllm.cloud/ | grep -i 'server\|content-type' # GH Pages, text/html + curl -s https://meshllm.cloud/docs/ | grep -i '' # Docs title + ``` + +**Rollback:** in Cloudflare, restore apex `A 66.241.124.167`. Apex serves the +console again within DNS TTL. + +--- + +## Step 3 — `docs.meshllm.cloud` → 301 redirect to `meshllm.cloud/docs/` + +`docs.meshllm.cloud` is no longer a Pages custom domain (Pages allows one, now +the apex). Keep the name alive as a redirect so old links never die. + +1. **Cloudflare → DNS** — make `docs` a **proxied** placeholder so the redirect + rule can run (must be **orange cloud**): + ``` + CNAME docs meshllm.cloud (Proxied / orange) + ``` + (If a `docs` record already exists pointing at GitHub Pages, just switch it to + this proxied CNAME.) + +2. **Cloudflare → Rules → Redirect Rules → Create rule** + - **When incoming requests match:** `Hostname equals docs.meshllm.cloud` + - **Then → Dynamic redirect:** + - Status code: **301 (Permanent)** + - Target expression: + ``` + concat("https://meshllm.cloud/docs", http.request.uri.path) + ``` + - **Preserve query string:** on + +3. **Verify** (path-preserving): + ```bash + curl -sI https://docs.meshllm.cloud/ # 301 -> https://meshllm.cloud/docs/ + curl -sI https://docs.meshllm.cloud/install # 301 -> https://meshllm.cloud/docs/install + ``` + +Note: `#fragment` anchors (e.g. `docs.meshllm.cloud/#install`) redirect to +`meshllm.cloud/docs/#install`. The page loads; the anchor is wrong because +`#install` lives on the marketing home (`meshllm.cloud/#install`). Step 5 fixes +the source links. + +--- + +## Step 4 — Decommission the apex on Fly + +Once apex serves Pages and is verified, stop Fly from claiming `meshllm.cloud`: + +```bash +fly certs remove meshllm.cloud -a mesh-llm-console +# Keep public.meshllm.cloud and *.fly.dev certs. +``` + +Verify the console is unaffected: +```bash +curl -s https://public.meshllm.cloud/api/status | head -c 120 +``` + +--- + +## Step 5 — Follow-up: fix in-console UI links (no urgency) + +These are baked into the console UI bundle and require a console rebuild + +redeploy. Not blocking; covered by the Step 3 redirect in the meantime. + +In `crates/mesh-llm-ui/src/`: + +- Keep links meant for **docs** as `https://docs.meshllm.cloud/` (redirects to + `/docs/`) — or update to `https://meshllm.cloud/docs/` directly. +- Fix **marketing-home anchors** to the apex: + - `https://docs.meshllm.cloud/#install` -> `https://meshllm.cloud/#install` + - `https://docs.meshllm.cloud/#blackboard` -> `https://meshllm.cloud/#blackboard` +- Files with these refs: `features/app-tabs/data.ts`, + `features/shell/components/TopNav.tsx`, `features/app-shell/components/AppHeader.tsx`, + `features/chat/components/ChatPage.tsx`, + `features/configuration/pages/ConfigurationPage.tsx`, + `constants/default-system-prompt.md`, plus their `.test.tsx` expectations. + +After editing, rebuild + redeploy the console: +```bash +fly deploy --config fly/console/fly.toml --dockerfile fly/Dockerfile +``` + +--- + +## Quick reference — final DNS state (Cloudflare) + +| Type | Name | Target | Proxy | +|---|---|---|---| +| A | `@` | 185.199.108–111.153 (GH Pages) | proxied or DNS-only | +| CNAME | `public` | `mesh-llm-console.fly.dev` | **DNS only (grey)** | +| CNAME | `docs` | `meshllm.cloud` | **Proxied (orange)** + redirect rule |