> ## Documentation Index
> Fetch the complete documentation index at: https://gomodel-docs-benchmark-writeup-and-tooling.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# config.yaml

> When to use config.yaml, when not to, and how it interacts with environment variables and Docker.

The goal in GoModel is to make `config.yaml` optional as much as possible.
Prefer environment variables for normal deployments, CI, containers, and secret
injection.

Use `config.yaml` when you need structure that env vars cannot express cleanly,
especially:

* per-provider resilience overrides
* custom provider instance names that do not fit the generated
  `<provider-type>-<suffix>` env naming
* richer reviewable provider model lists, especially when using allowlist mode
* reviewable budget limits by `user_path`
* larger nested config that is easier to review in one file

For multiple provider instances, env vars support
`<PROVIDER>_<SUFFIX>_API_KEY`, `<PROVIDER>_<SUFFIX>_BASE_URL`, and
`<PROVIDER>_<SUFFIX>_MODELS`. The suffix becomes a hyphenated provider name:
`OPENAI_EAST_API_KEY` registers `openai-east`, and
`OLLAMA_A_BASE_URL` registers `ollama-a`. Azure also supports
`<PROVIDER>_<SUFFIX>_API_VERSION`.

Google Vertex AI follows the same suffix-to-name rule (`VERTEX_US_PROJECT`
registers `vertex-us`). Vertex project, location, and other Vertex settings
must use the same suffix for each instance: for example, pair
`VERTEX_US_PROJECT` with `VERTEX_US_LOCATION`, not the generic
`VERTEX_PROJECT` or `VERTEX_LOCATION`. `VERTEX_AUTH_TYPE` defaults to
`gcp_adc`.

Configured provider model lists can stay in env via `<PROVIDER>_MODELS`, for
example `OPENROUTER_MODELS`, `ORACLE_MODELS`, `AZURE_MODELS`, or `VLLM_MODELS`.
Set `CONFIGURED_PROVIDER_MODELS_MODE=fallback` (default) to use those lists only
when upstream `/models` fails or is empty, or `allowlist` to expose only the
configured models for providers that define a list and skip their upstream
`/models` calls.

## Priority Order

Effective precedence is:

1. environment variables
2. optional `config/config.yaml` or `config.yaml`
3. built-in defaults from code

`.env` is not a separate priority layer. It is just a convenient way to load
environment variables before startup.

## Current Schema

The current source of truth lives in the main codebase:

* [config/config.go](https://github.com/ENTERPILOT/GoModel/blob/main/config/config.go)
* [config/config.example.yaml](https://github.com/ENTERPILOT/GoModel/blob/main/config/config.example.yaml)

For deployments mounted below a domain root, set `server.base_path` or
`BASE_PATH`. For example, `BASE_PATH=/g` serves the gateway at `/g/v1/...`,
`/g/admin/...`, and `/g/health`.

To change the inbound user path header, set `server.user_path_header` or
`USER_PATH_HEADER`. The default remains `X-GoModel-User-Path`.

## Docker

GoModel reads `config/config.yaml` first, then `config.yaml`.

With `docker run`, you can keep a host file named `config.yml` and mount it to
the in-container path GoModel expects:

```bash theme={null}
docker run --rm -p 8080:8080 \
  -v "$PWD/config.yml:/app/config/config.yaml:ro" \
  enterpilot/gomodel:latest
```

With Docker Compose:

```yaml theme={null}
services:
  gomodel:
    image: enterpilot/gomodel:latest
    ports:
      - "8080:8080"
    volumes:
      - ./config.yml:/app/config/config.yaml:ro
```

<Tip>
  If env vars and YAML both define the same setting, the environment variable
  wins.
</Tip>

## Gotchas

### Unresolved `${VAR}` placeholders drop the provider

If `${OPENAI_API_KEY}` appears in YAML but the env var is not actually set, the
literal string `${OPENAI_API_KEY}` ends up as the API key value. The credential
filter detects the `${` substring and removes the provider entirely. This also
applies if `${VAR}` appears in the middle of the value, such as
`prefix-${OPENAI_API_KEY}`. Always verify your env vars are exported before
starting the process, or supply a default: `${OPENAI_API_KEY:-}`.

### Per-provider resilience can only come from YAML

The env-var override walk skips `map` fields. `RETRY_MAX_RETRIES` changes the
global default for all providers but cannot target a single provider.
Per-provider tuning requires a `providers.<name>.resilience:` block in
`config.yaml`.

### Partial YAML leaves the rest at defaults

YAML is unmarshalled onto a struct that has already been populated with
built-in defaults. Only fields that appear in the file are written. Omitting
`max_backoff` from `resilience.retry` leaves it at its built-in default; you do
not need to repeat defaults you are happy with.
