> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crewship.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment Variables

> Complete reference for all environment variables that configure the Crewship server, containers, auth, and integrations.

# Environment Variables

All Crewship configuration can be set via environment variables. These override values from the YAML config file. The mapping is defined in `applyEnvOverrides` in `internal/config/config.go`.

<Tip>
  As of PR #446, **no env vars are required for first boot** — secrets are auto-generated and persisted. Set variables here only to override a default or hand a secret to an external manager. Jump to a group: [Server](#server) · [Container](#container) · [Storage](#storage) · [Auth](#authentication) · [Encryption](#encryption) · [Keeper](#keeper-ai-security-gatekeeper) · [CLI client](#cli-client) · [Installer](#installer).
</Tip>

## Server

| Variable        | Default   | Description           |
| --------------- | --------- | --------------------- |
| `CREWSHIP_HOST` | `0.0.0.0` | Server listen address |
| `CREWSHIP_PORT` | `8080`    | Server listen port    |

## IPC

| Variable               | Default              | Description                       |
| ---------------------- | -------------------- | --------------------------------- |
| `CREWSHIP_SOCKET_PATH` | `/tmp/crewship.sock` | Unix socket path for internal IPC |

## Container

| Variable                      | Default                | Description                                                                                                                                                                |
| ----------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_CONTAINER_PROVIDER` | `docker`               | Container provider: `docker`, `apple`, `auto` (Kubernetes provider on the v0.2 roadmap)                                                                                    |
| `CREWSHIP_CONTAINER_NETWORK`  | `crewship-agents`      | Docker bridge network name                                                                                                                                                 |
| `CREWSHIP_CONTAINER_PREFIX`   | (empty)                | Container name prefix for multi-instance isolation                                                                                                                         |
| `CREWSHIP_RUNTIME_IMAGE`      | `debian:bookworm-slim` | Default agent runtime image for crews without an explicit `runtime_image`. Any glibc-based Linux image works — Crewship bind-mounts the sidecar and entrypoint at runtime. |
| `CREWSHIP_SIDECAR_ENABLED`    | `false`                | Enable sidecar proxy (`true` or `1`)                                                                                                                                       |
| `CREWSHIP_SIDECAR_PATH`       | autodetected           | Absolute host path to the `crewship-sidecar` Go binary. See [Devcontainers reference](/configuration/devcontainers#environment-variables) for autodetect order.            |
| `CREWSHIP_ENTRYPOINT_PATH`    | autodetected           | Absolute host path to `entrypoint.sh`.                                                                                                                                     |
| `CREWSHIP_SKIP_SIDECAR`       | (unset)                | Set to `1` to bypass fail-fast autodetect (tests only — never set in production).                                                                                          |

<Note>
  `CREWSHIP_CONTAINER_PREFIX` is essential for multi-instance deployments. Without it, multiple Crewship instances will create containers with colliding names like `crewship-team-engineering`.
</Note>

## Storage

| Variable                     | Default             | Description                                                                                                                                                                               |
| ---------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_DATA_DIR`          | `~/.crewship`       | Root directory for `crewship.db`, output, chats, logs, skills, and workspace memory. Resolved by `database.DefaultDataDir` — every admin / backup / doctor / start path flows through it. |
| `DATABASE_URL`               | (unset)             | Direct DSN override for `crewship admin` only. Bypasses `CREWSHIP_DATA_DIR` resolution. Use when running admin commands against a SQLite file outside the standard data-dir tree.         |
| `CREWSHIP_STORAGE_PROVIDER`  | `localfs`           | Storage backend: `localfs` or `s3`                                                                                                                                                        |
| `CREWSHIP_STORAGE_BASE_PATH` | `/var/lib/crewship` | Base path for local file storage                                                                                                                                                          |
| `CREWSHIP_LOG_PATH`          | `/var/log/crewship` | Path for log files                                                                                                                                                                        |

## State

| Variable                  | Default                      | Description                                         |
| ------------------------- | ---------------------------- | --------------------------------------------------- |
| `CREWSHIP_STATE_PROVIDER` | `bbolt`                      | State store: `bbolt` (postgres on the v0.2 roadmap) |
| `CREWSHIP_BOLT_PATH`      | `/var/lib/crewship/state.db` | BoltDB file path                                    |

## Public-facing URL

