From e55c44818d2f78f0a76f59dff55da546ea309b3d Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Mon, 4 May 2026 04:48:28 -0700 Subject: [PATCH] docs: update Fly Machines references to AWS EC2 + Railway (Apr 2026 migration) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Apr 2026 SaaS migration moved tenant + workspace compute from Fly Machines to AWS EC2, and the control plane from Fly to Railway. Update docs that still claim Fly Machines as the production provisioner; leave historical / changelog references intact. Files changed: - content/docs/architecture.mdx — SaaS Deployment Modes section now states each tenant runs on a dedicated AWS EC2 instance provisioned by the Railway-hosted control plane; adds an Apr 2026 migration note + link to the molecule-controlplane README "Migration history". - content/docs/tutorials/fly-machines-provisioner.md — preserved as historical PR #501 lineage record; adds a DEPRECATED banner at the top pointing to the EC2 provisioner (`internal/provisioner/ec2.go`) and the controlplane migration history. Tutorial body kept untouched. - content/docs/self-hosting/admin-token.mdx — drops the "Fly.io (recommended for self-hosted)" framing since the SaaS no longer runs on Fly. Adds a Railway example alongside the existing Fly.io example, keeps both as illustrative options. Rotation steps generalised to "the host's secrets store" (Railway, Fly.io, AWS Secrets Manager all work). - content/docs/tutorials/saas-federation.md — security model table row "No Fly/API tokens on tenant" → "No AWS/cloud API tokens on tenant" so it matches the EC2 + Neon architecture the rest of the page already describes. Untouched on purpose: - content/docs/changelog.mdx Phase 33 "Fly Machines provisioner" entry — changelogs are historical record. - content/docs/architecture/wildcard-dns-proxy.md — only references Fly.io as a generic SaaS example, not as Molecule's infrastructure. - content/docs/security/safe-mcp-advisory.mdx — `fly.toml` is one of several illustrative deploy-target egress-lock examples for self-hosters. - content/docs/guides/external-workspace-quickstart.md — lists Fly / Railway / DigitalOcean as example self-host targets for external workspaces (still valid). Source of truth: molecule-controlplane README "Migration history" (https://github.com/Molecule-AI/molecule-controlplane#migration-history). Verified: \`pnpm build\` (Next.js 16.2.4) — 111/111 static pages green. Co-Authored-By: Claude Opus 4.7 (1M context) --- content/docs/architecture.mdx | 4 ++- content/docs/self-hosting/admin-token.mdx | 34 ++++++++++++++++--- .../tutorials/fly-machines-provisioner.md | 13 ++++++- content/docs/tutorials/saas-federation.md | 2 +- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/content/docs/architecture.mdx b/content/docs/architecture.mdx index 16b05c9..f1fa5f1 100644 --- a/content/docs/architecture.mdx +++ b/content/docs/architecture.mdx @@ -295,7 +295,9 @@ docker compose up ### SaaS -Hosted at `moleculesai.app` with per-tenant isolation. Each tenant gets a dedicated Fly Machine running the tenant image. The `MOLECULE_ORG_ID` env var gates API access -- every non-allowlisted request must carry a matching `X-Molecule-Org-Id` header or gets a 404. When unset, the guard is a passthrough so self-hosted and dev environments are unaffected. +Hosted at `moleculesai.app` with per-tenant isolation. Each tenant gets a dedicated AWS EC2 instance running the tenant image, provisioned by the control plane (`api.moleculesai.app`, hosted on Railway). The `MOLECULE_ORG_ID` env var gates API access -- every non-allowlisted request must carry a matching `X-Molecule-Org-Id` header or gets a 404. When unset, the guard is a passthrough so self-hosted and dev environments are unaffected. + +> **Migration note (Apr 2026):** SaaS infrastructure was migrated from Fly Machines to AWS EC2 (workspaces) + Railway (control plane). See the [`molecule-controlplane` README "Migration history"](https://github.com/Molecule-AI/molecule-controlplane#migration-history) for the canonical record. ### Tenant Image diff --git a/content/docs/self-hosting/admin-token.mdx b/content/docs/self-hosting/admin-token.mdx index b0297e7..c84c42c 100644 --- a/content/docs/self-hosting/admin-token.mdx +++ b/content/docs/self-hosting/admin-token.mdx @@ -30,7 +30,28 @@ platform. ## Setting ADMIN_TOKEN in production -### Fly.io (recommended for self-hosted) +The platform reads `ADMIN_TOKEN` from the process environment, so any +production-grade host with a secrets store works. Pick the path that +matches your deployment target. + +> **Note (Apr 2026):** The Molecule AI SaaS itself runs on AWS EC2 +> (workspaces) + Railway (control plane). Self-hosters can use any host +> with secret-injection (Railway, Fly.io, AWS, GCP, bare-metal) — the +> examples below are illustrative, not prescriptive. See the +> [`molecule-controlplane` README "Migration history"](https://github.com/Molecule-AI/molecule-controlplane#migration-history) +> for the canonical SaaS infrastructure record. + +### Railway + +In the Railway dashboard, go to your service → Variables and add +`ADMIN_TOKEN`, then redeploy. Or via CLI: + +```bash +railway variables --set ADMIN_TOKEN="your-generated-token" +railway up +``` + +### Fly.io ```bash fly secrets set ADMIN_TOKEN="your-generated-token" @@ -92,10 +113,13 @@ payload with a `count` field, the token is working. To rotate without downtime: -1. **Deploy** the new token: `fly secrets set ADMIN_TOKEN="new-token" && fly deploy` -2. **Verify** the new token works (see above) -3. **Remove** the old token: `fly secrets unset OLD_TOKEN_NAME` (Fly does not - persist old secret values after unset) +1. **Deploy** the new token via your host's secrets store, e.g. + `railway variables --set ADMIN_TOKEN="new-token" && railway up` + or `fly secrets set ADMIN_TOKEN="new-token" && fly deploy`. +2. **Verify** the new token works (see above). +3. **Remove** the old token from the secrets store. Most managed hosts + (Railway, Fly.io, AWS Secrets Manager) do not persist old secret + values after unset. ## Related diff --git a/content/docs/tutorials/fly-machines-provisioner.md b/content/docs/tutorials/fly-machines-provisioner.md index 9d1acab..f55db9e 100644 --- a/content/docs/tutorials/fly-machines-provisioner.md +++ b/content/docs/tutorials/fly-machines-provisioner.md @@ -1,8 +1,19 @@ --- -title: "Provisioning Workspaces on Fly Machines (CONTAINER_BACKEND=flyio)" +title: "Provisioning Workspaces on Fly Machines (CONTAINER_BACKEND=flyio) — DEPRECATED" --- # Provisioning Workspaces on Fly Machines (CONTAINER_BACKEND=flyio) +> **DEPRECATED — historical reference only.** As of April 2026, the SaaS +> control plane and tenant/workspace fleets migrated off Fly Machines to +> **AWS EC2 (workspaces) + Railway (control plane)**. The current +> production provisioner lives at +> [`molecule-controlplane/internal/provisioner/ec2.go`](https://github.com/Molecule-AI/molecule-controlplane/blob/main/internal/provisioner/ec2.go). +> The Fly provisioner code (`fly.go`, `internal/flyapi/`) remains in the +> tree as legacy awaiting cleanup but is no longer the production path. +> See the [`molecule-controlplane` README "Migration history"](https://github.com/Molecule-AI/molecule-controlplane#migration-history) +> for the canonical record. This page is preserved as the original PR +> #501 lineage record; do not follow it for new self-hosted deployments. + Molecule AI can provision agent workspaces on [Fly Machines](https://fly.io/docs/machines/) instead of local Docker containers. When `CONTAINER_BACKEND=flyio` is set, every `POST /workspaces` creates a Fly Machine and boots the workspace agent inside it — with tier-based resource limits, env-var injection, and A2A registration handled automatically. The platform manages the workspace (lifecycle, auth, routing); Fly manages the machine it runs on. > **Scope note (PR #501):** Workspace images must already be published to GHCR before provisioning. The `delete` and `restart` platform endpoints are not yet fully wired to the Fly provisioner — use `flyctl machine stop/destroy` for teardown until a follow-up PR lands. diff --git a/content/docs/tutorials/saas-federation.md b/content/docs/tutorials/saas-federation.md index 26ab6e7..ab73c10 100644 --- a/content/docs/tutorials/saas-federation.md +++ b/content/docs/tutorials/saas-federation.md @@ -226,7 +226,7 @@ This terminates all EC2 instances, drops the Neon branch, and removes the org re |---|---|---| | Database | Neon branch-per-tenant | Tenant's branch, operator has no direct access | | Compute | EC2 in tenant's VPC | Control plane provisions, operator manages SG rules | -| Credentials | No Fly/API tokens on tenant | All cloud credentials held by control plane | +| Credentials | No AWS/cloud API tokens on tenant | All cloud credentials held by control plane | | API access | Org-scoped API keys | Tenant manages their own keys; operator has CP-level override | | Network | Security group: port 443 from platform only | Control plane manages; tenant can't modify |