Configuration
Every setting a Docker copy reads from .env, and what the important ones do.
A Docker copy reads its settings from .env next to compose.yaml (copied from .env.example). On Coolify and Dokploy
they go in the deployment's environment instead. After a change, run docker compose up -d (or Redeploy): compose makes
new containers, and the setup step pushes the backend's settings to Convex again.
Every setting
Version
CAREERBOT_VERSIONWhich CareerBot release to run. Unset: the release this compose.yaml came with. A version such as 0.8.0 stays on it until you change it here; `latest` moves to the newest release on each `docker compose pull`. Before changing it, back up and read the release notes: https://careerbot.dev/changelog
Your site
SITE_URLhttp://localhost:3000Where people open CareerBot, as the browser sees it. On your own computer: http://localhost:3000. On a server with a domain: its https address (https://careerbot.example.com), with your proxy or tunnel sending it to WEB_PORT.
Convex: pick one
NEXT_PUBLIC_CONVEX_URLhttps://your-deployment.convex.cloudA) Convex's cloud (free plan). Create a project at https://dashboard.convex.dev, then: NEXT_PUBLIC_CONVEX_URL: Settings > URL & Deploy Key, the deployment URL (https://….convex.cloud) CONVEX_DEPLOY_KEY: Settings > URL & Deploy Key, Generate Production Deploy Key CONVEX_SITE_ORIGIN isn't needed: Google and GitHub send people back to https://….convex.site. Uncomment the two lines below and comment out or delete B's four lines.CONVEX_DEPLOY_KEYprod:your-deployment|…A) Convex's cloud (free plan). Create a project at https://dashboard.convex.dev, then: NEXT_PUBLIC_CONVEX_URL: Settings > URL & Deploy Key, the deployment URL (https://….convex.cloud) CONVEX_DEPLOY_KEY: Settings > URL & Deploy Key, Generate Production Deploy Key CONVEX_SITE_ORIGIN isn't needed: Google and GitHub send people back to https://….convex.site. Uncomment the two lines below and comment out or delete B's four lines.COMPOSE_PROFILESself-hostedB) Self-hosted Convex, run by this compose file on this computer. Its data stays in the convex-data Docker volume. On a server with a domain, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN are two https addresses of their own (https://convex.example.com, https://convex-site.example.com) that your proxy sends to CONVEX_PORT and CONVEX_SITE_PORT. CONVEX_SELF_HOSTED_URL stays as it is: the setup step reaches Convex inside compose.NEXT_PUBLIC_CONVEX_URLhttp://localhost:3210B) Self-hosted Convex, run by this compose file on this computer. Its data stays in the convex-data Docker volume. On a server with a domain, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN are two https addresses of their own (https://convex.example.com, https://convex-site.example.com) that your proxy sends to CONVEX_PORT and CONVEX_SITE_PORT. CONVEX_SELF_HOSTED_URL stays as it is: the setup step reaches Convex inside compose.CONVEX_SITE_ORIGINhttp://localhost:3211B) Self-hosted Convex, run by this compose file on this computer. Its data stays in the convex-data Docker volume. On a server with a domain, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN are two https addresses of their own (https://convex.example.com, https://convex-site.example.com) that your proxy sends to CONVEX_PORT and CONVEX_SITE_PORT. CONVEX_SELF_HOSTED_URL stays as it is: the setup step reaches Convex inside compose.CONVEX_SELF_HOSTED_URLhttp://convex-backend:3210B) Self-hosted Convex, run by this compose file on this computer. Its data stays in the convex-data Docker volume. On a server with a domain, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN are two https addresses of their own (https://convex.example.com, https://convex-site.example.com) that your proxy sends to CONVEX_PORT and CONVEX_SITE_PORT. CONVEX_SELF_HOSTED_URL stays as it is: the setup step reaches Convex inside compose.
Signing in
SIGNUP_ALLOWLISTPeople sign in with a username and password: the owner's account is made with the setup code, and the owner adds everyone else in Settings, Account. Google and GitHub are optional; the sign-in screen offers them once they're set. Who may sign in with Google or GitHub: their emails, comma-separated. Empty: nobody (password accounts don't need it). Changing the list takes effect after `docker compose up -d`; to empty it again, delete SIGNUP_ALLOWLIST in the Convex dashboard's environment variables (an empty value here leaves the one there as it is).AUTH_GOOGLE_IDEach of Google and GitHub needs an OAuth app whose callback URL is your Convex HTTP actions URL plus /api/auth/callback/google (or /github): self-hosted on this computer: http://localhost:3211/api/auth/callback/google self-hosted on a server: CONVEX_SITE_ORIGIN/api/auth/callback/google (https://convex-site.example.com/…) Convex's cloud: https://your-deployment.convex.site/api/auth/callback/google Google: https://console.cloud.google.com/apis/credentials (OAuth client ID, Web application) GitHub: https://github.com/settings/developers (New OAuth App; its homepage URL is SITE_URL)AUTH_GOOGLE_SECRETEach of Google and GitHub needs an OAuth app whose callback URL is your Convex HTTP actions URL plus /api/auth/callback/google (or /github): self-hosted on this computer: http://localhost:3211/api/auth/callback/google self-hosted on a server: CONVEX_SITE_ORIGIN/api/auth/callback/google (https://convex-site.example.com/…) Convex's cloud: https://your-deployment.convex.site/api/auth/callback/google Google: https://console.cloud.google.com/apis/credentials (OAuth client ID, Web application) GitHub: https://github.com/settings/developers (New OAuth App; its homepage URL is SITE_URL)AUTH_GITHUB_IDEach of Google and GitHub needs an OAuth app whose callback URL is your Convex HTTP actions URL plus /api/auth/callback/google (or /github): self-hosted on this computer: http://localhost:3211/api/auth/callback/google self-hosted on a server: CONVEX_SITE_ORIGIN/api/auth/callback/google (https://convex-site.example.com/…) Convex's cloud: https://your-deployment.convex.site/api/auth/callback/google Google: https://console.cloud.google.com/apis/credentials (OAuth client ID, Web application) GitHub: https://github.com/settings/developers (New OAuth App; its homepage URL is SITE_URL)AUTH_GITHUB_SECRETEach of Google and GitHub needs an OAuth app whose callback URL is your Convex HTTP actions URL plus /api/auth/callback/google (or /github): self-hosted on this computer: http://localhost:3211/api/auth/callback/google self-hosted on a server: CONVEX_SITE_ORIGIN/api/auth/callback/google (https://convex-site.example.com/…) Convex's cloud: https://your-deployment.convex.site/api/auth/callback/google Google: https://console.cloud.google.com/apis/credentials (OAuth client ID, Web application) GitHub: https://github.com/settings/developers (New OAuth App; its homepage URL is SITE_URL)
Made for you the first time
JWT_PRIVATE_KEYLeft empty, the first `docker compose up` makes these and keeps them in your Convex deployment's settings. Set them only to bring keys from another copy. MASTER_KEY_V1 encrypts the API keys people save in CareerBot; losing it means entering those again.JWKSLeft empty, the first `docker compose up` makes these and keeps them in your Convex deployment's settings. Set them only to bring keys from another copy. MASTER_KEY_V1 encrypts the API keys people save in CareerBot; losing it means entering those again.MASTER_KEY_V1Left empty, the first `docker compose up` makes these and keeps them in your Convex deployment's settings. Set them only to bring keys from another copy. MASTER_KEY_V1 encrypts the API keys people save in CareerBot; losing it means entering those again.
Optional
GOOGLE_PICKER_KEYChoosing a Google Drive folder in Settings (a browser API key for Google's Picker).LIQUIDAI_API_KEYLiquid AI's model, for an experiment in sorting roles.UPDATE_CHECKoffOnce a day this copy asks https://careerbot.dev/releases.json whether there's a newer version, and its owner sees it in Settings, Updates. Nothing about you or this copy is sent, but like any web request it shows careerbot.dev this server's IP address. off: never ask (the owner can also turn it off there).WEB_PORT3000Ports on this computer, if the defaults are taken. Change SITE_URL, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN to match when they're localhost addresses (behind a domain they stay as they are). Dokploy's own dashboard is on 3000: there, set WEB_PORT=3001 or another free port.CONVEX_PORT3210Ports on this computer, if the defaults are taken. Change SITE_URL, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN to match when they're localhost addresses (behind a domain they stay as they are). Dokploy's own dashboard is on 3000: there, set WEB_PORT=3001 or another free port.CONVEX_SITE_PORT3211Ports on this computer, if the defaults are taken. Change SITE_URL, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN to match when they're localhost addresses (behind a domain they stay as they are). Dokploy's own dashboard is on 3000: there, set WEB_PORT=3001 or another free port.CONVEX_DASHBOARD_PORT6791Ports on this computer, if the defaults are taken. Change SITE_URL, NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN to match when they're localhost addresses (behind a domain they stay as they are). Dokploy's own dashboard is on 3000: there, set WEB_PORT=3001 or another free port.BIND_ADDRESS127.0.0.1The address those ports are published on. 127.0.0.1 (the default): this machine only; Coolify's and Dokploy's proxies don't need them, and on a server they'd skip the proxy and its HTTPS (Docker's ports also go around ufw). Set 0.0.0.0 only to reach the ports from other machines without a proxy, never on a server facing the internet.
The ones that matter most
SITE_URL
Where people open CareerBot, as the browser sees it: http://localhost:3000 on your own computer,
https://careerbot.example.com on a server. It's fixed into the web container when it starts (the image is built with a
stand-in that the start script swaps), and sign-in sends people back to it. A wrong SITE_URL breaks Google and GitHub
sign-in.
NEXT_PUBLIC_CONVEX_URL and CONVEX_SITE_ORIGIN
Where the browser reaches Convex: its API, and (self-hosted only) its HTTP actions, where Google and GitHub send people
back after signing in. Both must be addresses the browser can open, never convex-backend. On a server, two https
hostnames of their own. Compose stops with "Set NEXT_PUBLIC_CONVEX_URL in .env" when it's missing.
Neither may contain |, \ or &.
COMPOSE_PROFILES
self-hosted runs Convex in the same compose file. Leave it out for Convex's cloud. See Convex.
CONVEX_DEPLOY_KEY, CONVEX_SELF_HOSTED_URL
Which Convex the setup step deploys to. A deploy key means Convex's cloud; otherwise CONVEX_SELF_HOSTED_URL
(http://convex-backend:3210) means self-hosted. With neither, the setup step stops: "Set CONVEX_DEPLOY_KEY (Convex's
cloud) or CONVEX_SELF_HOSTED_URL (self-hosted Convex); see .env.example."
SIGNUP_ALLOWLIST
Who may sign in with Google or GitHub: emails, comma-separated. Empty: nobody. Password accounts don't need it. An empty value doesn't clear the list on the deployment; delete it in Convex's dashboard. See Sign-in and who can join.
AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET, AUTH_GITHUB_ID, AUTH_GITHUB_SECRET, GOOGLE_PICKER_KEY
Google and GitHub sign-in, Google Drive, and Drive's folder picker. Each sign-in button shows once both of its keys are set. See Keys and accounts.
JWT_PRIVATE_KEY, JWKS, MASTER_KEY_V1
Made by the first run and kept in the Convex deployment. Set them only to bring keys from another copy.
MASTER_KEY_V1 encrypts the API keys people save in CareerBot; losing it means entering those again.
WEB_PORT, CONVEX_PORT, CONVEX_SITE_PORT, CONVEX_DASHBOARD_PORT
The ports compose publishes on the machine: 3000, 3210, 3211 and 6791. Change one when it's taken, and the localhost
address that uses it. On Dokploy, set WEB_PORT=3001 (Dokploy's dashboard holds 3000). See
Your own computer.
BIND_ADDRESS
The address compose publishes those ports on. Default 127.0.0.1: they open from this machine only, and a proxy in
Docker (Coolify, Dokploy) doesn't need them. 0.0.0.0 opens them to other machines too; use it only on a private
network without a proxy, never on a server facing the internet (Firewall).
CAREERBOT_VERSION
Which CareerBot release the web app and the setup step run, such as 0.8.0. Unset, the release compose.yaml came
with; latest, the newest release each time docker compose pull runs. See
Updates, backups, export.
CONVEX_RELEASE
The Convex backend and dashboard image tag for self-hosted Convex. Unset, compose.yaml's pinned release. See
Upgrading self-hosted Convex.
Settings that aren't in .env
CAREERBOT_MODE=self-hosted: compose sets it on the Convex deployment, and the Docker image is built with it. It's what makes a copy yours: the app at/, username and password sign-in, the owner adds people. Only the Cloudflare way sets it by hand. Without it on the deployment, the sign-in screen says "This copy’s Convex isn’t set up for username and password sign-in: set CAREERBOT_MODE=self-hosted in its environment."AUTH_REDIRECT_ORIGINS: more addresses, comma-separated, that sign-in may send people back to besidesSITE_URL.scripts/sync-convex-env.shsets it when it's in the environment; compose doesn't pass it, so set it withnpx convex env setor in Convex's dashboard if you need it.LIQUIDAI_API_KEY: in.env.exampleunder Optional, for an experiment in sorting roles. You don't need it.UPDATE_CHECK=off: in.env.exampleunder Optional. Once a day a self-hosted copy askshttps://careerbot.dev/releases.jsonwhether there's a newer version, and its owner sees it in Settings, Updates. The request carries no account, personal data or anything about the copy or the people on it, but like any web request it shows careerbot.dev the IP address of the server the copy runs on.offstops it; the owner can also turn it off with Check for updates in Settings, Updates.