LocalAI supports two authentication modes: **legacy API key authentication** (simple shared keys) and a full **user authentication system** with roles, sessions, OAuth, and per-user usage tracking.
## Legacy API Key Authentication
The simplest way to protect your LocalAI instance is with API keys. Set one or more keys via environment variable or CLI flag:
```bash
# Single key
LOCALAI_API_KEY=sk-my-secret-key localai run
# Multiple keys (comma-separated)
LOCALAI_API_KEY=key1,key2,key3 localai run
```
Clients provide the key via any of these methods:
-`Authorization: Bearer <key>` header
-`x-api-key: <key>` header
-`xi-api-key: <key>` header
-`token` cookie
Legacy API keys grant **full admin access** — there is no role separation. For multi-user deployments with role-based access, use the user authentication system instead.
API keys can also be managed at runtime through the [Runtime Settings]({{%relref "features/runtime-settings" %}}) interface.
## User Authentication System
The user authentication system provides:
- **User accounts** with email, name, and avatar
- **Role-based access control** (admin vs. user)
- **Session-based authentication** with secure cookies
- **OAuth login** (GitHub) and **OIDC single sign-on** (Keycloak, Google, Okta, Authentik, etc.)
- **Per-user API keys** for programmatic access
- **Admin route gating** — management endpoints are restricted to admins
- **Per-user usage tracking** with token consumption metrics
### Enabling Authentication
Set `LOCALAI_AUTH=true` or provide a GitHub OAuth Client ID or OIDC Client ID (which auto-enables auth):
```bash
# Enable with SQLite (default, stored at {DataPath}/database.db)
| `LOCALAI_DISABLE_LOCAL_AUTH` | `false` | Disable local email/password registration and login (for OAuth/OIDC-only deployments) |
### Disabling Local Authentication
If you want to enforce OAuth/OIDC-only login and prevent users from registering or logging in with email/password, set `LOCALAI_DISABLE_LOCAL_AUTH=true` (or pass `--disable-local-auth`):
```bash
# OAuth-only setup (no email/password)
LOCALAI_DISABLE_LOCAL_AUTH=true \
GITHUB_CLIENT_ID=your-client-id \
GITHUB_CLIENT_SECRET=your-client-secret \
LOCALAI_BASE_URL=http://localhost:8080 \
localai run
```
When disabled:
- The login page will not show email/password forms (the UI checks the `providers` list from `/api/auth/status`)
- **Admin**: Full access to all endpoints, including model management, backend configuration, system settings, traces, agents, and user management.
- **User**: Access to inference endpoints only — chat completions, embeddings, image/video/audio generation, TTS, MCP chat, and their own usage statistics.
The **first user** to sign in is automatically assigned the admin role. Additional users can be promoted to admin via the admin user management API or by setting `LOCALAI_ADMIN_EMAIL` to their email address.
### Registration Modes
| Mode | Description |
|---|---|
| `open` | Anyone can register and is immediately active |
| `approval` | New users land in "pending" status until an admin approves them. If a valid invite code is provided during registration, the user is activated immediately (skipping the approval wait). **(default)** |
| `invite` | Registration requires a valid invite link generated by an admin. Without one, registration is rejected. |
### Invite Links
Admins can generate single-use, time-limited invite links from the **Users → Invites** tab in the web UI, or via the API:
```bash
# Create an invite link (default: expires in 7 days)
curl -X POST http://localhost:8080/api/auth/admin/invites \
Share the invite URL (`/invite/<code>`) with the user. When they open it, the registration form is pre-filled with the invite code. Invite codes are single-use — once consumed, they cannot be reused. Expired or used invites are rejected.
For GitHub OAuth, the invite code is passed as a query parameter to the login URL (`/api/auth/github/login?invite_code=<code>`) and stored in a cookie during the OAuth flow.
### Admin-Only Endpoints
When authentication is enabled, the following endpoints require admin role:
For OIDC, invite codes work the same way as GitHub OAuth — the invite code is passed as a query parameter to the login URL (`/api/auth/oidc/login?invite_code=<code>`) and stored in a cookie during the OAuth flow.
### User API Keys
Authenticated users can create personal API keys for programmatic access:
```bash
# Create an API key (requires session auth)
curl -X POST http://localhost:8080/api/auth/api-keys \
-H "Cookie: session=<session-id>" \
-H "Content-Type: application/json" \
-d '{"name": "My Script Key"}'
```
User API keys inherit the creating user's role. Admin keys grant admin access; user keys grant user-level access.
-`month` — last 30 days, bucketed by day (default)
-`all` — all time, bucketed by month
**Response format:**
```json
{
"usage": [
{
"bucket": "2026-03-18",
"model": "gpt-4",
"user_id": "abc-123",
"user_name": "Alice",
"prompt_tokens": 1500,
"completion_tokens": 800,
"total_tokens": 2300,
"request_count": 12
}
],
"totals": {
"prompt_tokens": 1500,
"completion_tokens": 800,
"total_tokens": 2300,
"request_count": 12
}
}
```
### Usage Dashboard
The web UI Usage page provides:
- **Period selector** — switch between day, week, month, and all-time views
- **Summary cards** — total requests, prompt tokens, completion tokens, total tokens
- **By Model table** — per-model breakdown with visual usage bars
- **By User table** (admin only) — per-user breakdown across all models
## Combining Auth Modes
Legacy API keys and user authentication can be used simultaneously. When both are configured:
1. User sessions and user API keys are checked first
2. Legacy API keys are checked as fallback — they grant **admin-level access**
3. This allows a gradual migration from shared API keys to per-user accounts
## Build Requirements
The user authentication system requires CGO for SQLite support. It is enabled with the `auth` build tag, which is included by default in Docker builds.
```bash
# Building from source with auth support
GO_TAGS=auth make build
# Or directly with go build
go build -tags auth ./...
```
The default Dockerfile includes `GO_TAGS="auth"`, so all Docker images ship with auth support. When building from source without the `auth` tag, setting `LOCALAI_AUTH=true` has no effect — the system operates without authentication.