Environment Variable

Short definition

An environment variable is a named key-value pair that the operating system passes to a process when it starts. It controls runtime behaviour without requiring code changes or edits to application config files. Any child process inherits the environment variables of its parent unless explicitly overridden.

Extended definition

Environment variables are one of the oldest and most portable mechanisms for separating configuration from code. A process reads them at startup through the operating system’s process environment block, which is a flat list of strings in the format KEY=VALUE. Because this mechanism is available on every major OS and language runtime, it has become the standard way to supply secrets, feature flags, service endpoints, and tuning parameters to applications.

The Twelve-Factor App methodology formalised this practice by declaring that config should always be stored in the environment rather than in code or checked-in files. This keeps secrets out of version control and makes the same container image or binary deployable across development, staging, and production simply by changing the environment.

In practice, environment variables are set in shell sessions, CI/CD pipeline definitions, Docker Compose files, Kubernetes manifests, systemd unit override files, and cloud provider secret stores. A concrete example is Ollama, the local LLM server: it reads OLLAMA_HOST to decide which address and port to bind its API to, OLLAMA_MODELS to locate stored model weights, OLLAMA_NUM_PARALLEL to cap concurrent inference requests, and OLLAMA_KEEP_ALIVE to decide when to unload a model from RAM. None of these require recompiling or editing a config file; changing the variable and restarting the process is sufficient.

Because environment variables are process-scoped, they are also a reasonable isolation boundary. A containerised service only sees the variables explicitly injected into it, which reduces accidental exposure of credentials across service boundaries.

Deep technical explanation

When the kernel launches a new process, it copies the parent process’s environment into the child’s address space. The child process can read this data through language-level APIs such as os.environ in Python, process.env in Node.js, or getenv() in C. The environment is immutable from the kernel’s perspective after launch: writing to process.env in Node.js changes the in-memory copy but does not propagate changes back to the parent or to sibling processes.

Scope and inheritance

Shell variables and environment variables are distinct. A shell variable is local to the shell session unless exported with the export command, at which point it enters the environment and is inherited by child processes. This distinction matters in scripts: an unexported variable will not be visible to subprocesses invoked within that script.

Systemd and service-level overrides

When a process runs as a systemd service, its environment is not inherited from a user shell. Instead, variables are declared in the unit file using the Environment= directive, or injected via an EnvironmentFile= pointing to a file of KEY=VALUE lines. The recommended way to customise variables without editing the base unit file is to create a drop-in override: run systemctl edit ollama (for example), which creates /etc/systemd/system/ollama.service.d/override.conf. Adding an [Service] section with Environment= entries there keeps the original unit file untouched and survives package upgrades.

Key Ollama environment variables

OLLAMA_HOST sets the IP and port for the API listener, defaulting to 127.0.0.1:11434. OLLAMA_MODELS sets the directory where model weights are stored, defaulting to ~/.ollama/models. OLLAMA_NUM_PARALLEL caps how many inference requests run concurrently. OLLAMA_MAX_LOADED_MODELS limits how many models stay resident in RAM simultaneously. OLLAMA_KEEP_ALIVE controls the idle timeout before a loaded model is evicted from memory. OLLAMA_NUM_THREADS sets the CPU thread count used during inference. Tuning these variables correctly prevents memory exhaustion and controls GPU or CPU utilisation under load.

Common failure modes

A variable set in a shell session is not visible to a systemd service because the service runs under its own environment. A variable that contains spaces or special characters must be quoted correctly in the unit file or it will be parsed as multiple tokens. Secrets placed directly in Dockerfiles or Compose files get baked into image layers and can be extracted from image history. Finally, relying on .env files without a secrets manager means credentials are often committed to version control by mistake.

Practical examples

Scenario 1: Ollama binding to a network interface

A team ran Ollama on a GPU server and needed it accessible from other machines on the LAN. By setting OLLAMA_HOST=0.0.0.0:11434 in a systemd override file and reloading the service, the API became network-accessible without any code change. A firewall rule then limited which IP ranges could reach port 11434.

Scenario 2: Per-environment database URLs in a Node.js API

A SaaS product used the same Docker image across three environments. The DATABASE_URL environment variable was injected via Kubernetes Secrets in production and via a local .env file in development. Rotating the production credential required updating one Secret object, not rebuilding or redeploying the image.

Scenario 3: CI/CD pipeline gating on feature flags

A team used an environment variable ENABLE_DARK_MODE=true in their GitHub Actions pipeline to run an additional set of integration tests only for feature branches. The flag was absent in the main branch pipeline, keeping build times short for production releases.

Scenario 4: Controlling inference concurrency on a shared GPU

Two teams shared one GPU server running Ollama. Setting OLLAMA_NUM_PARALLEL=2 and OLLAMA_MAX_LOADED_MODELS=1 prevented the server from loading a second model while the first was in use, eliminating out-of-memory crashes during peak hours.

Why it matters

  • Environment variables keep secrets and config out of source code, reducing credential exposure in version control.
  • They allow the same build artifact or container image to run correctly in development, staging, and production.
  • They give operators a controlled point for runtime tuning without requiring a rebuild or redeployment.
  • Process-scope isolation means one service cannot accidentally read another service’s variables in a containerised environment.
  • Systemd override files make variable management auditable and reversible without modifying vendor-supplied unit files.
  • Mismanaging environment variables is one of the most common causes of config drift between environments, leading to bugs that only appear in production.

Share this post

Share this link via

Or copy link