How to Enable and Configure API Authentication in PrivateGPT: A Complete Guide
You can enable API authentication in PrivateGPT by setting server.auth.enabled: true and defining a secret in your 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. This Pydantic model exposes two critical fields:
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, PrivateGPT dynamically constructs the authenticated dependency based on runtime settings:
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 or a custom profile like settings-prod.yaml) to add the server.auth block:
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. 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:
export PGPT_SETTINGS_FOLDER=/path/to/custom/settings
export PGPT_PROFILES=prod
Place a 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 and declare it in their router definitions:
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:
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:
{
"detail": "Not authenticated"
}
Summary
- Authentication is opt-in via the
enabledfield inAuthSettings(defaultFalse). - Configuration lives in YAML profiles processed by
settings_loader.py, with support for environment variable overrides throughPGPT_SETTINGS_FOLDER. - Security is enforced by the
authenticateddependency inprivate_gpt/server/utils/auth.py, which uses constant-time string comparison viasecrets.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), as specified by the AuthSettings model in 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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →