Config file and profiles

The ~/.up0/config.yaml shape, the --profile flag, and the default-profile trap.

Config file and profiles

Every command resolves its configuration the same way: pick a profile, then resolve values within it. Nothing here is interactive — there is no setup wizard, only a plain YAML file that commands read from and occasionally write to.

The config file

~/.up0/config.yaml (or $UP0_CONFIG_DIR/config.yaml if set) holds one or more named profiles, plus the OIDC session for each issuer you have logged into:

version: 2
current_profile: default

auth:
  https://auth.up0.io:
    access_token: ey...
    refresh_token: ...
    expires_at: '2026-07-29T07:43:56.030518+00:00'
    client_id: '3315...'

profiles:
  default:
    api_url: https://api.up0.io
    issuer: https://auth.up0.io
    org_id: 3fc89052-dc3b-427e-8d95-b3abce9314c8
  staging:
    api_url: https://api.up0.io
    issuer: https://auth.up0.io
    org_id: c4aa1148-f907-47ca-8e1b-215499ae64df

Two profiles naming the same issuer share one entry under auth:, so switching between them costs no new browser login. A profile pointing at a different issuer needs its own up0 auth login.

Nothing writes org_id except up0 auth login, which fills it in automatically when the account belongs to exactly one organization. Naming a second profile, or setting org_id for an account with several organizations, means editing the file by hand.

There is no built-in API URL or issuer

up0 auth login with no flags creates (or reuses) a profile named default, but nothing fills in api_url or issuer for you: with neither a flag, an environment variable (UP0_API_URL, UP0_ZITADEL_ISSUER) nor a value already stored on the profile, the CLI stops with Error: no API URL configured rather than guessing. The first login against any instance needs both, and naming the profile after the instance keeps them apart:

up0 auth login --profile local \
  --api-url https://api.your-instance.example \
  --issuer https://auth.your-instance.example

The trap is the reuse, not a default. Once default holds one instance's URLs from an earlier login, every later up0 <command> without --profile goes back to that instance, silently, whatever you have been testing against since. A profile name that says which instance it is makes the mistake visible.

Selecting a profile

up0 --profile staging tail --type logs

or UP0_PROFILE=staging. Profile resolution, most to least specific:

  1. --profile <name> flag
  2. UP0_PROFILE environment variable
  3. current_profile key in the config file
  4. the literal name default

An unknown profile name exits with an error listing the profiles that do exist, rather than silently falling back to default.

Per-value environment overrides

Within a resolved profile, three individual values can still be overridden one at a time: UP0_API_URL, UP0_ORG_ID, and UP0_PROFILE itself.

An env var wins over an explicitly named profile

up0 --profile staging tail with a stale exported UP0_ORG_ID in your shell queries the org in UP0_ORG_ID, not staging's. This matches how aws --profile behaves alongside AWS_* env vars, and CI depends on the override working this way. up0 whoami prints (from UP0_ORG_ID) next to any value that came from the environment, so the override is visible instead of silent — run it first if a command seems to be looking at the wrong organization.

Migrating an old config file

A v1 flat config (no profiles: key) migrates to this shape automatically the first time any command runs against it, with the original file copied to config.yaml.v1.bak before the rewrite — so a bad migration never costs a refresh token.

Trusting a private certificate authority

The CLI has no --ca-bundle flag or config field. Against an endpoint whose certificate isn't signed by a public CA — a self-hosted deployment behind an internal root, or a local cluster using a tool like mkcert — set the standard SSL_CERT_FILE environment variable to a bundle that includes that CA:

export SSL_CERT_FILE=/path/to/ca-bundle.pem
up0 --profile local whoami

This is a known limit, not a documented feature: there is no first-class way to point the CLI at a private CA short of the environment variable above (tracked as issue #1671).

On this page