> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runflow.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Hosted & Multiple Environments

> Point the CLI at your own RunFlow installation and switch between environments

The CLI talks to RunFlow Cloud (`https://api.runflow.ai`) by default. If you run RunFlow in your own environment — or juggle several environments (cloud, staging, a customer install) — you point the CLI at each API **once** and it remembers everything for that profile: the API URL and the identity provider used to log in.

## Change the API once

```bash theme={null}
rf login --api https://api.yourcompany.com
```

That single flag does three things:

1. **Resolves the target API** and shows it before opening the browser.
2. **Discovers the login provider** from the server, so you sign in against *your* identity provider — not `auth.runflow.ai`.
3. **Remembers both** in the active profile. Every later `rf login`, token refresh, and command reuses the same URL and provider — no need to pass `--api` again.

<Info>
  Discovery is automatic. The CLI calls the installation's public
  `GET /runtime/auth/cli-config` endpoint to learn which OIDC provider to open.
  If the server doesn't publish it (older versions) or is unreachable, the CLI
  falls back to RunFlow Cloud defaults — so existing logins keep working.
</Info>

## How the provider is resolved

When you log in or refresh a token, the CLI resolves the auth provider in this order (first match wins):

| Priority | Source                                        | When to use                                                 |
| -------- | --------------------------------------------- | ----------------------------------------------------------- |
| 1        | `RUNFLOW_AUTH0_*` env vars                    | Force a provider locally (CI, testing)                      |
| 2        | Server discovery (`/runtime/auth/cli-config`) | Normal self-hosted flow — nothing to configure on your side |
| 3        | `auth` saved in the profile                   | Reusing a profile you already logged into                   |
| 4        | RunFlow Cloud defaults                        | Cloud, or a server without the discovery endpoint           |

The API URL follows the same idea: `--api` > `RUNFLOW_API_URL` > the active profile's saved `api` > cloud default.

## Multiple environments as profiles

Each profile remembers its own API URL and provider, so cloud and self-hosted installs live side by side. There's no separate "create profile" command — a profile is created (and activated) when you log in with `--profile`:

```bash theme={null}
# Cloud (default provider)
rf login --profile cloud

# Your self-hosted staging install
rf login --profile staging --api https://api.staging.yourcompany.com

# A customer's install with their own identity provider
rf login --profile acme --api https://runflow.acme.com
```

`rf login --profile <name>` both creates and activates that profile, so the last
login is the active one. You only pass `--api` the first time — the URL and
provider are remembered for that profile afterward.

<Info>
  **Switching environments vs. tenants.** With a browser (OIDC) login,
  `rf switch` moves between the **tenants of the active account** — not between
  profiles. To activate a different environment, log into it again with
  `rf login --profile <name>`. (API-key logins switch between profiles directly
  with `rf switch <name>`.) See [Profiles](/cli/profiles).
</Info>

## Signing out

`rf logout` clears the stored tokens **but keeps** the API URL, provider, and tenant, so signing back in is a single `rf login` with no flags:

```bash theme={null}
rf logout               # current profile
rf logout staging       # a specific profile
rf logout --all         # every profile
```

## Environment variable overrides

Useful for CI or scripted runs where you don't want to persist a profile:

| Variable                  | Overrides                             |
| ------------------------- | ------------------------------------- |
| `RUNFLOW_API_URL`         | Target API base URL                   |
| `RUNFLOW_AUTH0_DOMAIN`    | Login provider domain                 |
| `RUNFLOW_AUTH0_CLIENT_ID` | OIDC client ID used for login/refresh |
| `RUNFLOW_AUTH0_AUDIENCE`  | Token audience                        |

Env vars take precedence over both server discovery and the saved profile.

## Where it's stored

Connection settings are saved per profile in `~/.runflowrc` (YAML):

```yaml theme={null}
currentProfile: staging
profiles:
  staging:
    api: https://api.staging.yourcompany.com/api/v1/runtime
    auth:
      domain: https://login.yourcompany.com
      clientId: <native-oidc-client-id>
      audience: https://api.staging.yourcompany.com
    tenantId: tenant_123
    tenantName: Your Company
```

<Warning>
  `~/.runflowrc` holds credentials. Keep it private and restrict permissions:

  ```bash theme={null}
  chmod 600 ~/.runflowrc
  ```
</Warning>

## For self-hosted administrators

For the CLI to discover *your* provider (instead of falling back to cloud), the api-portal serving the installation must expose the discovery endpoint and have these set:

| api-portal env var    | Purpose                                                                                              |
| --------------------- | ---------------------------------------------------------------------------------------------------- |
| `AUTH0_DOMAIN`        | Your identity provider's domain — the CLI opens `/authorize` here                                    |
| `AUTH0_CLI_CLIENT_ID` | A **dedicated native/public (PKCE) client**, distinct from the portal SPA client (`AUTH0_CLIENT_ID`) |
| `AUTH0_AUDIENCE`      | The API audience for issued tokens                                                                   |

Register the native OIDC client on your identity provider with these callback URLs:

```
http://localhost:8630/callback
http://localhost:8631/callback
...
http://localhost:8640/callback
```

<Warning>
  `AUTH0_DOMAIN` and `AUTH0_CLI_CLIENT_ID` must be set **together**. If only the
  domain is set, the CLI keeps the cloud client ID — which doesn't exist on your
  provider — and login fails. If neither is set, discovery returns nothing and
  the CLI opens RunFlow Cloud login instead.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Login" icon="key" href="/cli/login">
    Authentication and profile basics
  </Card>

  <Card title="Profiles" icon="users" href="/cli/profiles">
    Manage and switch environments
  </Card>
</CardGroup>