| Variable              | Default | Description                                                                                                                                                                                                                                                                        |
| --------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_PUBLIC_URL` | (unset) | Externally-reachable base URL of the Crewship server. Required for password-recovery emails and for `/expose-port` (port-exposed agent containers). Without it the recovery email link is degraded and `/expose-port` returns `503` with a `CREWSHIP_PUBLIC_URL not set` log line. |

## Origin enforcement (CORS / EnforceOrigin)

| Variable                   | Default                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| -------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_ALLOWED_ORIGINS` | (unset — same-origin only) | Comma-separated allowlist of cross-origin `scheme://host[:port]` values that may issue state-changing requests (POST/PUT/PATCH/DELETE). Parsed by `internal/api/origin_check.go`; matched as **exact host equality** after `url.Parse` (no suffix wildcards, no IDN tricks — those previously enabled bypasses). Required whenever the frontend is served from a different origin than the daemon (cross-origin Playwright E2E, separate `:3001` dev frontend on `nuke`-reset envs, reverse-proxy host with custom domain). `dev.sh` writes this automatically alongside `NEXTAUTH_URL`/`CREWSHIP_PORT` so the value survives `./dev.sh nuke`. Example: `CREWSHIP_ALLOWED_ORIGINS=https://app.crewship.io,https://staging.crewship.io`. |

## Rate limiting & proxy trust

| Variable                       | Default                                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                             |
| ------------------------------ | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_TRUSTED_PROXY_CIDRS` | (unset — only loopback `127.0.0.0/8` and `::1/128` trusted) | Comma-separated list of CIDR ranges whose `X-Forwarded-For` header the rate limiter and client-IP extractor will trust. Set this to the address(es) of your reverse proxy (nginx/Caddy/load balancer) so per-IP throttles see the real client IP. Leaving it unset means any non-loopback client presenting a forged `X-Forwarded-For` is ignored (the header is only honoured from trusted hops). Read by `internal/api/ratelimit.go`. |
| `CREWSHIP_ENV`                 | (unset — treated as non-prod)                               | Deployment environment label. When set to `prod` or `production` (case-insensitive), the server **refuses to start** if rate limiting has been disabled, and tightens WebSocket origin enforcement. Any other value (or unset) is treated as non-production. Read by `internal/api/ratelimit.go` and `internal/ws/hub.go`.                                                                                                              |

## Metrics

| Variable                 | Default                                        | Description                                                                                                                                                                                                                                                                |
| ------------------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_METRICS_TOKEN` | (unset — metrics only reachable from loopback) | Bearer token gating non-loopback access to the Prometheus `/metrics` endpoint. Loopback peers are always allowed; remote scrapers must send `Authorization: Bearer <token>`. When unset, non-loopback requests are rejected outright. Read by `internal/server/routes.go`. |

## Webhooks / hooks (SSRF guard)

| Variable                       | Default                                | Description                                                                                                                                                                                                                                                                                                                                                                |
| ------------------------------ | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_HOOKS_ALLOW_PRIVATE` | (unset — private destinations blocked) | Set to `1`/`true`/`yes`/`on` to allow hook/webhook handlers to dial loopback and RFC1918 private addresses. Off by default so a misconfigured hook cannot reach localhost services or internal LAN hosts. Link-local (cloud metadata IMDS `169.254.169.254`), multicast, and unspecified addresses stay blocked regardless of this flag. Read by `internal/hooks/http.go`. |

## Profiling & observability

These are off by default and intended for operators debugging performance.

| Variable                      | Default                           | Description                                                                                                                                                                                                                                   |
| ----------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_PPROF_ADDR`         | (unset — pprof disabled)          | Bind address for the Go `net/http/pprof` server (recommended: `127.0.0.1:6060`, loopback only). Exposing pprof publicly is an info-leak and DoS vector, so it stays off unless explicitly set. Read by `internal/server/server.go`.           |
| `CREWSHIP_PYROSCOPE_URL`      | (unset — push profiling disabled) | Pyroscope server URL. When set, the binary continuously pushes CPU/heap/goroutine/alloc profiles. Read by `internal/server/server.go`.                                                                                                        |
| `CREWSHIP_PYROSCOPE_TAG_SLOT` | (hostname)                        | Value for the `slot` tag attached to Pyroscope profiles, used to filter the Grafana flame-graph per dev slot/instance. Falls back to the machine hostname when unset. Read by `internal/telemetry/pyroscope.go`.                              |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | (unset — noop tracer)             | Standard OpenTelemetry OTLP HTTP endpoint for GenAI traces. When unset, tracing silently degrades to a no-op tracer so local dev runs without an observability stack. Read by `internal/server/server.go` / `internal/telemetry/provider.go`. |
| `CREWSHIP_SERVICE_NAME`       | `crewshipd`                       | Overrides the OpenTelemetry `service.name` resource attribute. Set per binary (e.g. `crewship-sidecar`) or per tenant to differentiate traces. Read by `internal/telemetry/service_name.go`.                                                  |

