Hosted Deployment#
Co-Vibe can be hosted as a single Next.js container.
The hosted app is the customer control plane: WorkOS login, tenants,
workspaces, dashboards, MCP API, verified telemetry storage, and reports.
Developers still install the local companion in each tracked repo and point
COVIBE_BASE_URL at this hosted URL.
The checked-in Docker path is still useful for local and single-host rehearsal,
and it now uses PostgreSQL rather than a file-backed app database. The GCP production
target is Cloud Run plus Cloud SQL for PostgreSQL. PostgreSQL schema
initialization and a runtime bridge now exist; run both PostgreSQL smokes before
the production doctor is allowed to pass. See
gcp-production.md.
Container Path#
The repo ships a provider-neutral Dockerfile.
It uses Next.js standalone output:
next.config.tssetsoutput: "standalone".Dockerfilerunsnpm ciandnpm run build.- The dependency stage uses a BuildKit npm cache mount plus npm fetch retries so customer image builds tolerate transient registry resets.
- The runtime image runs
node server.jsfrom.next/standalone. publicand.next/staticare copied into the runtime image.- The ONNX native runtime bin is copied explicitly because Next standalone does
not trace the adjacent shared library needed by
@huggingface/transformers. /app/datais a volume for profile-photo uploads..github/workflows/customer-readiness.ymlruns readiness and a container runtime smoke on pull requests, pushes tomain, and manual dispatch. When WorkOS secrets are configured, CI also runs the fullnpm run readiness:customerhandoff gate; whenCOVIBE_HOSTED_URLis also configured, or a manual dispatch provideshosted_url, CI runsnpm run readiness:handoff -- "$COVIBE_HOSTED_URL"against the permanent domain. Otherwise those jobs report skips.
Required runtime env:
COVIBE_AUTH_MODE=workosWORKOS_CLIENT_IDWORKOS_API_KEYWORKOS_COOKIE_PASSWORDNEXT_PUBLIC_WORKOS_REDIRECT_URI=https://<host>/callbackCOVIBE_DATABASE_BACKEND=postgresDATABASE_URL=postgres://...(NON-superuser, non-owner app role — subject to RLS)COVIBE_POSTGRES_ADMIN_URL=postgres://...(owner/superuser, init + provisioning only; required for self-contained auto-init with privilege separation)COVIBE_UPLOAD_DIR=/app/data/uploads
Optional runtime env:
COVIBE_HOSTED_URLWORKOS_COOKIE_MAX_AGECOVIBE_REMEMBER_ME_DAYSCOVIBE_COMPANION_INSTALL_COMMANDCOVIBE_PAXEL_ENABLED/COVIBE_PAXEL_STALE_MS(seepaxel-integration.md)ANTHROPIC_API_KEYCOVIBE_SUMMARY_MODEL
Our Hosted Docker Profile#
For a VPS or managed Docker host, use the checked-in Compose profile:
export COVIBE_HOSTED_URL=https://co-vibe.example.com
export NEXT_PUBLIC_WORKOS_REDIRECT_URI=https://co-vibe.example.com/callback
export WORKOS_CLIENT_ID=...
export WORKOS_API_KEY=...
export WORKOS_COOKIE_PASSWORD=...
docker compose up -d --builddocker-compose.yml binds the app to 127.0.0.1:3000 by default for a reverse
proxy such as Caddy, nginx, or a load balancer that terminates HTTPS. Set
COVIBE_BIND=0.0.0.0 only when another network layer restricts access. Runtime
state lives in the named covibe-data volume mounted at /app/data, which
stores profile uploads across container restarts. App state lives in PostgreSQL.
The Postgres service bootstraps covibe_owner as the superuser/owner used via
COVIBE_POSTGRES_ADMIN_URL; on first boot the app connects as the owner to
create the schema and provision the non-superuser covibe_app role named in
DATABASE_URL, then runs all subsequent queries as that least-privilege role so
row-level security is enforced.
COVIBE_HOSTED_URL is forwarded into the container when present so in-container
doctor/readiness checks use the same origin as the operator shell. The Compose
profile includes a PostgreSQL service for rehearsal; production Cloud Run should
use Cloud SQL instead.
For a single-host HTTPS deployment, point DNS at the machine, allow ports 80 and 443 through the host firewall, make sure the WorkOS dashboard allowlists the same deployed callback, then run the proxy profile:
export COVIBE_HOSTED_URL=https://co-vibe.example.com
export COVIBE_HOSTNAME=co-vibe.example.com
export NEXT_PUBLIC_WORKOS_REDIRECT_URI=https://co-vibe.example.com/callback
export WORKOS_CLIENT_ID=...
export WORKOS_API_KEY=...
export WORKOS_COOKIE_PASSWORD=...
docker compose --profile proxy up -d --buildThe proxy profile starts Caddy from deploy/caddy/Caddyfile, terminates HTTPS
for COVIBE_HOSTNAME, and forwards traffic to the private covibe:3000
container. Caddy certificate and account state live in caddy-data and
caddy-config volumes so renewals survive restarts.
After the proxy/domain is live, run:
npm run readiness:handoff -- https://co-vibe.example.comRelease Gate#
Before every pull request or internal release:
npm run readinessCI runs the same command on a clean Ubuntu runner and separately runs:
npm run smoke:packageinside readiness to prove the companion package installs and configures a clean external repo.npm run smoke:containerin the container job to build the image, boot it, and verify production auth fails closed when WorkOS env is absent.npm run readiness:customerin a conditional customer-handoff job when WorkOS secrets are configured.
npm run build first runs npm run build:companion, which stages a minimal
companion manifest and packs public/downloads/co-vibe.tgz. The companion
tarball depends only on the local runtime packages it needs, not on the hosted
app's Next/WorkOS/database/embedding dependencies. The hosted container serves
that file from /downloads/co-vibe.tgz, and Agent Setup uses the current host
origin in the copied install command. Set COVIBE_COMPANION_INSTALL_COMMAND
only when overriding the hosted tarball with a public npm package or internal
registry command. Unsafe overrides with shell chaining, comments, line
continuations, token-looking values, or --token fall back to the hosted
tarball. If the command is public npm, verify
publication first:
npm run security also runs npm run check:package, which allowlists the
tarball contents, rejects unexpected dependencies, and rejects env files, local
state, app routes, tests, reports, or broad server code before the package can
be shipped.
npm view co-vibe versionnpm run smoke:containerThe container smoke first runs a short Docker daemon probe. If Docker Desktop or the host daemon is not responding, the script fails before starting the image build and tells the operator to restart Docker.
With WorkOS env available, also run the WorkOS-mode image smoke:
npm run smoke:container:workosIt builds the same image, passes WorkOS secrets by environment name so raw values are not echoed in command args, overrides only the temporary localhost callback, and verifies health, sign-in, protected API rejection, hidden local-dev routes, and invalid MCP-token rejection inside the container.
With production env available:
npm run db:postgres:init
npm run smoke:postgres
npm run smoke:postgres:runtime
npm run doctor:productionUse npm run doctor:production -- --help to inspect the required WorkOS and
hosted-release env without loading credentials first. The production doctor
loads the same .env* files as Next, rejects local-dev auth, checks cookie
strength, validates the callback path, and when
COVIBE_HOSTED_URL is set for a non-localhost deployment requires the WorkOS
redirect origin to match the hosted origin. For real hosted URLs it also
requires either the generated hosted tarball or COVIBE_COMPANION_INSTALL_COMMAND,
so the Agent Setup page cannot silently advertise an unpublished package.
Before a real HTTPS deploy is available, operators can rehearse the hosted canary against a locally running container:
npm run readiness:container:hostedThis command builds the image, boots a temporary WorkOS-mode container with a
matching localhost callback, then runs the same production doctor and hosted
canary checks used after deployment. It passes the explicit canary-only
--allow-local-rehearsal flag internally; the real handoff command rejects
localhost and non-HTTPS URLs.
To rehearse the exact public HTTPS handoff before a permanent domain exists,
install and authenticate the ngrok CLI, then run:
npm run readiness:hosted:https-rehearsalThat command builds the hosted image, opens a temporary public HTTPS tunnel to a
WorkOS-mode container, sets the matching callback URL, and runs the real
npm run readiness:hosted -- https://... command without the localhost
rehearsal flag. It proves the HTTPS canary contract, but it is not a durable
customer deployment or stable customer domain.
Before customer handoff, run the full customer rehearsal with Docker and WorkOS env available, then run the strict handoff wrapper against the deployed permanent HTTPS origin:
npm run readiness:customer
npm run readiness:handoff -- https://<host>The handoff wrapper rejects missing, localhost, HTTP, credential-bearing,
callback/path/query/hash URLs, private-network hosts, and temporary tunnel
domains before downstream checks. With a valid permanent origin it first runs a
fast /api/health, /api/mcp, and /downloads/co-vibe.tgz preflight so
DNS, TLS, WorkOS mode, MCP tool-count/surface, missing companion-package, broken
sign-in, public protected-API issues, unauthenticated token creation, or exposed
local-only routes, malformed MCP envelopes, or missing/invalid MCP-token
rejection, token-shaped response leaks, or a broken/non-Co-Vibe companion
tarball fail before the long local gate. It then runs doctor:production
against the same hosted origin before customer readiness and remote hosted
readiness.
Customer setup and operator details live in
hosting-handoff.md.