Getting started
Self-host Codexa
Run Codexa on your own infrastructure with your own AI keys. Stays free across the entire stack.
The hosted version of Codexa is convenient, but you may prefer to self-host for full control over data residency, custom prompts, or just to learn how the system works. This guide walks through every step.
What you'll need
- Node 20+ and Python 3.12+
- A free Supabase project (Auth + Postgres)
- A free Google Gemini API key, a free Groq API key, or both
- A GitHub account with a repo to test on
- Free-tier accounts on Vercel and Render (or your own VPS)
1. Clone the repo
bashgit clone https://github.com/techyMk/codexa-ai.git cd codexa
2. Set up Supabase
- Create a project at supabase.com
- In the SQL editor, run
supabase/migrations/001_init.sqlfollowed by002_review_detail_and_settings.sql - Authentication → Providers → enable GitHub (instructions below in the GitHub OAuth step)
- Settings → API: copy the project URL, publishable (anon) key, and secret (service role) key
3. Create a GitHub App
Visit GitHub → Settings → Developer settings → GitHub Apps → New GitHub App. Use these values:
Name: codexa-<your-username>
Homepage URL: https://your-frontend-domain
Webhook URL: https://your-backend-domain/webhooks/github
Webhook secret: (generate a random 32-byte hex string)
Permissions:
Pull requests: Read and write
Contents: Read-only
Checks: Read and write
Subscribe to events: Pull requestAfter creating, generate a private key (downloads a .pem file) and copy the App ID, Client ID, and a fresh client secret.
4. Create a GitHub OAuth App (for dashboard sign-in)
Separate from the GitHub App. Settings → Developer settings → OAuth Apps → New OAuth App.
Name: Codexa Login
Homepage: https://your-frontend-domain
Authorization callback URL: https://<your-supabase>.supabase.co/auth/v1/callback5. Configure environment variables
backend/.env
envGITHUB_APP_ID=... GITHUB_APP_CLIENT_ID=... GITHUB_APP_CLIENT_SECRET=... GITHUB_APP_PRIVATE_KEY_PATH=github-app.pem GITHUB_WEBHOOK_SECRET=... GEMINI_API_KEY=... GROQ_API_KEY=... SUPABASE_URL=https://....supabase.co SUPABASE_SERVICE_ROLE_KEY=... FRONTEND_URL=http://localhost:3000
Place the GitHub App private key file (the .pem you downloaded) at backend/github-app.pem.
frontend/.env.local
envNEXT_PUBLIC_SUPABASE_URL=https://....supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=... NEXT_PUBLIC_BACKEND_URL=http://localhost:8000 NEXT_PUBLIC_GITHUB_APP_NAME=codexa-yourname NEXT_PUBLIC_GITHUB_REPO_URL=https://github.com/yourname/codexa
6. Run locally
Two terminals:
bash# Backend cd backend python -m venv .venv .venv/Scripts/Activate.ps1 # Windows; on Linux/Mac: source .venv/bin/activate pip install -r requirements.txt uvicorn app.main:app --reload
bash# Frontend cd frontend npm install npm run dev
7. Tunnel the webhook (dev only)
GitHub needs to reach your local backend over HTTPS. Use ngrok or Cloudflare Tunnel:
bashngrok http 8000 # or cloudflared tunnel --url http://localhost:8000
Paste the public URL (with /webhooks/github appended) into your GitHub App's webhook URL field.
8. Deploy to production
Backend → Render
On Render, "New + Blueprint", point to your repo. Render reads render.yaml at the repo root and provisions the service. Set all the env vars from backend/.env in the Render dashboard. Paste the entire .pem file content (including BEGIN/END lines) into the GITHUB_APP_PRIVATE_KEY env var (Render handles multi-line values natively).
Frontend → Vercel
Import the repo on Vercel. Set Root Directory to frontend — this is critical. Add the env vars from frontend/.env.local, with NEXT_PUBLIC_BACKEND_URL pointed at the Render URL.
Update production URLs
- GitHub App → Webhook URL → your Render URL +
/webhooks/github - GitHub App → Homepage URL → your Vercel URL
- Supabase → Authentication → URL Configuration → Site URL + Redirect URLs
- Render env →
FRONTEND_URL= Vercel URL
Updating GitHub App permissions later
When you add features that need new GitHub permissions (e.g., switching from PR-comments-only to also posting status checks), you have to update the App definition AND get existing installations to accept the change. Two-step flow:
Step A — change the App permission
- Open
github.com/settings/apps/<your-app>/permissions - Adjust the permission you need (e.g., Checks → Read and write)
- Click Save changes
- GitHub shows a yellow box: "The following permissions have changed... These changes require approval from each installation."
Step B — accept on each installation
Existing installs keep using the OLD permissions until the install owner accepts the new ones. To accept:
- Click your avatar → Settings
- Left sidebar → Applications → Installed GitHub Apps
- Find your app → click Configure
- Yellow banner at top: Review permissions → Accept new permissions
403 Resource not accessible by integration in your backend logs. Always re-accept after permission changes.Common deployment errors
- Render returns 502 / takes 60s on first hit — free tier cold start. Normal. Upgrade to Starter ($7/mo) for always-on.
- Backend returns 401 on webhooks — webhook secret in GitHub doesn't match
GITHUB_WEBHOOK_SECRETin Render env. - JWT signing fails with "invalid key" — multi-line PEM got mangled. Re-paste the entire .pem content (including BEGIN/END lines) into Render's env editor.
- Dashboard shows 0 reviews but PR was reviewed —
NEXT_PUBLIC_BACKEND_URLwrong in Vercel env. Update + redeploy. - Status check never appears on PR — App permission update wasn't accepted on the install (see above).