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.
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 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). |
CREWSHIP_CONTAINER_PREFIX is essential for multi-instance deployments. Without it, multiple Crewship instances will create containers with colliding names like crewship-team-engineering.
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). |
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.
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. |
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.
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. |
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.
See Paymaster for the full billing-mode model and 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 gatekeeper LLM, the Episodic memory embedder, and the Consolidator. 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 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.
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.
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
# 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 |