Skip to content

Deploy with Cloudflare

Cloudflare integrates with Tyravel as optional modules — pick only what you need. Tyravel 1.x still runs on Node.js (Fly, Railway, Docker, VPS). Full Tyravel on Workers is not supported yet.

New apps ship a copy-paste guide at deploy/cloudflare.md with the same module layout.

Pick your modules

I want…ModuleNeeds Node origin?
TLS, DDoS, hide origin IPModule 1: DNS + proxyYes
Cache public GET at the edgeModule 2: CDN + edge cacheYes (usually with Module 1)
S3-compatible file storageModule 3: R2Yes for uploads; no proxy required
Host Vite/client buildModule 4: PagesAPI/SSR on separate host
Staging without public portsModule 5: TunnelYes (local or remote)
WAF, rate limits, botsModule 6: WAF + securityYes (usually with Module 1)

Deploy the Node origin first — Fly.io, Railway, or Docker.

Common combinations

StackModules
CDN in front of full-stack SSR1 + 2
API + R2 uploads1 + 3 (or 3 alone for storage)
SPA on Pages, API on Fly1 + 4 (+ 3 optional)
Production + staging tunnel1 + 2 + 5
Hardened public API1 + 2 + 6

Product status

Cloudflare productTyravel integrationModule
DNS + proxyOrigin on Node1
Cache / CDNETag middleware + cache rules2
R2@tyravel/storage-r23
PagesVite/client dist/4
TunnelPreview/staging5
WAF / DDoS / TLSIn front of origin1, 6
Workers (full Tyravel)Not supported (roadmap)
D1Not supported
Queues (CF)Use tyravel queue:work on origin

Module 1: DNS + proxy

When: Custom domain, free TLS, DDoS protection, orange-cloud origin masking.

Prerequisites: Tyravel running with a public hostname.

  1. Add the domain in Cloudflare DNS.
  2. Create a proxied record — CNAME to Fly/Railway hostname, or A/AAAA to a VPS IP.
  3. SSL/TLSFull (strict).
  4. Origin env:
bash
APP_URL=https://your-domain.example
TYRAVEL_HOST=0.0.0.0
SESSION_SECURE=true

Use TRUST_PROXY=true when the app reads X-Forwarded-*. WebSocket upgrades pass through; broadcasting still terminates on the Node origin (Redis fan-out for multiple instances).

Standalone: TLS + DDoS without edge caching.


Module 2: CDN + edge cache

When: Repeat traffic to public, cacheable GET routes.

Prerequisites: Module 1 or another CDN in front of the same origin.

typescript
import { createHttpCacheMiddleware } from '@tyravel/http';

Route.get('/posts/:slug', showPost, {
  middleware: [createHttpCacheMiddleware({ maxAge: 300 })],
});

In Cloudflare: enable Origin Cache Control, add Cache Rules for public GET paths, and bypass authenticated routes (/dashboard/*, anything with Set-Cookie). See edge cache cookbook.

RouteEdge cache?
Public HTML / JSONYes — short max-age + ETag
Session / dashboardBypass
/build/* fingerprinted assetsYes — long max-age
WebSocketBypass

Skip if all routes are personalized or you only need TLS (Module 1).


Module 3: R2 object storage

When: Uploads, exports, or static blobs — independent of proxy/CDN.

Prerequisites: Node origin. Works without Module 1.

bash
npm install @tyravel/storage-r2

Register R2StorageServiceProvider and configure config/storage.ts. Full config: Storage guide.

bash
R2_BUCKET=tyravel
R2_ENDPOINT=https://<account_id>.r2.cloudflarestorage.com
R2_ACCESS_KEY_ID=...
R2_SECRET_ACCESS_KEY=...
R2_PUBLIC_URL=https://files.your-domain.example  # optional

Standalone: Storage only — no Cloudflare proxy required.


Module 4: Pages (static assets)

When: SPA front-end; Tyravel API or SSR on a subdomain.

HostServes
www.example.com (Pages)Vite client dist/
api.example.com (Node)Tyravel (headless or full stack)

Connect Pages to Git or wrangler pages deploy dist. Point api.example.com through Module 1 at the Tyravel origin. Set VITE_API_URL on the client build.

Subdomain split is simpler than single-hostname origin rules. Headless API origins skip view:cache.


Module 5: Tunnel (previews)

When: Staging, PR previews, local demos.

bash
# Quick (no account)
cloudflared tunnel --url http://127.0.0.1:3000

# Named tunnel
cloudflared tunnel create tyravel-staging
cloudflared tunnel route dns tyravel-staging staging.example.com
cloudflared tunnel run tyravel-staging

Set APP_URL to the tunnel hostname. Not a production origin replacement.


Module 6: WAF + security

When: Public API or SSR behind Module 1.

Prerequisites: Module 1.

  • WAF managed rulesets
  • Rate limiting on /api/* or login routes
  • Bot Fight Mode (test against legitimate API clients)
  • Disable Rocket Loader on WebSocket or strict CSP paths

Pair with Tyravel auth throttling and APP_DEBUG=false.


Not supported on Workers (yet)

Tyravel requirementWorkers limitation
Node.js 26+ (node:sqlite, etc.)Subset compat
view:cache, framework diskNo persistent local disk
tyravel queue:workNo long-lived processes
tyravel start --clusterIsolates, not node:cluster
WebSocket hub + RedisCustom fan-out needed

Planned: headless JSON on Workers + Hyperdrive, then precompiled SSR. See Tyravel Cloud and ROADMAP.


Troubleshooting by module

ModuleSymptomFix
1Redirect loopSSL Full (strict); valid origin HTTPS
1Wrong client IPTRUST_PROXY=true
2Stale HTMLShorter max-age; bypass auth; ETag
2Session lostBypass Set-Cookie routes; SESSION_SECURE=true
3R2 403Token permissions; bucket CORS
4CORS errorsAPI allows Pages origin
5Tunnel 502TYRAVEL_HOST=0.0.0.0 on origin
6WS dropsBypass Rocket Loader

Released under the MIT License.