## Crash reporting (Sentry)

| Variable              | Default                                  | Description                                                                                                                                                                       |
| --------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_SENTRY_DSN` | (vendor default, baked-in at build time) | Operator override for the crash-reporting DSN. Empty string disables crash reporting at startup even when telemetry consent is on. Read by `internal/crashreport/crashreport.go`. |

## Email (password recovery)

| Variable         | Default                                  | Description                                                                                                                                                                              |
| ---------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RESEND_API_KEY` | (unset — recovery emails disabled)       | Resend API key for transactional email delivery. When unset, password-recovery flows surface a "configure RESEND\_API\_KEY or share the reset link manually" message instead of sending. |
| `RESEND_FROM`    | (unset — required together with API key) | `From:` address used for outbound recovery emails (e.g. `Crewship <recovery@example.com>`).                                                                                              |

## Google sign-in (optional)

| Variable               | Default                           | Description                                                                                                            |
| ---------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `GOOGLE_CLIENT_ID`     | (unset — Google sign-in disabled) | OAuth 2.0 client ID for the "Sign in with Google" flow. Loaded via `applyEnvOverrides` in `internal/config/config.go`. |
| `GOOGLE_CLIENT_SECRET` | (unset)                           | OAuth client secret paired with the client ID. Required when `GOOGLE_CLIENT_ID` is set.                                |

## Logging

| Variable              | Default | Description                                 |
| --------------------- | ------- | ------------------------------------------- |
| `CREWSHIP_LOG_LEVEL`  | `info`  | Log level: `debug`, `info`, `warn`, `error` |
| `CREWSHIP_LOG_FORMAT` | `json`  | Log format: `json` or `text`                |

## Authentication

| Variable                    | Default                            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| --------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEXTAUTH_SECRET`           | Auto-generated on first boot       | JWT signing secret for user authentication. Generated via `crypto/rand` (32 bytes → 64 hex chars) and persisted to `<dataDir>/secrets.env` on first start; subsequent boots read the file back. Explicit env vars always win, so Vault / Kubernetes secret mounts / `EnvironmentFile=` keep working unchanged.                                                                                                                                           |
| `CREWSHIP_NEXTJS_URL`       | Auto-derived from port             | Internal URL for self-referencing API calls                                                                                                                                                                                                                                                                                                                                                                                                              |
| `CREWSHIP_INTERNAL_TOKEN`   | Auto-generated on first boot       | Token for sidecar-to-crewshipd IPC authentication. Same auto-gen + persist path as `NEXTAUTH_SECRET`; **stays stable across restarts** once the file exists.                                                                                                                                                                                                                                                                                             |
| `CREWSHIP_ALLOW_SIGNUP`     | `false`                            | Allow new user registration (`true` or `1`)                                                                                                                                                                                                                                                                                                                                                                                                              |
| `CREWSHIP_BOOTSTRAP_WINDOW` | *(unset — open until first admin)* | Opt-in finite first-run window. Unset (default), `/bootstrap` stays open until the first admin account exists (the empty user table is the gate). Set to a positive Go duration (e.g. `5m`, `30s`, `1h`) to arm a deploy-race window that refuses `/bootstrap` with `410` after it elapses — for instances exposed to the internet before they're bootstrapped. Invalid or non-positive values are ignored (falls back to the open-until-admin default). |

<Note>
  As of PR #446 (`internal/secrets`), `NEXTAUTH_SECRET`, `ENCRYPTION_KEY` and `CREWSHIP_INTERNAL_TOKEN` are all bootstrapped on first start: missing values are generated with `crypto/rand`, persisted atomically to `<dataDir>/secrets.env` at mode `0600`, and re-exported into the process environment so existing `os.Getenv` call sites see them unchanged. Explicit env vars override the file; partial persistence is handled (one missing key is filled, the other valid keys are preserved). For clustered deployments, set them explicitly via your secret manager.
</Note>

### Auto-Derived Values

* `CREWSHIP_NEXTJS_URL`: If not explicitly set, defaults to `http://localhost:{CREWSHIP_PORT}`. In single-binary mode, the internal resolver calls itself on the same port.
* `CREWSHIP_INTERNAL_TOKEN`: Auto-generated on first boot and persisted (see Note above). Stays stable across restarts.

