feat(web): vercel deployment and vds compose/systemd setup
Add Vercel config with React Router preset, vercel-build script and /api/auth rewrite to the Convex site. Add VDS staging compose for the Rivet engine and runner plus systemd units, deployment plan, and Docker/Vercel ignore rules. Lockfile covers both the web and agents dependency additions.
This commit is contained in:
63
deploy/compose/Caddyfile
Normal file
63
deploy/compose/Caddyfile
Normal file
@@ -0,0 +1,63 @@
|
||||
# Caddy reverse proxy for the Zopu VDS staging agent stack.
|
||||
#
|
||||
# This is the ONLY public ingress to the private worker (see
|
||||
# docs/DEPLOYMENT_PLAN.md §"Public surface"). It terminates TLS for the Flue
|
||||
# callback hostname that Convex reaches, then forwards ONLY the documented agent
|
||||
# worker paths to the internal `agents` service.
|
||||
#
|
||||
# Hard rules this file enforces:
|
||||
# - No generic /api/* proxy and no browser-to-Flue traffic (DEPLOYMENT_PLAN.md
|
||||
# line 86). Browsers talk only to Convex.
|
||||
# - Only the Flue Node worker paths Convex actually calls are routed:
|
||||
# /agents/zopu/<organizationId> conversation admission
|
||||
# /internal/work-attempts/* work attempt execute + cancel
|
||||
# /api/rivet/* RivetKit Actor gateway surface
|
||||
# /workflows/* Flue workflow execution
|
||||
# /health liveness probe (Compose healthcheck/CI)
|
||||
# - Everything else returns 404. The private worker protocol stays narrow.
|
||||
#
|
||||
# Variables are injected by the `caddy` Compose service environment:
|
||||
# {$AGENTS_HOST} public hostname, e.g. agents-staging.example.com
|
||||
# {$AGENTS_UPSTREAM} internal upstream host:port, e.g. agents:3000
|
||||
# {$ACME_EMAIL} email for the Let's Encrypt account
|
||||
#
|
||||
# TLS certs and the ACME account persist in the caddy-data volume. Caddy serves
|
||||
# its own ACME HTTP-01 challenge responses on :80 automatically, so the :80
|
||||
# block below only redirects everything else to HTTPS — worker traffic is never
|
||||
# served over plain HTTP.
|
||||
{
|
||||
email {$ACME_EMAIL}
|
||||
}
|
||||
|
||||
# --- TLS termination for the Flue callback hostname ---------------------------
|
||||
{$AGENTS_HOST} {
|
||||
encode zstd gzip
|
||||
|
||||
# Conversation admission: Convex POSTs to /agents/zopu/<organizationId>.
|
||||
# The conversationRoute middleware requires the FLUE_DB_TOKEN bearer and the
|
||||
# matching x-zopu-organization-id header.
|
||||
reverse_proxy /agents/zopu/* {$AGENTS_UPSTREAM}
|
||||
|
||||
# Internal work-attempt execute/cancel. Requires the internalRoute bearer.
|
||||
reverse_proxy /internal/work-attempts/* {$AGENTS_UPSTREAM}
|
||||
|
||||
# RivetKit Actor gateway surface (app.all("/api/rivet/*")). Routed so the
|
||||
# runtime registry handler is reachable for actor metadata/start.
|
||||
reverse_proxy /api/rivet/* {$AGENTS_UPSTREAM}
|
||||
|
||||
# Flue workflow execution (workflows/plan-work). Requires the workflowRoute
|
||||
# bearer + x-zopu-organization-id header.
|
||||
reverse_proxy /workflows/* {$AGENTS_UPSTREAM}
|
||||
|
||||
# Caddy routes the liveness request to the actual worker; it must not mask a
|
||||
# failed worker process with a synthetic successful response.
|
||||
reverse_proxy /health {$AGENTS_UPSTREAM}
|
||||
|
||||
# Everything else is not part of the private worker protocol.
|
||||
respond 404
|
||||
}
|
||||
|
||||
# --- HTTP → HTTPS redirect (Caddy still answers ACME challenges on :80) -------
|
||||
:80 {
|
||||
redir https://{host}{uri} permanent
|
||||
}
|
||||
Reference in New Issue
Block a user