| sidebar_position | 2 |
|---|---|
| title | OAuth Credentials |
CodeRunner does not store passwords. Sign-in is handled by Better Auth using GitHub and/or Google as OAuth providers. At least one provider must be configured for any non-demo deployment; without one, the login page has no working sign-in button.
You only need both if you want students to choose between GitHub and Google; configuring one is fine.
This page covers registering the OAuth apps and wiring the resulting
credentials into CodeRunner. The values you produce here are used the same way
whether you deploy locally or to Google Cloud;
only the URLs differ (http://localhost:4000 vs https://<your-domain>).
Every OAuth app registration asks for a homepage/origin URL and a redirect (callback) URL. For CodeRunner:
-
Homepage / origin = your
BETTER_AUTH_URL(the public base URL of the app). -
Callback / redirect URL =
BETTER_AUTH_URL+ a fixed per-provider path. Better Auth mounts its routes at/api/auth(confirmed inapps/control/src/auth/auth.ts), so the callbacks are:Provider Callback URL GitHub <BETTER_AUTH_URL>/api/auth/callback/githubGoogle <BETTER_AUTH_URL>/api/auth/callback/google
For local development that is http://localhost:4000/api/auth/callback/github
and .../google. For the cloud VM it is
https://<your-domain>/api/auth/callback/github and .../google.
In GitHub: Settings → Developer settings → OAuth Apps → New OAuth App.
- Application name: anything (e.g. "CodeRunner - Team 1234").
- Homepage URL: your
BETTER_AUTH_URL. - Authorization callback URL:
<BETTER_AUTH_URL>/api/auth/callback/github.
Save, then generate a client secret. You now have a Client ID and a Client Secret.
In the Google Cloud console:
- APIs & Services → OAuth consent screen: configure it once (External user type is fine for a team). Add your sign-in email as a test user while the app is in testing.
- APIs & Services → Credentials → Create credentials → OAuth client ID,
type Web application.
- Authorized JavaScript origins: your
BETTER_AUTH_URL. - Authorized redirect URIs:
<BETTER_AUTH_URL>/api/auth/callback/google.
- Authorized JavaScript origins: your
You now have a Client ID and a Client Secret.
CodeRunner reads these from environment variables (see
apps/control/src/config.ts and Configuration):
| Variable | Purpose |
|---|---|
BETTER_AUTH_URL |
Public base URL. Must match the homepage/callback URLs you registered. Defaults to http://localhost:4000. |
BETTER_AUTH_SECRET |
Secret used to sign sessions. Change this in production; the built-in default is a dev placeholder. Generate one with openssl rand -hex 32. |
GITHUB_CLIENT_ID |
GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET |
GitHub OAuth app client secret |
GOOGLE_CLIENT_ID |
Google OAuth client ID |
GOOGLE_CLIENT_SECRET |
Google OAuth client secret |
A provider only appears on the login page when both its ID and secret are set. Where these values live depends on the deployment:
- Local: in your
.envfile. See Local Deployment. - Cloud VM: in Google Secret Manager, materialized into the VM's
.envbyrender-env.shat boot. See Google Cloud Deployment.
OAuth establishes who a person is; CodeRunner separately controls whether they may sign in (the allowlist) and whether they are an admin (the role).
Set CODERUNNER_ADMIN_EMAIL (comma-separated for multiple people) alongside
your OAuth credentials before the first startup and the two steps below happen
automatically — no exec commands needed. At startup the control plane adds
each listed email to the allowlist, and on first OAuth sign-in the account is
created with the admin role. An account that already exists with that email is
promoted to admin at the next startup, so it also rescues a coach who signed in
before the env var was set.
CODERUNNER_ADMIN_EMAIL=coach@frcteam.org,assistant@frcteam.orgThis is the recommended way to reach the admin panel on a fresh deployment. The manual commands below are still useful for allowlisting students and for changing roles later.
:::note[Running these commands]
On a containerized deployment (the default) the allowlist and users
commands run inside the control container via the coderunner CLI:
docker compose exec control coderunner allowlist add coach@frcteam.org
docker compose exec control coderunner users promote coach@frcteam.orgUse docker compose run --rm control <subcommand> instead while the control
plane is stopped. On the Google Cloud VM the compose project lives in
/opt/coderunner and needs sudo (cd /opt/coderunner && sudo docker compose exec -T control …). The bun run … short forms shown below are equivalent
and apply to a from-source host checkout with Bun.
:::
The allowlist gates every OAuth login. Until an email or domain is added, sign-in is blocked for everyone. Add an individual email or a whole domain:
bun run allowlist:add coach@frcteam.org
# or allow an entire domain:
bun run allowlist:add frcteam.orgOther allowlist commands: bun run allowlist:list, bun run allowlist:remove.
Every user, including the first one, signs in as a regular user. After the first coach has signed in once (so their user row exists), promote them to admin:
bun run users:promote coach@frcteam.orgThe reverse is bun run users:demote, and bun run users:list shows current
roles. On the cloud VM, run coderunner users promote over IAP SSH; see the
Google Cloud Deployment "Become the first admin" step.
Admins also get a break-glass option: setting the
ADMIN_TOKENenv var lets you call the/admin/*API with a bearer token even before any user is promoted. See Configuration.