## Encryption

| Variable            | Default                      | Description                                                                                                                                                    |
| ------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ENCRYPTION_KEY`    | Auto-generated on first boot | 256-bit hex-encoded AES key for credential encryption. Same auto-gen + persist path as `NEXTAUTH_SECRET` (32 bytes → 64 hex chars in `<dataDir>/secrets.env`). |
| `ENCRYPTION_KEY_V2` | (optional)                   | Rotated encryption key (for key versioning)                                                                                                                    |

## Composio integrations

| Variable                              | Default                           | Description                                                                                                                                                                                                                                                                                                                                                            |
| ------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `COMPOSIO_API_KEY`                    | (unset — provider off)            | Server-wide Composio project API key (`ak_…`). When set, auto-enables the Composio provider unless `COMPOSIO_ENABLED` is explicitly set. Fallback when a workspace has no per-workspace key. Single-tenant: one key = one Composio project shared by all workspaces.                                                                                                   |
| `COMPOSIO_ENABLED`                    | (derived from `COMPOSIO_API_KEY`) | Gates only the **server-env** path (`true`/`1` … `false`/`0`): it forces the env-key auto-enable on without a key, or off so a present `COMPOSIO_API_KEY` is ignored. It is **not** a global kill switch — a workspace that has saved its own key (`composio_settings`) keeps Composio regardless, since the per-workspace key takes precedence over the env fallback. |
| `COMPOSIO_BASE_URL`                   | (Composio production host)        | Override the Composio API host (self-host / proxy / testing).                                                                                                                                                                                                                                                                                                          |
| `COMPOSIO_DEFAULT_CONNECTOR`          | `false`                           | When `true`/`1`, every agent without an explicit per-agent Composio binding inherits a workspace-wide default connector (full access to all connected apps), and legacy non-Composio MCP servers are excluded at resolve time. Behaviour switch only — never auto-enables the provider.                                                                                |
| `NEXT_PUBLIC_LEGACY_MCP_INTEGRATIONS` | (unset)                           | Build-time dashboard flag. `=true` restores the legacy self-hosted MCP integrations UI at `/integrations` (default is the managed Composio UI).                                                                                                                                                                                                                        |

## Keeper (AI Security Gatekeeper)

| Variable            | Default                  | Description                                                                                                                                                   |
| ------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `KEEPER_ENABLED`    | `false`                  | Enable Keeper AI gatekeeper (`true` or `1`)                                                                                                                   |
| `KEEPER_OLLAMA_URL` | `http://localhost:11434` | Ollama API URL for Keeper LLM                                                                                                                                 |
| `KEEPER_MODEL`      | *(none)*                 | Model for Keeper evaluations (e.g. `claude-haiku-4-5`, or an Ollama model name). No default — an enabled Keeper with an empty model fails startup validation. |

<Tip>
  Setting `KEEPER_OLLAMA_URL` auto-enables Keeper (unless `KEEPER_ENABLED` is explicitly `false`). This means you only need to set the URL to activate Keeper.
</Tip>

## LLM Proxy

| Variable    | Default                                | Description           |
| ----------- | -------------------------------------- | --------------------- |
| (YAML only) | `llm_proxy.enabled: true`              | Enable LLM proxy      |
| (YAML only) | `llm_proxy.token_sync_interval: 30s`   | Token sync interval   |
| (YAML only) | `llm_proxy.health_check_interval: 60s` | Health check interval |

## Paymaster (Billing Modes)

These variables tag every cost-ledger row written from inside an agent run. The orchestrator sets them on the agent's environment from the credential type before exec; the sidecar reads them once at startup and includes them on every `POST /api/v1/internal/cost/record` call.

