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

# Environment Variables

CyborgDB Service is configured through environment variables (or an
optional [YAML config file](#yaml-configuration-file)). Every value
below is settable in both places; environment variables override the
file on conflict.

<Note>
  **v0.17 storage refactor.** The service now exposes a single, flat
  storage surface: `memory`, `disk` (embedded RocksDB), or `s3` (AWS S3
  or any S3-compatible store). The previous `standalone`, `postgres`,
  and `redis` backends — and the catch-all `CYBORGDB_CONNECTION_STRING`
  — are gone. If you are upgrading from v0.16: switch
  `standalone` → `disk` and replace `CYBORGDB_CONNECTION_STRING` with
  the new `CYBORGDB_DISK_PATH` / `CYBORGDB_S3_*` variables.
</Note>

## API Key and Tiers

| Variable           | Description                                                                                                                                                                                                                                                            | Example            |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `CYBORGDB_API_KEY` | *(Optional)* Your CyborgDB license key. Doubles as the value clients must send in the `X-API-Key` request header when `REQUIRE_API_KEY=true`. If unset, the service runs in **free tier** mode (per-index cap of 1,000,000 items). Set a paid key for unlimited usage. | `cyborg_abc123...` |

<Note>
  **Free tier vs paid.** `CYBORGDB_API_KEY` is the single switch between the two:

  * **Unset** → free tier. cyborgdb-core enforces a 1M-item-per-index cap. The startup banner prints `CYBORGDB_API_KEY not set — running in free tier`. For evaluation only.
  * **Set to a paid key** (from the [CyborgDB dashboard](https://cyborgdb.co/)) → unlimited items, full feature set.
  * **Set to a demo key** (from `cyborgdb.get_demo_api_key()` / `getDemoApiKey()` / `cyborgdb.GetDemoAPIKey(...)`) → also free tier, time-limited. Useful for getting a real-looking key into `X-API-Key` without dashboard signup.

  In every case, the same value is what clients pass in the `X-API-Key` header (assuming `REQUIRE_API_KEY=true`, the default).
</Note>

<Warning>Storage configuration is optional — `disk` is used by default.</Warning>

## RBAC / Multi-Tenancy

CyborgDB Service can run in single-key mode (default) or with role-based access control enabled. RBAC is opt-in: setting `CYBORGDB_SERVICE_ROOT_KEY` switches the service into RBAC mode, after which the legacy single key is no longer accepted on index routes — only the root key or a minted per-user `cdbk_…` key.

| Variable                      | Description                                                                                                                                                                                                                                        | Default          |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| `CYBORGDB_SERVICE_ROOT_KEY`   | When set, enables RBAC. The holder of this key has full admin access and can mint per-user API keys via `POST /v1/indexes/{index_name}/users`. Per-user keys are scoped to one index with `read` / `write` permissions enforced cryptographically. | unset (RBAC off) |
| `INDEX_KEK_CACHE_TTL_SECONDS` | TTL for plaintext index KEKs in the service-side cache. Shorter = faster KMS revocation propagation; longer = fewer KMS calls.                                                                                                                     | `60`             |

See the [Multi-Tenancy guide](./multi-tenancy) for the full operator playbook (key kinds, provisioning users, KMS-backed constraint, revocation).

## Storage Backend

Pick one of `memory`, `disk`, or `s3`. If `CYBORGDB_DB_TYPE` is unset,
the service defaults to `disk`.

| Variable           | Description                                | Default | Example |
| ------------------ | ------------------------------------------ | ------- | ------- |
| `CYBORGDB_DB_TYPE` | Storage backend: `memory`, `disk`, or `s3` | `disk`  | `s3`    |

### Disk (default)

Embedded RocksDB. Persistent local key-value storage with no external
dependency.

| Variable             | Description                          | Default                                                    |
| -------------------- | ------------------------------------ | ---------------------------------------------------------- |
| `CYBORGDB_DISK_PATH` | Data directory for the RocksDB store | `~/.cyborgdb/data` (local) / `/app/cyborgdb_data` (Docker) |

```bash theme={null}
export CYBORGDB_DB_TYPE=disk
export CYBORGDB_DISK_PATH=/var/lib/cyborgdb   # optional
```

### Memory

In-process storage. Nothing persists across restarts. Use only for
tests and ephemeral indexes.

```bash theme={null}
export CYBORGDB_DB_TYPE=memory
```

### S3

AWS S3 or any S3-compatible store (MinIO, Cloudflare R2, …).

| Variable                    | Description                        | Required for S3                      |
| --------------------------- | ---------------------------------- | ------------------------------------ |
| `CYBORGDB_S3_BUCKET`        | Bucket name                        | ✅                                    |
| `CYBORGDB_S3_REGION`        | Bucket region                      | Optional (defaults to `us-east-1`)   |
| `CYBORGDB_S3_PREFIX`        | Key prefix for stored objects      | Optional                             |
| `CYBORGDB_S3_ENDPOINT`      | Custom endpoint URL (MinIO, R2, …) | Required for non-AWS endpoints       |
| `CYBORGDB_S3_ACCESS_KEY`    | S3 access key ID                   | Required with `CYBORGDB_S3_ENDPOINT` |
| `CYBORGDB_S3_SECRET_KEY`    | S3 secret access key               | Required with `CYBORGDB_S3_ENDPOINT` |
| `CYBORGDB_S3_SESSION_TOKEN` | Optional temporary session token   | Optional                             |

#### S3 credential resolution

The S3 client resolves credentials independently of any KMS client:

* **On AWS (EC2 / ECS / EKS), real S3.** Leave all `CYBORGDB_S3_*`
  credential variables unset. The AWS default credential provider
  chain picks up the instance/task role.
* **Off AWS, real S3.** Provide `AWS_ACCESS_KEY_ID` /
  `AWS_SECRET_ACCESS_KEY` (or a mounted AWS profile). The default
  chain picks them up.
* **S3-compatible endpoint (MinIO, R2, …).** Set
  `CYBORGDB_S3_ENDPOINT` **plus** explicit
  `CYBORGDB_S3_ACCESS_KEY` / `CYBORGDB_S3_SECRET_KEY`. A custom
  endpoint is not AWS — the AWS chain is never used against it, and
  startup fails fast if the explicit keys are missing.

The `CYBORGDB_S3_*` namespace is deliberately separate from `AWS_*`
so storage credentials cannot collide with KMS credentials.

```bash theme={null}
# AWS S3 with instance role
export CYBORGDB_DB_TYPE=s3
export CYBORGDB_S3_BUCKET=my-bucket
export CYBORGDB_S3_REGION=us-east-1

# MinIO
export CYBORGDB_DB_TYPE=s3
export CYBORGDB_S3_BUCKET=my-bucket
export CYBORGDB_S3_ENDPOINT=https://minio.internal:9000
export CYBORGDB_S3_ACCESS_KEY=minioadmin
export CYBORGDB_S3_SECRET_KEY=minioadmin
```

## Optional Environment Variables

<AccordionGroup>
  <Accordion title="Service Configuration">
    | Variable                     | Description                                            | Default |
    | ---------------------------- | ------------------------------------------------------ | ------- |
    | `PORT`                       | HTTP port for the service                              | `8000`  |
    | `CYBORGDB_SERVICE_LOG_LEVEL` | Log level (`DEBUG`, `INFO`, `WARNING`, `ERROR`)        | `INFO`  |
    | `REQUIRE_API_KEY`            | Whether the `X-API-Key` header is required on requests | `true`  |

    <Warning>When `REQUIRE_API_KEY=true` (the default), clients must send a bearer credential in `X-API-Key`. That credential is `CYBORGDB_API_KEY` (legacy single-key auth, also the license key — see above) or `CYBORGDB_SERVICE_ROOT_KEY` (RBAC / multi-tenant). If neither is set, every request is rejected with 401 and the service emits a startup warning. To run unauthenticated, set `REQUIRE_API_KEY=false` explicitly — note this is independent of the free-tier / paid-tier distinction, which is gated only by `CYBORGDB_API_KEY`'s value.</Warning>
  </Accordion>

  <Accordion title="TLS / HTTPS">
    | Variable        | Description             | Default      |
    | --------------- | ----------------------- | ------------ |
    | `SSL_CERT_PATH` | Path to TLS certificate | unset (HTTP) |
    | `SSL_KEY_PATH`  | Path to TLS private key | unset (HTTP) |

    <Note>HTTPS is enabled automatically when both `SSL_CERT_PATH` and `SSL_KEY_PATH` are set and both files exist. Otherwise the service starts on HTTP.</Note>
  </Accordion>

  <Accordion title="Per-keystore RAM cache">
    Applied to every newly created index. `cyborgdb-core` caches
    nothing by default; opt in here per keystore.

    | Variable                | Description                  | Default |
    | ----------------------- | ---------------------------- | ------- |
    | `CACHE_POLICY_VECTORS`  | Cache vector payloads in RAM | `false` |
    | `CACHE_POLICY_METADATA` | Cache metadata in RAM        | `false` |
    | `CACHE_POLICY_IDS`      | Cache item IDs in RAM        | `false` |
  </Accordion>

  <Accordion title="Performance">
    | Variable              | Description                                                                                                                                                                                                                        | Default |
    | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
    | `CPU_THREADS`         | Worker threads. `0` = auto-detect                                                                                                                                                                                                  | `0`     |
    | `GPU_OPERATIONS`      | GPU-accelerated ops: `none`, `upsert`, `train`, `all`, or comma-separated (e.g. `upsert,train`)                                                                                                                                    | `none`  |
    | `RETRAIN_THRESHOLD`   | Auto-retrain trigger — fires when `num_vectors > n_lists * RETRAIN_THRESHOLD`                                                                                                                                                      | `10000` |
    | `AUTO_TRAIN_DISABLED` | Fully disable post-upsert auto-training. Explicit `train()` / `POST /v1/indexes/train` still work. Useful for benchmarking a fixed index state or controlling training timing yourself. Also implied when `RETRAIN_THRESHOLD < 0`. | `false` |

    <Note>GPU-accelerated query is not yet supported by `cyborgdb-core`. Passing `query` in `GPU_OPERATIONS` is silently ignored.</Note>
  </Accordion>

  <Accordion title="Per-index KMS">
    Per-index KMS (BYOK) is configured exclusively via the YAML
    file's `kms.registry` block — see the
    [KMS / BYOK guide](./kms-byok). The related environment
    variable is documented above under **RBAC / Multi-Tenancy** (`INDEX_KEK_CACHE_TTL_SECONDS`).
  </Accordion>
</AccordionGroup>

## YAML Configuration File

Every setting above is also expressible in a YAML file. The file is
resolved in this order (first hit wins):

1. `CYBORGDB_CONFIG_FILE` environment variable
2. `./cyborgdb.yaml`, `./cyborgdb.yml`, `/etc/cyborgdb/cyborgdb.yaml`

A missing file is fine — the service falls back to env-only. An
explicit `CYBORGDB_CONFIG_FILE` path that doesn't exist is a hard
error.

```yaml cyborgdb.yaml theme={null}
service:
  port: 8000
  require_api_key: true
  cyborgdb_service_log_level: INFO

  # Optional: enable RBAC by setting a root API key. See ./multi-tenancy.
  # cyborgdb_service_root_key: ${CYBORGDB_SERVICE_ROOT_KEY}

  # Storage backend: memory | disk | s3 (default: disk)
  cyborgdb_db_type: disk
  # cyborgdb_disk_path: /var/lib/cyborgdb

  # S3 settings (when cyborgdb_db_type: s3)
  # cyborgdb_s3_bucket: my-bucket
  # cyborgdb_s3_region: us-east-1
  # cyborgdb_s3_endpoint: https://minio.internal:9000
  # cyborgdb_s3_access_key: ${MINIO_ACCESS_KEY}
  # cyborgdb_s3_secret_key: ${MINIO_SECRET_KEY}

  cpu_threads: 0
  index_kek_cache_ttl_seconds: 60

kms:
  registry:
    # See the KMS / BYOK guide for the full schema.
    # vendor-default:
    #   provider: aws-kms
    #   key_id:   alias/cyborgdb-default
    #   region:   us-east-1
```

**Precedence:** init args > environment variables > `.env` > YAML
file > file secrets.

**Env-var substitution.** Any string value in the YAML may reference
an environment variable as `${VAR}` (required — startup fails if
unset) or `${VAR:-default}` (uses `default` when unset). This lets
you keep BYOK role ARNs / account IDs out of the checked-in file. A
variable set to the empty string counts as **unset**.

## Configuration Examples

<AccordionGroup>
  <Accordion title="Quick start (disk, default)">
    ```bash theme={null}
    export CYBORGDB_API_KEY="cyborg_your_api_key_here"
    cyborgdb-service
    # Data goes to ~/.cyborgdb/data
    ```
  </Accordion>

  <Accordion title="In-memory (tests only)">
    ```bash theme={null}
    export CYBORGDB_API_KEY="cyborg_your_api_key_here"
    export CYBORGDB_DB_TYPE=memory
    cyborgdb-service
    ```
  </Accordion>

  <Accordion title="S3 on AWS with instance role">
    ```bash theme={null}
    export CYBORGDB_API_KEY="cyborg_your_api_key_here"
    export CYBORGDB_DB_TYPE=s3
    export CYBORGDB_S3_BUCKET=my-bucket
    export CYBORGDB_S3_REGION=us-east-1
    # No explicit credentials — instance role picked up automatically
    cyborgdb-service
    ```
  </Accordion>

  <Accordion title="S3 on MinIO with explicit credentials">
    ```bash theme={null}
    export CYBORGDB_API_KEY="cyborg_your_api_key_here"
    export CYBORGDB_DB_TYPE=s3
    export CYBORGDB_S3_BUCKET=my-bucket
    export CYBORGDB_S3_ENDPOINT=https://minio.internal:9000
    export CYBORGDB_S3_ACCESS_KEY=minioadmin
    export CYBORGDB_S3_SECRET_KEY=minioadmin
    cyborgdb-service
    ```
  </Accordion>

  <Accordion title="Production with HTTPS">
    ```bash theme={null}
    export CYBORGDB_API_KEY="cyborg_your_api_key_here"
    export CYBORGDB_DB_TYPE=s3
    export CYBORGDB_S3_BUCKET=cyborgdb-prod
    export CYBORGDB_S3_REGION=us-east-1
    export PORT=8443
    export SSL_CERT_PATH=/etc/ssl/certs/cyborgdb.crt
    export SSL_KEY_PATH=/etc/ssl/private/cyborgdb.key
    cyborgdb-service
    ```
  </Accordion>
</AccordionGroup>

### Docker

Pass any of the variables above to `docker run` with `-e`:

```bash theme={null}
docker run -p 8000:8000 \
  -e CYBORGDB_API_KEY="cyborg_your_api_key_here" \
  -e CYBORGDB_DB_TYPE=s3 \
  -e CYBORGDB_S3_BUCKET=my-bucket \
  -e CYBORGDB_S3_REGION=us-east-1 \
  cyborginc/cyborgdb-service:latest
```

Or use an `--env-file`:

```bash theme={null}
docker run -p 8000:8000 --env-file .env cyborginc/cyborgdb-service:latest
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Missing API key">
    Set `CYBORGDB_API_KEY`. Check for typos. Keys start with
    `cyborg_`.
  </Accordion>

  <Accordion title="`Invalid CYBORGDB_DB_TYPE`">
    v0.17 only accepts `memory`, `disk`, or `s3`. The legacy
    `standalone`, `postgres`, and `redis` values are gone. If
    you were on `standalone`, switch to `disk` and set
    `CYBORGDB_DISK_PATH` if you used a custom directory.
  </Accordion>

  <Accordion title="S3 startup fails with missing credentials">
    With `CYBORGDB_S3_ENDPOINT` set, the AWS default credential
    chain is bypassed entirely. Provide
    `CYBORGDB_S3_ACCESS_KEY` and `CYBORGDB_S3_SECRET_KEY`
    explicitly.
  </Accordion>

  <Accordion title="TLS not enabling">
    Both `SSL_CERT_PATH` and `SSL_KEY_PATH` must be set **and
    both files must exist on disk** before the service starts.
    Missing either falls back to HTTP silently.
  </Accordion>
</AccordionGroup>
