# Environment variables (/environment-variables)



## What Crucible manages [#what-crucible-manages]

Crucible generates or resolves the platform values required by Auth, model access, databases, workers, and managed integrations. Add only the application-specific values; Crucible assembles the right configuration for each workspace, deployment, and local machine before it starts.

* **Project variables**: Shared defaults in the project's **Variables** tab. Every workspace, deployment, and local setup inherits them.
* **Deployment variables**: Set in a deployment's **Variables** tab. They override project defaults for that deployment only.
* **Managed variables**: Generated by Crucible and its integrations. They appear alongside your variables as read-only rows.

```mermaid
flowchart TD
  P[Project variables] -->|inherited| W[Workspace]
  P -->|inherited| L[Local setup]
  P -->|inherited| O[Deployment variables]
  O -->|overrides win| D[Deployment]
```

<Accordions>
  <Accordion title="Under the hood: the variables Crucible generates">
    * `AUTH_SERVICE_API_KEY` and `AUTH_SERVICE_API_URL` let the backend call the right Auth Service for its environment.
    * `LLM_GATEWAY_API_KEY` and `LLM_GATEWAY_ENDPOINT` let the project call models through the gateway instead of storing provider keys.
    * `TEMPORAL_*` variables wire up worker execution. They exist on full deployments only, since they back durable cloud resources.
    * `DATABASE_URL` and `REDIS_PASSWORD` are infrastructure secrets that the full deployment's Terraform generates; `REDIS_PASSWORD` exists only when agents are enabled.
    * `VITE_*` values are frontend build-time config, not secrets. They tell the browser which API and auth project to talk to.
    * `ADMIN_EMAIL_ALLOWLIST` gives new workspaces and deployments a snapshot of the project's admins at creation. Later membership changes do not update existing environments, and the value is empty when there are no admins.
    * Integration keys are minted per target: each deployment, workspace, and local setup gets its own credentials.
  </Accordion>
</Accordions>

## Rules that matter [#rules-that-matter]

* **[Secrets stay on the backend](/environment-variables/types/)**: Frontend keys must start with `VITE_`, and only backend values can be secret. Provider keys stay server-side or behind managed integrations.
* **[Changing a full deployment is a release](/deployments/full-deployment/)**: Editing a full deployment's variables starts an update that applies infrastructure and, for frontend values, rebuilds the frontend. Treat it like shipping a change.
* **[Local development is already wired](/work-locally/)**: Use **Work locally** on the project overview to copy the values resolved for you instead of rebuilding the environment by hand.
* **[Prefer managed keys](/llm-gateway/)**: With the LLM Gateway and other managed integrations, you never handle provider credentials at all.

<Accordions>
  <Accordion title="Under the hood: how changes apply and local values resolve">
    A full deployment variable change runs as a workflow:

    1. Saving records an `EnvVarUpdate` and starts `UpdateEnvVarsWorkflow` for that deployment. The change shows as **Pending** until it applies.
    2. Backend, frontend, and secret changes are written to the environment's `terraform.auto.tfvars`, then an infrastructure release applies them. On Kubernetes deployments, the delivery pipeline rebuilds the frontend when `VITE_*` values changed, since they are baked into the bundle.
    3. New secret values become new versions in the provider's secret store, and older versions are disabled.
    4. Crucible pulls the applied values back so the **Variables** tab matches the running deployment.

    Lite deployment and workspace changes update the managed runtime directly. Local values resolve from project variables, then managed integration values, then fixed local-runtime defaults. Existing personal integration secrets are reused instead of minting new upstream keys.
  </Accordion>
</Accordions>