| Variable                     | Default   | Description                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_BILLING_MODE`      | `metered` | `metered` (per-token \$ math) or `flat_rate` (subscription credential, marginal cost = \$0). Source: `internal/orchestrator/exec_env.go:142,153`, `internal/sidecar/server.go:168`.                                                                                                                                                                                                                               |
| `CREWSHIP_SUBSCRIPTION_PLAN` | (empty)   | Display label for flat-rate credentials. Currently the orchestrator hard-codes `"Anthropic Max"` for the OAuth Claude Code path; future credential types (`"Cursor Ultra"`, `"ChatGPT Plus"`) will surface their own labels. Set when `CREWSHIP_BILLING_MODE=flat_rate`; the Paymaster surfaces it on the Subscriptions panel. Source: `internal/orchestrator/exec_env.go:143`, `internal/sidecar/server.go:172`. |

<Note>
  Operators do **not** set these manually for normal use. They are propagated automatically based on the credential's auth type (API key → `metered`, OAuth/subscription → `flat_rate`). They are listed here only for sidecar-image authors and tooling that intercepts the orchestrator handoff.
</Note>

See [Paymaster](/guides/paymaster) for the full billing-mode model and [Migrations](/guides/migrations) for the v62 cost-ledger schema.

## Ollama (Episodic Memory + Keeper)

| Variable        | Default            | Description                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OLLAMA_MODELS` | `~/.ollama/models` | Directory where Ollama stores model blobs. Used by the [Keeper](/guides/keeper) gatekeeper LLM, the [Episodic memory](/guides/episodic-memory) embedder, and the [Consolidator](/guides/consolidate). On macOS dev machines this is typically pointed at an external SSD: `OLLAMA_MODELS="/Volumes/SSD 990 PRO/ollama-models"`. Set this **before** starting Ollama (`./dev.sh start` or `ollama serve`); changing it requires a restart. |

## Feature toggles & runtime tuning

| Variable                    | Default                       | Description                                                                                                                                                                                                                                                                 |
| --------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_CONSOLIDATE_HITL` | (unset — off)                 | Set to `1`/`true`/`yes`/`on` to route the [memory consolidator](/guides/consolidate) through a human-in-the-loop approval step instead of writing directly. Read on every tick so it can be flipped without a restart. Read by `internal/consolidate/runner.go`.            |
| `CREWSHIP_PIPELINE_RUNNER`  | (unset — orchestrator runner) | Selects the pipeline execution backend. Set to `llm_direct` to run pipeline steps through the in-process LLM runner instead of spawning orchestrator containers (also the automatic fallback when no container provider is available). Read by `cmd/crewship/cmd_start.go`. |
| `CREWSHIP_FORECAST_RATES`   | (built-in rate table)         | Overrides the provider price table used by `crewship cost forecast`. Format: `Name,inPerM,outPerM;Name,inPerM,outPerM;…` (USD per million tokens). Malformed entries fall back to the defaults with a one-time stderr warning. Read by `cmd/crewship/cmd_cost_forecast.go`. |
| `CREWSHIP_QUERY_DEPTH`      | `0`                           | Default crew-to-crew query recursion depth when a request does not specify one. Hard-capped at `2` (deeper queries are rejected to prevent loops). Read by `internal/sidecar/query.go`.                                                                                     |

## License

| Variable                | Default | Description          |
| ----------------------- | ------- | -------------------- |
| `CREWSHIP_LICENSE_FILE` | (empty) | Path to license file |

## Seed Data

These variables are used by the `./dev.sh seed` command:

| Variable                 | Description                                      |
| ------------------------ | ------------------------------------------------ |
| `SEED_ANTHROPIC_API_KEY` | Anthropic API key or OAuth token for demo agents |
| `SEED_GOOGLE_EMAIL`      | Google email for seed Google credential          |
| `SEED_GOOGLE_PASSWORD`   | Google password for seed Google credential       |

## Container Runtime

| Variable      | Description                                                  |
| ------------- | ------------------------------------------------------------ |
| `DOCKER_HOST` | Docker socket override (e.g., `unix:///var/run/docker.sock`) |

The Docker provider checks `DOCKER_HOST` first, then auto-detects from candidate socket paths.

## Devcontainer Cache GC

Crewship runs a background sweeper every 30 minutes that detects three kinds
of leaks: temporary provisioning containers orphaned by a `crewshipd` crash
(matched by the `crewship.temp=provision` label), unreferenced
`crewship-cache:*` images left behind when the process is killed between
`docker commit` and the database write that links the image to a crew, and
intermediate `crewship-feat:*` BuildKit feature images (per-feature layers
that are regenerable and never directly referenced by a crew row).

Temp containers older than one hour are always removed. Cache and feature
images are **logged only by default**; deletion must be explicitly enabled.

