Cloudflare deployment
Pages + Worker for AXIS: Pages axis.hoox.sh (project axis), Worker worker.axis.hoox.sh, CLI deploy, bindings, security checklist.
This page
Cloudflare® deployment
Abstract
Production AXIS on Cloudflare® is a split deploy:
| Piece | Role |
|---|---|
| Pages | Static PWA (dist/) |
| Worker | JSON API + WebSocket (worker/) |
Pages: project axis, canonical https://axis.hoox.sh. Worker: script worker-axis at https://worker.axis.hoox.sh.
Evaluation truth: Worker /api/run proxies to EXTERNAL_BACKEND unless the gated Pyodide path is fully implemented and enabled. You still need a Python host (VPS Flask, container, etc.) for real Pine Script™ fidelity today.
Prefer the AXIS CLI for setup and deploy (axis deploy).
Conceptual model
Rendering…
Deploy procedure
1. Provision bindings (once)
See Worker bindings:
- KV
API_KEYS,USAGE - D1
pynescript+ schema - Optional R2, Durable Objects
2. Configure secrets / vars
Production checklist:
| Setting | Production guidance |
|---|---|
EXTERNAL_BACKEND | Public HTTPS URL of Flask/PYNE API (axis secret put) |
ALLOWED_ORIGIN | Extra exact origins (comma-separated); product hosts + *.axis.pages.dev are built-in — CORS |
ADMIN_TOKEN | Secret, strong |
API_KEYS KV | Bind in prod — D1 without KV fails closed (API_KEYS_REQUIRED) |
ALLOW_OPEN_KEYS | "0" or unset |
REQUIRE_RUN_AUTH | "1" optional force Bearer on /api/run |
GITHUB_OAUTH_CLIENT_ID | Env preferred; never rely on body clientId alone |
PYODIDE_IN_WORKER | "disabled" until wheel pipeline ready |
3. Deploy Worker
# Preferred: AXIS CLI
axis deploy
# or: make axis-deploy
# Schema first (remote)
axis setup d1 --remote
# Equivalent raw wrangler
cd worker
bun install
bun run deploy
4. Build & deploy Pages
bun run axis deploy pages
# or
bun run build
bunx wrangler pages deploy dist --project-name=axis
# Make: make pages-deploy
5. Point the PWA
- Engine endpoint: Worker URL (if path-mapped to
/run) or Flask URL directly - Cloud storage endpoint: Worker origin
- Ensure CORS allows Pages origin
Internals
| Path | Role |
|---|---|
worker/wrangler.toml / .example | Worker name + bindings |
worker/README.md | Ops narrative |
worker/package.json | deploy scripts |
packages/cli/ | axis deploy / axis health |
Makefile axis-deploy / pages-deploy / worker-deploy | Convenience targets |
Health check
axis health
# or
curl -sS https://<worker>/health
# service: worker-axis
Invariants & edge cases
- Pages ≠ Worker host — CORS required unless same-origin routing via custom domain routes.
- Localhost EXTERNAL_BACKEND is useless from the edge.
- DO migrations apply on deploy when uncommented.
- Observability enabled in wrangler for log tails (
wrangler tail).
Failure modes
| Issue | Fix |
|---|---|
| 503 NO_BACKEND | Set reachable EXTERNAL_BACKEND |
| CORS blocked | ALLOWED_ORIGIN mismatch |
| SPA HTML for wheels | Pages must serve /vendor and /pyodide as static files |
| Stream NO_DO | Enable SessionDO bindings |