How to Manage Environment Variables in OpenWork: A Complete Configuration Guide
OpenWork uses the dotenv library to load configuration from .env files in three layers—local files, service-specific overrides, and process environment—allowing secure secret management without committing sensitive data to version control.
OpenWork relies heavily on environment variables for runtime configuration, from authentication tokens to workspace paths. Understanding how to properly manage these variables is essential for both local development and production deployments in the different-ai/openwork repository. This guide explains the complete environment variable lifecycle, from the initial loading mechanisms in load-env.ts to specific configuration options for tokens, ports, and development modes.
Three-Layer Configuration Loading
OpenWork implements a cascading configuration system that prioritizes security and flexibility. The loading order ensures that committed code never contains secrets while allowing overrides for different deployment environments.
Layer 1: Local Environment Files
The system first searches for /.env or /.env.local files adjacent to the service directory. These files load without overriding existing values, establishing baseline configuration for development. This implementation resides in ee/apps/inference/src/load-env.ts and similar service-specific loaders.
Layer 2: Service-Specific Overrides
Certain services implement additional environment file discovery. The den-worker-proxy searches upward through the directory tree for /.env.daytona, enabling per-Daytona environment configurations. This logic is implemented in ee/apps/den-worker-proxy/src/load-env.ts, allowing the proxy to locate environment files up to eight directories above its execution context using OPENWORK_DAYTONA_ENV_PATH.
Layer 3: Process Environment
Finally, dotenv.config({ override: false }) executes to ensure any variables set by your CI pipeline, Docker container, or shell session take precedence. Because the loading order follows file → file → process, system-level environment variables always win, making the system safe for production deployments where .env files may not exist.
Essential Environment Variables
OpenWork recognizes several critical environment variables that control authentication, workspace location, and development behavior.
Authentication and Security
OPENWORK_TOKEN: The primary bearer token for the OpenWork UI, auto-generated on first launch or read from the token store. This variable facilitates communication between the server and user interface.OPENWORK_HOST_TOKEN: Grants administrative access to host-only routes, including secret management endpoints. The server generates this alongside the standard token during initialization.OPENWORK_TOKEN_STORE: Overrides the default path for token persistence. When unset, tokens write to<config-dir>/tokens.jsonas determined byopenworkConfigDir(). TheTokenServiceclass inapps/server/src/tokens.ts(lines 22-31) handles this resolution usingpath.resolve.
Workspace and Network Configuration
OPENWORK_WORKSPACE: Defines the root folder holding the user's OpenWork workspace. Defaults to the current working directory (process.cwd()).OPENWORK_REMOTE_ACCESS: When set totrue, binds the server to0.0.0.0instead of localhost, making the instance reachable from other hosts on the network.OPENWORK_PUBLIC_HOST: Overrides the host reported in the runtime manifest, essential for NAT traversal and port-forwarding scenarios.OPENWORK_PORTandOPENWORK_WEB_PORT: Define custom ports for the server and web interface. TheresolvePorthelper inscripts/dev-headless-web.ts(lines 70-95) validates port availability, requesting random free ports from the OS if these variables are unset.
Development and Testing Variables
OPENWORK_DEV_HEADLESS_WEB_REPLACE: Forces a fresh headless-web instance when runningscripts/dev-headless-web.ts. Set to1ortrueto enable.OPENWORK_DEV_HEADLESS_WEB_DEN_PROXY: Controls the embedded Den proxy. Defaults totrue; set to0orfalseto disable.OPENWORK_DEV_DEN_PROXY_TARGET: Specifies a custom URL for the Den proxy. Thedev-headless-web.tsscript normalizes this value withnormalizeDenTargetand exposes it to Vite asVITE_DEN_API_BASE_URL(lines 117-138).OPENWORK_EVAL_*: A series of flags (such asAPP_SPECS=1orDAYTONA=1) used exclusively by the evaluation suite inevals/specs/. These do not affect production runtime.
Frontend Build Variables
VITE_OPENWORK_URLandVITE_OPENWORK_TOKEN: Injected into the browser bundle during the Vite build process. These are populated from the generated runtime manifest. Never exposeOPENWORK_HOST_TOKENto these frontend variables.
Practical Configuration Examples
Creating a Local Development Environment
Create a .env.local file in your project root to store sensitive development credentials without committing them to version control:
# .env.local (never commit this file!)
OPENWORK_TOKEN=my-dev-token
OPENWORK_HOST_TOKEN=my-host-token
OPENWORK_WORKSPACE=/path/to/my/workspace
OPENWORK_REMOTE_ACCESS=1
Running pnpm dev:headless-web automatically picks up these values because load-env.ts processes .env.local before other configuration sources.
Customizing Token Storage Location
To store tokens in a temporary location for testing or CI environments:
export OPENWORK_TOKEN_STORE=/tmp/openwork-tokens.json
pnpm start
The server now reads and writes authentication tokens to /tmp/openwork-tokens.json instead of the default configuration directory. This override is processed in apps/server/src/tokens.ts (lines 24-31).
Managing Headless Web Sessions
Force a complete restart of the headless-web environment with fresh tokens:
pnpm dev:headless-web --replace
To preserve existing tokens during the restart:
pnpm dev:headless-web --replace --keep-tokens
The --replace flag checks process.env.OPENWORK_DEV_HEADLESS_WEB_REPLACE at line 31 of dev-headless-web.ts.
Configuring Custom Proxy Targets
Point the embedded Den proxy to a custom backend for integration testing:
export OPENWORK_DEV_DEN_PROXY_TARGET=https://custom-den.example.com
export OPENWORK_DEV_HEADLESS_WEB_DEN_PROXY=1
pnpm dev:headless-web
The script validates the target URL through normalizeDenTarget before injecting VITE_DEN_API_BASE_URL into the Vite environment.
Security Best Practices
Token Persistence and Permissions
When scripts/dev-headless-web.ts generates the runtime manifest containing URLs, tokens, and process IDs, it writes the file with mode 0o600 (owner-only permissions). This prevents accidental leakage of sensitive credentials to other system users.
Variable Precedence for Secrets
Because the loading mechanism uses override: false when processing .env files, you can safely template default values in committed .env.example files while overriding them with actual secrets in your shell environment or Docker secrets management. The TokenService class respects this precedence when resolving OPENWORK_TOKEN_STORE paths.
Separation of Concerns
Maintain strict separation between OPENWORK_TOKEN (UI access) and OPENWORK_HOST_TOKEN (administrative access). The host token grants elevated privileges for secret management routes and should never be exposed to frontend code or browser-accessible environment variables.
Summary
- OpenWork loads environment variables in three layers: local
.envfiles, service-specific overrides (like.env.daytona), and process environment variables. - The dotenv library handles initialization in
ee/apps/inference/src/load-env.tsand related service loaders without overriding existing process variables. - Authentication tokens (
OPENWORK_TOKENandOPENWORK_HOST_TOKEN) auto-generate on first launch unless specified via environment variables or custom token store paths. - Development scripts like
dev-headless-web.tsconsume specific variables (OPENWORK_DEV_HEADLESS_WEB_REPLACE,OPENWORK_DEV_DEN_PROXY_TARGET) to control runtime behavior and proxy configuration. - Runtime manifests write with restrictive
0o600permissions to prevent credential leakage.
Frequently Asked Questions
What is the precedence order for environment variables in OpenWork?
OpenWork follows a strict file-to-process hierarchy. First, it loads /.env and /.env.local from the service directory. Next, specific services like the den-worker-proxy search for /.env.daytona upward through the directory tree. Finally, dotenv.config({ override: false }) ensures that variables already present in the process environment (set by Docker, CI systems, or shell exports) take final precedence.
How do I securely store tokens in OpenWork?
Tokens persist to a JSON file determined by OPENWORK_TOKEN_STORE or defaulting to <config-dir>/tokens.json. The runtime manifest writes with mode 0o600 (owner-only read/write) to prevent unauthorized access. For production, set tokens via process environment variables rather than .env files, and never commit .env.local to version control.
Can I use a custom path for the token store file?
Yes. Set the OPENWORK_TOKEN_STORE environment variable to an absolute path before starting the server. The TokenService class in apps/server/src/tokens.ts (lines 22-31) resolves this path using path.resolve, allowing you to store tokens in tmpfs mounts, external volumes, or specific directories outside the default configuration folder.
What is the difference between OPENWORK_TOKEN and OPENWORK_HOST_TOKEN?
OPENWORK_TOKEN serves as the primary bearer token for UI-to-server communication, while OPENWORK_HOST_TOKEN grants administrative access to host-only routes such as secret management endpoints. The host token carries elevated privileges and should remain server-side only, whereas the standard token can safely populate VITE_OPENWORK_TOKEN for frontend authentication.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →