# How to Enable and Configure API Authentication in PrivateGPT: A Complete Guide

> Secure your PrivateGPT API by enabling and configuring authentication. Learn how to set up header validation and protect your routes with this comprehensive guide.

- Repository: [Zylon/private-gpt](https://github.com/zylon-ai/private-gpt)
- Tags: how-to-guide
- Published: 2026-03-06

---

**You can enable API authentication in PrivateGPT by setting `server.auth.enabled: true` and defining a secret in your [`settings.yaml`](https://github.com/zylon-ai/private-gpt/blob/main/settings.yaml) file, which activates a FastAPI dependency that validates the `Authorization` header on every protected route.**

PrivateGPT (zylon-ai/private-gpt) ships with a simple, optional HTTP-Basic-style authentication system that secures all FastAPI endpoints without requiring external identity providers. This mechanism is controlled through configuration files or environment variables and is implemented as a zero-overhead dependency that bypasses validation when disabled.

## Understanding the Authentication Architecture

### The AuthSettings Configuration Model

Authentication behavior is defined by the `AuthSettings` model in **[`private_gpt/settings/settings.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/settings/settings.py)**. This Pydantic model exposes two critical fields:

```python
class AuthSettings(BaseModel):
    enabled: bool = Field(
        description="Flag indicating if authentication is enabled or not.", 
        default=False
    )
    secret: str = Field(
        description="The secret to be used for authentication. It can be any non-blank string."
    )

```

The `enabled` field acts as a global toggle, while the `secret` field stores the exact string value expected in the HTTP **`Authorization`** header, including any scheme prefixes like `Bearer ` or `Basic `.

### The Authentication Dependency Implementation

In **[`private_gpt/server/utils/auth.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/server/utils/auth.py)**, PrivateGPT dynamically constructs the `authenticated` dependency based on runtime settings:

```python
if not settings().server.auth.enabled:
    def authenticated() -> bool:
        return True
else:
    def authenticated(
        _simple_authentication: Annotated[bool, Depends(_simple_authentication)]
    ) -> bool:
        assert settings().server.auth.enabled
        if not _simple_authentication:
            raise NOT_AUTHENTICATED
        return True

```

When **disabled**, the dependency returns `True` instantly, adding no latency to requests. When **enabled**, it delegates to `_simple_authentication`, which uses **`secrets.compare_digest`** to perform a constant-time comparison between the incoming `Authorization` header and the configured secret, raising a `401 Not authenticated` response on mismatch.

## Configuring API Authentication

### Method 1: YAML Configuration Files

The most common approach is modifying the settings profile. Edit your active YAML file (default **[`settings.yaml`](https://github.com/zylon-ai/private-gpt/blob/main/settings.yaml)** or a custom profile like [`settings-prod.yaml`](https://github.com/zylon-ai/private-gpt/blob/main/settings-prod.yaml)) to add the `server.auth` block:

```yaml
server:
  env_name: prod
  auth:
    enabled: true
    secret: "Bearer my-secret-token-12345"

```

You can place this configuration in any profile file loaded by **[`private_gpt/settings/settings_loader.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/settings/settings_loader.py)**. The loader merges these YAML profiles into the live `Settings` object accessed via `settings().server.auth`.

### Method 2: Environment Variables

For containerized deployments or secrets management systems, override the configuration using environment variables:

```bash
export PGPT_SETTINGS_FOLDER=/path/to/custom/settings
export PGPT_PROFILES=prod

```

Place a [`settings-prod.yaml`](https://github.com/zylon-ai/private-gpt/blob/main/settings-prod.yaml) containing the authentication block in the specified folder, or override the entire configuration structure through the settings loader's environment-based overrides.

## Securing API Routes

All protected endpoints in PrivateGPT import the `authenticated` dependency from **[`private_gpt/server/utils/auth.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/server/utils/auth.py)** and declare it in their router definitions:

```python
from fastapi import APIRouter, Depends
from private_gpt.server.utils.auth import authenticated

router = APIRouter()

@router.get("/health", dependencies=[Depends(authenticated)])
def health_check():
    return {"status": "healthy"}

```

This pattern ensures that when authentication is enabled, FastAPI rejects any request missing the valid `Authorization` header before reaching the endpoint logic.

## Testing Authenticated Requests

Once enabled, every API request must include the exact authorization string configured in your settings file:

```bash
curl -H "Authorization: Bearer my-secret-token-12345" \
     http://localhost:8001/health

```

Requests without the header or with an incorrect secret receive a `401 Unauthorized` response:

```json
{
  "detail": "Not authenticated"
}

```

## Summary

- **Authentication is opt-in** via the `enabled` field in `AuthSettings` (default `False`).
- **Configuration lives in YAML profiles** processed by [`settings_loader.py`](https://github.com/zylon-ai/private-gpt/blob/main/settings_loader.py), with support for environment variable overrides through `PGPT_SETTINGS_FOLDER`.
- **Security is enforced by the `authenticated` dependency** in [`private_gpt/server/utils/auth.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/server/utils/auth.py), which uses constant-time string comparison via `secrets.compare_digest`.
- **All routes requiring protection** must explicitly declare `dependencies=[Depends(authenticated)]` in their FastAPI router definitions.
- **The secret supports any string format**, allowing you to implement Bearer tokens, Basic auth, or custom schemes.

## Frequently Asked Questions

### Where is the authentication secret configured in PrivateGPT?

The secret is defined in the `server.auth.secret` field of your active settings YAML file (e.g., [`settings.yaml`](https://github.com/zylon-ai/private-gpt/blob/main/settings.yaml)), as specified by the `AuthSettings` model in [`private_gpt/settings/settings.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/settings/settings.py). You can also manage this through the `PGPT_SETTINGS_FOLDER` environment variable to load custom profiles containing the authentication configuration.

### What happens if authentication is disabled in PrivateGPT?

When `server.auth.enabled` is set to `false` (the default), the `authenticated` dependency in [`private_gpt/server/utils/auth.py`](https://github.com/zylon-ai/private-gpt/blob/main/private_gpt/server/utils/auth.py) resolves to a dummy function that immediately returns `True`. This design ensures zero performance overhead and allows all requests to pass through without header validation.

### How do I send authenticated requests to the PrivateGPT API?

You must include an `Authorization` HTTP header with a value exactly matching your configured secret. For example, if your [`settings.yaml`](https://github.com/zylon-ai/private-gpt/blob/main/settings.yaml) contains `secret: "Bearer my-token"`, your requests must include `-H "Authorization: Bearer my-token"`. The comparison is case-sensitive and performed using `secrets.compare_digest` to prevent timing attacks.

### Can I use HTTP Basic Authentication with PrivateGPT?

Yes. While PrivateGPT implements a simple secret-matching mechanism rather than full RFC 7617 Basic auth parsing, you can simulate HTTP Basic Authentication by setting your `secret` field to the complete expected header value, such as `"Basic dXNlcjpsw2Fzcw=="` (the Base64-encoded credentials). The system performs an exact string match against the incoming `Authorization` header, making it compatible with any scheme that sends static credentials in that header.