# How to Configure API Key Authentication for oMLX Server: Complete Setup Guide

> Learn how to configure API key authentication for oMLX server. Secure your server using CLI flags environment variables or the Admin UI with this simple setup guide.

- Repository: [Jun Kim/omlx](https://github.com/jundot/omlx)
- Tags: how-to-guide
- Published: 2026-05-11

---

**To configure API key authentication for the oMLX server, supply a key via the `--api-key` CLI flag, set the `OMLX_API_KEY` environment variable, or configure it through the Admin UI, which stores the credential in [`settings.json`](https://github.com/jundot/omlx/blob/main/settings.json) and caches it in the global `_server_state.api_key` for request validation.**

The **jundot/omlx** repository provides optional API-key authentication to protect its OpenAI-compatible endpoints. This security layer ensures that only authorized clients can access the `/v1/*` routes while offering flexible configuration methods through command-line arguments, environment variables, or the web-based administration panel.

## Understanding the Authentication Architecture

The oMLX server implements a three-component authentication system that validates requests against a stored secret before processing OpenAI-compatible API calls.

### Server State Storage

When the server initializes, the API key persists in two locations: the [`settings.json`](https://github.com/jundot/omlx/blob/main/settings.json) configuration file and the runtime `_server_state` object. In [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py), the `init_server` function receives the key from CLI arguments or environment variables and assigns it to the global state:

```python

# omlx/server.py – initialise server

# https://github.com/jundot/omlx/blob/main/omlx/server.py#L1075-L1081

_server_state.api_key = api_key
_server_state.global_settings = global_settings

```

This dual storage ensures that the key survives server restarts (via [`settings.json`](https://github.com/jundot/omlx/blob/main/settings.json)) while remaining accessible for fast runtime comparisons through the in-memory cache.

### Request Verification Flow

Every OpenAI-compatible endpoint includes the `Depends(verify_api_key)` dependency, which intercepts incoming requests before they reach the handler. The `verify_api_key` function in [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py) (lines 51-92) extracts tokens from the `Authorization: Bearer` header or the `x-api-key` header for Anthropic compatibility:

```python

# omlx/server.py – verify_api_key()

# https://github.com/jundot/omlx/blob/main/omlx/server.py#L51-L92

async def verify_api_key(request, credentials=Depends(security)) -> bool:
    if _server_state.api_key is None:          # no key → no auth required

        return True
    ...
    if not verify_any_api_key(api_key_value,
                              _server_state.api_key,
                              sub_keys):
        raise HTTPException(status_code=401, detail="Invalid API key")

```

The system uses **constant-time comparison** via `secrets.compare_digest` in [`omlx/admin/auth.py`](https://github.com/jundot/omlx/blob/main/omlx/admin/auth.py) (lines 36-58) to prevent timing attacks during validation.

### Admin Management Interface

The **Admin UI** and CLI tools provide interfaces for key rotation and initial setup. Administrative endpoints in [`omlx/admin/routes.py`](https://github.com/jundot/omlx/blob/main/omlx/admin/routes.py) update both the persistent configuration and the runtime state simultaneously, allowing key changes without server restarts.

## Methods to Configure the API Key

You can enable authentication through three primary methods, depending on your deployment environment and security requirements.

### Command Line Interface

Pass the key directly when starting the server using the `--api-key` flag. The argument parser in [`omlx/cli.py`](https://github.com/jundot/omlx/blob/main/omlx/cli.py) forwards this value to `init_server`:

```bash

# Start with a 32-character key (example only – do not use this key in production)

omlx serve \
  --model-dir /path/to/models \
  --max-model-memory 32GB \
  --api-key mySuperSecretKey1234

```

### Environment Variables

Set the `OMLX_API_KEY` environment variable before launching the server. The CLI automatically detects this variable and passes it to the initialization function:

```bash
export OMLX_API_KEY=mySuperSecretKey1234
omlx serve --model-dir /path/to/models

```

### Admin Web Interface

For interactive configuration or key rotation, use the built-in admin panel:

1. Navigate to `http://localhost:8000/admin` in your browser.
2. Select **"API Key"** → **"Setup"** for initial configuration or **"Change"** for rotation.
3. Enter the new key twice and click **Save**.

The backend validates the input using `validate_api_key` in [`omlx/admin/auth.py`](https://github.com/jundot/omlx/blob/main/omlx/admin/auth.py) (lines 62-82), which enforces minimum length (4 characters), prohibits whitespace, and ensures printable ASCII characters. Upon validation, the system updates both `global_settings.auth.api_key` and `_server_state.api_key` instantly.

## Making Authenticated Requests

Once authentication is enabled, clients must include the key in every request to `/v1/*` endpoints. The server accepts two header formats:

```bash
curl -X POST http://localhost:8000/v1/chat/completions \
     -H "Authorization: Bearer mySuperSecretKey1234" \
     -H "Content-Type: application/json" \
     -d '{"model":"llama-3b","messages":[{"role":"user","content":"Hello"}]}'

```

Alternatively, use the Anthropic-compatible `x-api-key` header. If authentication fails, the server returns a standard OpenAI-format error:

```json
{
  "error": {
    "message": "Invalid API key",
    "type": "authentication_error",
    "param": null,
    "code": null
  }
}

```

## Disabling Authentication

To run the server without authentication—useful for local development or isolated networks—simply omit the `--api-key` flag and the `OMLX_API_KEY` environment variable. When `_server_state.api_key` remains `None`, the `verify_api_key` dependency short-circuits and allows all requests:

```bash
omlx serve --model-dir /path/to/models

```

This configuration makes all `/v1/*` endpoints publicly accessible.

## Summary

- **Storage mechanism**: The API key persists in [`settings.json`](https://github.com/jundot/omlx/blob/main/settings.json) and the global `_server_state.api_key` variable defined in [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py).
- **Configuration methods**: Supply credentials via `--api-key` CLI flag, `OMLX_API_KEY` environment variable, or the Admin UI at `/admin/api/key/setup`.
- **Request validation**: The `verify_api_key` dependency in [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py) (lines 51-92) enforces authentication on all OpenAI-compatible endpoints using constant-time comparison.
- **Runtime updates**: Change keys through the Admin UI without restarting the server; updates apply immediately to `global_settings` and `_server_state`.
- **Disabling auth**: Start the server without providing any key to disable authentication entirely.

## Frequently Asked Questions

### How does oMLX store the API key securely?

The oMLX server stores the API key in the [`settings.json`](https://github.com/jundot/omlx/blob/main/settings.json) configuration file for persistence and caches it in the runtime `_server_state.api_key` variable for fast access. According to the source code in [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py) (lines 1075-1081), the key is written to both locations during initialization, ensuring that verification happens in-memory while configuration survives restarts.

### Can I rotate the API key without restarting the server?

Yes. The Admin UI provides endpoints to update the key at runtime. When you change the key through `/admin/api/key/change`, the system updates `global_settings.auth.api_key` and `_server_state.api_key` simultaneously, as implemented in [`omlx/admin/routes.py`](https://github.com/jundot/omlx/blob/main/omlx/admin/routes.py). New requests immediately use the updated credential without requiring a server restart.

### What happens if I provide the wrong API key in a request?

The server returns a 401 Unauthorized response with an OpenAI-compatible error format. The `verify_api_key` function in [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py) (lines 88-90) raises an `HTTPException` with the detail "Invalid API key" when the provided token fails validation against `verify_any_api_key` in [`omlx/admin/auth.py`](https://github.com/jundot/omlx/blob/main/omlx/admin/auth.py).

### Does oMLX support the Anthropic x-api-key header format?

Yes. The `verify_api_key` function extracts tokens from both the standard `Authorization: Bearer` header and the `x-api-key` header for compatibility with Anthropic client libraries. This dual-header support is implemented in [`omlx/server.py`](https://github.com/jundot/omlx/blob/main/omlx/server.py) (lines 73-80) to accommodate different API client configurations.