[VPS demo topology]

Single-box demo: static AXIS dist + Flask Pro API (+ optional reverse proxy) without Cloudflare.

VPS demo topology

Abstract

A VPS demo is the lowest-surprise production-like setup for Pine evaluation: one machine runs Flask (PYNE) and serves the static AXIS build. Optional nginx/caddy terminates TLS and reverse-proxies /run same-origin to avoid CORS.

No Worker required. Cloud storage and DO streams will not work without the Worker.

Conceptual model

Interface surface

Processes

ProcessCommandPort
Build (CI or once)cd frontend && bun run build
StaticPORT=8081 python axis_pwa_server.py8081
APImake run / python -m backend.app5002

Same-origin proxy sketch (Caddy)

axis.example.com {
  handle /run* {
    reverse_proxy 127.0.0.1:5002
  }
  handle {
    reverse_proxy 127.0.0.1:8081
  }
}

Then PWA endpoint = https://axis.example.com and the server engine posts to /run on the same host.

Minimal without TLS

  • Static :8081, Flask :5002
  • Set endpoint http://VPS_IP:5002
  • Open firewall; accept CORS from static origin (configure Flask accordingly)

Internals

ConcernNotes
Pyodide offlineShip full dist including vendor + pyodide
Process supervisorsystemd units for flask + axis_pwa_server
UpdatesRebuild dist artifact; restart static only
SecretsFlask admin / pro keys separate from Worker

Worked example — systemd sketch

# /etc/systemd/system/axis-pwa.service
[Service]
WorkingDirectory=/opt/axis/frontend
Environment=PORT=8081
ExecStart=/usr/bin/python3 axis_pwa_server.py
Restart=on-failure

Pair with an existing backend unit for Flask.

Invariants & edge cases

  1. CPU/RAM — Pyodide is browser-side; VPS load is Flask evaluate concurrency.
  2. Do not expose open admin tokens.
  3. Disk — dist + wheels are tens of MB.
  4. Hybrid: VPS Flask as EXTERNAL_BACKEND for a CF Worker still works if VPS has a public URL.

Failure modes

IssueFix
Mixed contentHTTPS page calling HTTP Flask blocked
CORSPrefer same-origin proxy
502 on /runFlask crashed; check journalctl

See also