# Using Container Environment Variables to Configure Runtime Behavior in OpenEnv

> Leverage OpenEnv container environment variables to dynamically configure runtime behavior. Adapt your environment across local, Docker, Kubernetes, and remote services seamlessly without code alterations.

- Repository: [Hugging Face/OpenEnv](https://github.com/huggingface/OpenEnv)
- Tags: how-to-guide
- Published: 2026-06-14

---

**OpenEnv reads configuration values from container environment variables at startup using `os.getenv`, allowing the same environment image to run across local development, Docker, Kubernetes, and remote inference services without code changes.**

OpenEnv from Hugging Face builds each environment as a lightweight FastAPI service that configures itself entirely through container environment variables. This design pattern lets you reuse the same Docker image across development, staging, and production simply by changing the variables injected at runtime. Whether you are running a wildfire simulation or an Atari game wrapper, the configuration logic in [`app.py`](https://github.com/huggingface/OpenEnv/blob/main/app.py) files like [`envs/wildfire_env/server/app.py`](https://github.com/huggingface/OpenEnv/blob/main/envs/wildfire_env/server/app.py) relies on standard `os.getenv` calls to control grid dimensions, concurrency limits, and feature toggles.

## How OpenEnv Reads Container Environment Variables

### Reading Variables with Default Values

Each environment’s [`app.py`](https://github.com/huggingface/OpenEnv/blob/main/app.py) begins by importing `os` and calling `os.getenv` with sensible defaults. This ensures the service starts even when variables are missing.

In [`envs/wildfire_env/server/app.py`](https://github.com/huggingface/OpenEnv/blob/main/envs/wildfire_env/server/app.py), the server reads grid dimensions and concurrency limits:

```python
import os

W = int(os.getenv("WILDFIRE_WIDTH", "16"))
H = int(os.getenv("WILDFIRE_HEIGHT", "16"))
max_concurrent = int(os.getenv("MAX_CONCURRENT_ENVS", "8"))

```

The retrieved values pass directly to the environment constructor:

```python
return WildfireEnvironment(width=W, height=H)

```

### Boolean Flags and Conditional Features

Boolean toggles use case-insensitive evaluation to enable optional UI components or debug modes. In [`envs/wildfire_env/server/app.py`](https://github.com/huggingface/OpenEnv/blob/main/envs/wildfire_env/server/app.py), the web interface flag parses as follows:

```python
enable_web = os.getenv("ENABLE_WEB_INTERFACE", "false").lower() in ("true", "1", "yes")

```

This pattern allows strings like `"True"`, `"1"`, or `"yes"` to activate features consistently across shell scripts and YAML manifests.

### Centralized Server Factory

All environments leverage the shared `create_app` helper in [`src/openenv/core/env_server/http_server.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/core/env_server/http_server.py). This factory reads global variables like `MAX_CONCURRENT_ENVS` and `ENABLE_WEB_INTERFACE` before instantiating the FastAPI application, guaranteeing a consistent HTTP interface regardless of the specific environment logic.

## Commonly Used Environment Variables

OpenEnv respects the following variables across different environment types:

- **`MAX_CONCURRENT_ENVS`**: Default `8`. Controls the maximum number of parallel environment instances the server hosts.
- **`ENABLE_WEB_INTERFACE`**: Default `false`. When set to `"true"`, injects custom HTML UI routes (e.g., the wildfire visualization).
- **`PORT`**: Default `8000`. TCP port for the uvicorn server binding.
- **`WILDFIRE_WIDTH`** / **`WILDFIRE_HEIGHT`**: Default `16`. Grid dimensions for the wildfire simulation.
- **`ATARI_GAME`** / **`ATARI_OBS_TYPE`**: Default `pong` and `rgb`. Selects the ROM and observation encoding for Atari environments.
- **`SUMO_NET_FILE`** / **`SUMO_ROUTE_FILE`**: Paths to SUMO simulation files for traffic control scenarios.
- **`CARLA_SCENARIO`** / **`CARLA_MODE`**: Default `trolley_saves` and `mock`. Configures autonomous driving scenarios.

Every variable follows the same idiom: an `os.getenv` call with a default, converted to the appropriate Python type (`int`, `float`, or `bool`).

## Runtime Configuration Examples

### Docker Deployment

Pass variables via the `-e` flag when running the container:

```bash
docker run -p 8000:8000 \
  -e MAX_CONCURRENT_ENVS=16 \
  -e ENABLE_WEB_INTERFACE=true \
  -e WILDFIRE_WIDTH=32 \
  -e WILDFIRE_HEIGHT=32 \
  huggingface/openenv-wildfire:latest

```

This command launches a 32×32 wildfire grid with the web UI enabled on port 8000.

### Kubernetes Pod Configuration

Inject variables through the `env` block in your pod spec:

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: echo-env
spec:
  containers:
    - name: echo
      image: huggingface/openenv-echo:latest
      env:
        - name: MAX_CONCURRENT_ENVS
          value: "4"
        - name: ENABLE_WEB_INTERFACE
          value: "false"

```

### Local Python Development

Set variables in your shell or Python script before importing the server:

```python
import os
from envs.echo_env.server.app import main

os.environ["MAX_CONCURRENT_ENVS"] = "2"
os.environ["ENABLE_WEB_INTERFACE"] = "true"

if __name__ == "__main__":
    main()

```

This local execution respects the same configuration interface as containerized deployments.

## Extending the Pattern for Custom Environments

When creating a new environment, add configuration variables at the top of your [`app.py`](https://github.com/huggingface/OpenEnv/blob/main/app.py):

```python
import os

# Custom parameter with default

my_param = os.getenv("MY_PARAM", "default_value")

# Boolean flag

my_flag = os.getenv("MY_FLAG", "false").lower() in ("true", "1", "yes")

```

Pass these values to your environment constructor. Because `create_app` in [`src/openenv/core/env_server/http_server.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/core/env_server/http_server.py) already handles `MAX_CONCURRENT_ENVS` and `ENABLE_WEB_INTERFACE`, you inherit global capabilities automatically.

## Summary

- OpenEnv uses `os.getenv` in `envs/*/server/app.py` files to read container environment variables at startup.
- **Default values** ensure the service runs without explicit configuration, while **type conversion** handles integers, floats, and booleans.
- The **`create_app`** factory in [`src/openenv/core/env_server/http_server.py`](https://github.com/huggingface/OpenEnv/blob/main/src/openenv/core/env_server/http_server.py) centralizes common settings like concurrency limits and web UI toggles.
- You can configure deployments identically across **Docker**, **Kubernetes**, and **local Python** processes by changing only the injected variables.

## Frequently Asked Questions

### How does OpenEnv handle missing environment variables?

OpenEnv supplies sensible defaults in every `os.getenv` call. For example, `MAX_CONCURRENT_ENVS` defaults to `"8"` and `PORT` defaults to `"8000"`, ensuring the FastAPI server starts even if you provide no variables.

### Can I add my own custom environment variables to a new environment?

Yes. Add an `os.getenv("MY_VAR", "default")` line at the top of your environment's [`app.py`](https://github.com/huggingface/OpenEnv/blob/main/app.py), then pass the value to your constructor. The centralized server factory automatically respects standard variables like `MAX_CONCURRENT_ENVS` without additional code.

### What is the correct format for boolean environment variables in OpenEnv?

OpenEnv checks for case-insensitive truthy values. Set the variable to `"true"`, `"1"`, or `"yes"` to enable a feature. Any other value, including `"false"` or an empty string, evaluates to disabled.

### Where is the server port configured in OpenEnv?

The `PORT` variable is read in individual [`app.py`](https://github.com/huggingface/OpenEnv/blob/main/app.py) files (e.g., [`envs/wildfire_env/server/app.py`](https://github.com/huggingface/OpenEnv/blob/main/envs/wildfire_env/server/app.py)) using `int(os.getenv("PORT", "8000"))`, then passed to the uvicorn server in the `main()` function.