Skip to content

Cloud Run Deployment

Deploy Beyond Retrieval v2 as two serverless containers on Google Cloud Run. The backend (FastAPI) and frontend (React + nginx) scale independently, connect to your Supabase cloud project, and cost nothing when idle.


Architecture

                     Internet
                        |
            +-----------+-----------+
            |                       |
   Cloud Run (frontend)    Cloud Run (backend)
   React + nginx            FastAPI
   *.run.app                *.run.app
            |                       |
            |     nginx proxies     |
            |     /api/* ---------->|
            |                       |
            |               +-------+-------+
            |               |  Supabase.co  |
            |               |  (Database,   |
            |               |   Auth,       |
            |               |   Storage)    |
            +               +---------------+
  • Frontend serves the React SPA and proxies /api/* requests to the backend
  • Backend handles all API logic, connects to Supabase for data/auth/storage
  • Supabase is fully managed — no database containers to run
  • Both services auto-scale from 0 to N instances based on traffic

Prerequisites

Before you start, you need:

Requirement How to get it
Google Cloud account cloud.google.com (free tier available)
gcloud CLI Install guide
Docker Docker Desktop or Docker Engine
Supabase project supabase.com (free tier works)
OpenRouter API key openrouter.ai (for LLM inference)

Step 1: Set Up Your Supabase Project

If you're cloning this repo for the first time, you need your own Supabase project with the database schema.

Create a Supabase project

  1. Go to supabase.com/dashboard
  2. Click New Project
  3. Choose a name, region, and password
  4. Wait for provisioning (~2 minutes)

Apply the database schema

  1. Open SQL Editor in your Supabase dashboard
  2. Copy the contents of migration.sql from the repo root
  3. Paste and click Run

This creates all tables, functions, extensions (vector, pg_trgm, pg_net), and RLS policies.

Grab your credentials

From your Supabase project dashboard (Settings > API):

  • Project URL — e.g. https://abcdefgh.supabase.co
  • Service Role Key — the service_role key (NOT the anon key)
  • Anon Key — needed if you want frontend auth

Step 2: Set Environment Variables

Export the required variables in your terminal:

# Required — your GCP project
export GCP_PROJECT_ID=my-gcp-project-id

# Required — your Supabase credentials
export SUPABASE_URL=https://your-project.supabase.co
export SUPABASE_SECRET_KEY=eyJhbGciOiJIUzI1NiIs...your-service-role-key

# Required — LLM provider
export OPENROUTER_API_KEY=sk-or-v1-your-openrouter-key

Optional variables

# GCP region (default: europe-west3)
export GCP_REGION=us-central1

# Auth bypass (default: false). Set true for testing without auth
export BYPASS_AUTH=true

# Supabase auth for the frontend (needed if BYPASS_AUTH=false)
export VITE_SUPABASE_URL=https://your-project.supabase.co
export VITE_SUPABASE_ANON_KEY=your-anon-key

# OCR support (optional)
export MISTRAL_API_KEY=your-mistral-key

# Reranking (optional)
export COHERE_API_KEY=your-cohere-key

Step 3: One-Time GCP Setup

Run the setup command to enable APIs and create the container registry:

cd beyond-retrieval-pythonv
./cloudrun-deploy.sh setup

This does three things:

  1. Enables Cloud Run, Artifact Registry, and Cloud Build APIs
  2. Creates a Docker repository in Artifact Registry
  3. Configures Docker authentication for pushing images

You only need to run this once per GCP project.


Step 4: Deploy

./cloudrun-deploy.sh deploy

This builds and deploys both services:

  1. Backend — builds backend/Dockerfile.cloudrun, pushes to Artifact Registry, deploys to Cloud Run
  2. Frontend — builds frontend/Dockerfile.cloudrun (multi-stage: React build + nginx), pushes, deploys
  3. CORS — automatically restricts the backend to only accept requests from the frontend URL

When done, you'll see:

[OK]  Deployment complete!
  Backend:  https://beyond-retrieval-backend-xxxxx-ey.a.run.app
  Frontend: https://beyond-retrieval-frontend-xxxxx-ey.a.run.app

Verify: curl https://beyond-retrieval-backend-xxxxx-ey.a.run.app/api/health

Deploy individual services

./cloudrun-deploy.sh deploy-backend   # Backend only
./cloudrun-deploy.sh deploy-frontend  # Frontend only

Step 5: Verify

# Health check
curl $(cat .backend-url)/api/health

# Tail logs
./cloudrun-deploy.sh logs backend
./cloudrun-deploy.sh logs frontend

Open the frontend URL in your browser. Create a notebook, upload a document, and test the RAG chat.


What Someone Cloning This Repo Needs to Change

Nothing in the code. The entire project is configured via environment variables. Here is exactly what a new user needs:

Must have (3 things)

What Where to get it Env var
Google Cloud project console.cloud.google.com GCP_PROJECT_ID
Supabase project supabase.com — run migration.sql SUPABASE_URL + SUPABASE_SECRET_KEY
OpenRouter API key openrouter.ai/keys OPENROUTER_API_KEY

Nice to have

What Purpose Env var
GCP region Deploy closer to your users GCP_REGION
Supabase anon key Frontend auth (email/password login) VITE_SUPABASE_URL + VITE_SUPABASE_ANON_KEY
Mistral API key PDF/document OCR parsing MISTRAL_API_KEY
Cohere API key Search result reranking COHERE_API_KEY

Quick start for a new clone

# 1. Clone the repo
git clone https://github.com/your-org/beyond-retrieval.git
cd beyond-retrieval/beyond-retrieval-pythonv

# 2. Set your credentials
export GCP_PROJECT_ID=my-project
export SUPABASE_URL=https://my-project.supabase.co
export SUPABASE_SECRET_KEY=eyJhbG...
export OPENROUTER_API_KEY=sk-or-v1-...
export BYPASS_AUTH=true

# 3. One-time setup
./cloudrun-deploy.sh setup

# 4. Deploy
./cloudrun-deploy.sh deploy

That's it. Zero code changes needed.


Cloud Run Service Specs

The deploy script configures these defaults:

Setting Backend Frontend
Memory 2 GiB 256 MiB
CPU 2 1
Min instances 0 (scales to zero) 0
Max instances 10 5
Concurrency 80 req/instance 250 req/instance
Timeout 300s 300s
Port 8080 8080

Both services scale to zero when idle, so you only pay for actual usage.


CI/CD with Cloud Build

Generate a cloudbuild.yaml for automated deployments on push:

./cloudrun-deploy.sh cloudbuild

This creates a Cloud Build config that:

  1. Builds backend and frontend images (tagged with commit SHA + latest)
  2. Pushes both to Artifact Registry
  3. Deploys both to Cloud Run

Set up a Cloud Build trigger in the GCP Console to run on push to main.

Secret management

Store SUPABASE_SECRET_KEY and OPENROUTER_API_KEY in Secret Manager and reference them in your Cloud Build config rather than hardcoding.


Custom Domain

Cloud Run services get a *.run.app URL by default. To use your own domain:

  1. Go to Cloud Run > your service > Integrations (or Domain Mappings)
  2. Click Add Custom Domain
  3. Verify domain ownership
  4. Add the DNS records shown (CNAME or A records)
  5. Wait for SSL provisioning (~15 minutes)

You can map separate domains for frontend and backend, or put both behind a load balancer.


Comparison: Cloud Run vs. Docker Compose (VPS)

Cloud Run Docker Compose (VPS)
Infrastructure Fully managed, serverless You manage the server
Scaling Auto (0 to N instances) Manual (fixed resources)
Cost Pay per request (free tier available) Fixed monthly VPS cost
HTTPS Automatic on *.run.app Caddy auto-HTTPS (needs domain)
Database Supabase cloud only Cloud or self-hosted Supabase
Ollama (local LLM) Not available Available with GPU support
Docling (document parser) Not available Available as sidecar
Cold starts ~2-5s on first request None (always running)
Best for Production SaaS, low/variable traffic Self-hosted, GPU workloads, privacy

Troubleshooting

Problem Fix
gcloud: command not found Install the gcloud CLI
GCP_PROJECT_ID: unbound variable export GCP_PROJECT_ID=your-project-id
Backend deploy fails with auth error Run gcloud auth login and gcloud auth configure-docker
Frontend shows "Failed to fetch" Check that BACKEND_URL is set correctly and backend is deployed
CORS errors in browser console Redeploy frontend to update CORS: ./cloudrun-deploy.sh deploy-frontend
Health check returns error Check env vars: gcloud run services describe beyond-retrieval-backend --region your-region
Cold start timeouts Increase min instances: gcloud run services update beyond-retrieval-backend --min-instances 1
migration.sql fails Check Supabase SQL Editor for error details — likely a missing extension

CLI Reference

./cloudrun-deploy.sh setup              # One-time: enable APIs, create registry
./cloudrun-deploy.sh deploy             # Build + deploy both services
./cloudrun-deploy.sh deploy-backend     # Deploy backend only
./cloudrun-deploy.sh deploy-frontend    # Deploy frontend only
./cloudrun-deploy.sh logs backend       # Tail backend logs
./cloudrun-deploy.sh logs frontend      # Tail frontend logs
./cloudrun-deploy.sh cloudbuild         # Generate cloudbuild.yaml for CI/CD