| Variable                       | Default | Description                                                                                                                                                                                                                                                                                  |
| ------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_CACHE_GC_AUTODELETE` | (unset) | Set to `true` or `1` to remove unreferenced `crewship-cache:*` and intermediate `crewship-feat:*` images automatically. Default behaviour is to log the orphans only — destructive removal is opt-in because deleting a freshly-built local image is surprising in interactive environments. |

A 5-minute age floor protects images that were committed in the last few
minutes (closing the race between `docker commit` and the DB update inside
`Provision()`), so enabling auto-delete is safe even on busy systems.

<Note>
  Leave `CREWSHIP_CACHE_GC_AUTODELETE` unset on developer machines. Enable
  it on long-running production hosts where reclaiming disk matters more
  than preserving incidental cached images. Inspect the orphan list in the
  logs first to verify nothing important would be removed.
</Note>

## CLI client

These configure the `crewship` CLI on a developer/operator machine (not the server). They override values in `~/.crewship/cli-config.yaml`. Resolution order and parsing live in `internal/cli/config.go`.

| Variable                 | Default                       | Description                                                                                                                                             |
| ------------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREWSHIP_SERVER`        | `http://localhost:8080`       | Base URL of the Crewship server the CLI talks to. Takes precedence over `server:` in the config file, but loses to a per-command `--server` flag.       |
| `CREWSHIP_CONFIG`        | `~/.crewship/cli-config.yaml` | Path to the CLI config file. Pin it to a per-instance path when running multiple clones on the same machine so their sessions don't clobber each other. |
| `CREWSHIP_WORKSPACE`     | (unset)                       | Default workspace ID/slug for commands that take one.                                                                                                   |
| `CREWSHIP_DEFAULT_AGENT` | (unset)                       | Default agent the CLI targets when a command omits an explicit agent.                                                                                   |

## Installer

Read by `scripts/install.sh` (the `curl … | bash` install path), not by the running server.

| Variable               | Default                                                            | Description                                                                          |
| ---------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| `CREWSHIP_VERSION`     | (latest stable release)                                            | Pin a specific release tag, e.g. `v0.1.0-beta.1`, instead of the latest stable.      |
| `CREWSHIP_INSTALL_DIR` | auto (`$XDG_BIN_HOME` / `$HOME/.local/bin`, else `/usr/local/bin`) | Override the directory the binary is installed into.                                 |
| `CREWSHIP_SKIP_VERIFY` | `0`                                                                | Set to `1` to skip checksum verification of the downloaded binary (not recommended). |

## Complete Example

```bash theme={null}
# Secrets — optional: auto-generated on first boot and persisted to
# <dataDir>/secrets.env. Set these explicitly only when an external
# secret manager owns them (Vault, k8s secret, systemd EnvironmentFile).
# ENCRYPTION_KEY=a1b2c3d4e5f6...  # 64 hex chars
# NEXTAUTH_SECRET=your-jwt-secret

# Server
CREWSHIP_HOST=0.0.0.0
CREWSHIP_PORT=8080

# Container
CREWSHIP_CONTAINER_PROVIDER=docker
CREWSHIP_SIDECAR_ENABLED=true
CREWSHIP_RUNTIME_IMAGE=debian:bookworm-slim
# CREWSHIP_SIDECAR_PATH and CREWSHIP_ENTRYPOINT_PATH are normally autodetected
# from `make build:sidecar` output. Override when running from an unusual layout.
# CREWSHIP_SIDECAR_PATH=/opt/crewship/crewship-sidecar
# CREWSHIP_ENTRYPOINT_PATH=/opt/crewship/entrypoint.sh

# Auth
CREWSHIP_ALLOW_SIGNUP=true

# Keeper (optional)
KEEPER_OLLAMA_URL=http://localhost:11434
KEEPER_MODEL=claude-haiku-4-5

# Logging
CREWSHIP_LOG_LEVEL=info
CREWSHIP_LOG_FORMAT=json
```

## Validation

The config is validated at startup (`Config.Validate`). These constraints are enforced:

| Field                       | Constraint                                                 |
| --------------------------- | ---------------------------------------------------------- |
| `server.port`               | 1-65535                                                    |
| `ipc.socket_path`           | Non-empty                                                  |
| `container.provider`        | `docker`, `apple`, or `auto`                               |
| `storage.provider`          | `localfs` or `s3`                                          |
| `state.provider`            | `bbolt`                                                    |
| `container.default_runtime` | `runc`, `runsc`, `kata-runtime`, or `sysbox-runc` (if set) |
| `auth.nextjs_url`           | Non-empty                                                  |
