Deployment Topology, Proxy Conflict & CI after eu-1
smo1 intermediate 7 min read
ELI5
Three hosts, three jobs. Cloudflare runs the edge worker on smo1.io. Railway runs the API and its database. Vercel runs the two websites. The worker shows marketing pages by fetching them from a second address, origin.smo1.io, that does not pass back through Cloudflare, otherwise it would end up asking itself. Since 2026-10-24 most of the automated checks run once a night on GitHub’s machines instead of on every push.
Technical Deep Dive
Source: zoomies-edge wrangler.toml:1-67, .github/workflows/deploy-cloudflare.yml:1-60, .github/workflows/ci.yml:1-24 (origin/main 5bdde59); purr-api .github/workflows/nightly-gates.yml:1-40 (bb6cfc2); meow-web .github/workflows/ci.yml:1-20 (e5d808c); smo1-io docs/decisions/2026-09-02-production-api-host.md (status open, “Ratified by alex@devarno.com”), docs/decisions/2026-10-24-eu1-retire-ci-nightly-gates.md (status open, sign-off PENDING), .github/workflows/prod-health.yml:18 (1f19667); public probes 2026-10-25.
Production map
flowchart TB U[Visitor] -->|"smo1.io/*"| Z[zoomies-edge Worker] U -.->|"petrova.smo1.io/*, no DNS yet"| Z Z -->|"API_URL = purr-api-production.up.railway.app"| P[purr-api on Railway] Z -->|"LANDING_ORIGIN = origin.smo1.io"| W[whiskers-landing on Vercel] D[Dashboard user] -->|"app.smo1.io"| M[meow-web on Vercel] M -->|"PURR_API_URL"| P X[API clients and x402 Gateway] -->|"purr.smo1.io, Cloudflare proxied"| P P --> PG[(Railway Postgres)]| Project | Platform | Host | Deploys by |
|---|---|---|---|
| zoomies-edge | Cloudflare Workers | routes smo1.io/*, petrova.smo1.io/* | deploy-cloudflare.yml on push to main: wrangler deploy --env lion, then curls https://smo1.io/health |
| purr-api | Railway, project “SMO1 • IO” | purr.smo1.io and purr-api-production.up.railway.app | Railway git auto-deploy from main |
| meow-web | Vercel | app.smo1.io | Vercel git integration |
| whiskers-landing | Vercel | origin.smo1.io | Vercel git integration |
Note the Worker calls the Railway hostname, not purr.smo1.io (wrangler.toml:39). The 2026-09-02 decision made purr.smo1.io the production API host after api.smo1.io was found not to resolve; on 2026-10-25 purr.smo1.io answered through Cloudflare (cf-ray), which the x402 provenance check requires (smo1-025). The Railway hostname still serves every route except the paid create.
The proxy conflict
Cloudflare routes smo1.io/* to the Worker. If the Worker fetched https://smo1.io/pricing it would be routed to itself. The landing site is therefore attached to Vercel as origin.smo1.io, a DNS-only record: on 2026-10-25 it answered server: Vercel with no cf-ray. If someone orange-clouds it, non-slug pages break.
Health checks
- Worker:
GET https://smo1.io/healthreturns{"status":"ok","environment":"lion",...}from the Worker itself. - purr-api:
GET https://purr.smo1.io/healthreturns{"status":"ok"}; smo1-ioprod-health.ymlchecks it daily at 06:52 UTC.
CI after eu-1
eu-1, the Hermes runner host, retires with no successor. On 2026-10-24 purr-api (#81), zoomies-edge (#26), whiskers-landing (#19), catnip-packages (#23) and smo1-io (#107) merged a change that removes push and pull_request triggers from gate CI. nightly-gates.yml runs on GitHub-hosted ubuntu-latest once a night (purr-api 02:43 UTC, zoomies-edge 02:55, smo1-io 03:13) and calls ci.yml only if main moved since the last green run. So PRs in those repos show no checks. meow-web was not part of the flip and still runs CI on push and pull request.
The governing smo1-io decision is status: open, sign-off: PENDING; its text says “the five PRs it describes are open and unmerged”, which stopped being true when they merged. Deploys were not touched: the Worker still deploys on push to main.
Key Terms
- Proxy conflict — a Worker fetching its own routed hostname loops back into itself
- origin.smo1.io — DNS-only Vercel attachment of whiskers-landing
- nightly-gates.yml — once-a-night gate entry point; runs
ci.ymlonly when main moved - lion — the only wrangler environment that is deployed
Q&A
Q: Which platform hosts each project in production? A: zoomies-edge on Cloudflare Workers, purr-api and its Postgres on Railway, meow-web and whiskers-landing on Vercel. catnip-packages and litter-box are not deployed.
Q: What is the proxy conflict and how is it resolved?
A: The Worker owns smo1.io/*, so fetching a landing page from smo1.io would route back to the Worker. It is resolved by serving whiskers-landing on origin.smo1.io, which is DNS-only to Vercel, and setting that as LANDING_ORIGIN.
Q: What is the purpose of origin.smo1.io? A: It is the address the Worker fetches marketing pages, static assets and unknown paths from. Visitors are not meant to use it, though it is publicly reachable.
Q: Where does smo1 gate CI run since eu-1 retired, and what is the governing decision’s status?
A: On GitHub-hosted runners, once a night via nightly-gates.yml, in five of the six repos; meow-web keeps per-push CI. The decision 2026-10-24-eu1-retire-ci-nightly-gates is still open with sign-off pending, even though its PRs are merged.
Examples
A contributor opens a purr-api PR and sees no checks. That is expected: run gh workflow run ci.yml --ref <branch> to gate it by hand, or wait for the 02:43 UTC nightly after merge. A zoomies-edge merge still deploys immediately, because deploy-cloudflare.yml kept its push trigger.
neighbors on the map
- Request Routing & Edge Resolution debugging why a slug returns 404 instead of redirecting
- Edge Redirect Flow debugging why a slug does not redirect
- petrova.smo1.io: Custom-Domain Links for petrova.codes Artifacts provisioning or debugging petrova.smo1.io links
- Launch Gates (gates/v1) and the Demo Tenant asking what still blocks smo1 from taking money