Configuration
Pia Server uses standard ASP.NET Core configuration: layered sources with environment variables overriding appsettings.json. Sensitive values (secrets, master key) must come from environment variables in production.
Source order (lowest precedence first)
Section titled “Source order (lowest precedence first)”appsettings.jsonappsettings.{Environment}.json(e.g.appsettings.Production.json)- Environment variables
- Command-line arguments
Sections
Section titled “Sections”Database
Section titled “Database”| Key | Env | Purpose |
|---|---|---|
Database:Provider | Database__Provider | sqlite (default in dev) or postgresql |
Database:ConnectionString | Database__ConnectionString | EF Core connection string for the chosen provider |
PostgreSQL example:
Host=postgres;Database=pia;Username=pia;Password=<db-password>Migrations are applied automatically on startup.
| Key | Env | Purpose |
|---|---|---|
Jwt:SecretKey | JWT_SECRET_KEY | HMAC signing key, ≥ 32 chars |
Jwt:Issuer | — | Default pia-server |
Jwt:Audience | — | Default pia-client |
Jwt:AccessTokenLifetime | — | Default 15 minutes |
Jwt:RefreshTokenLifetime | — | Default 30 days |
{ "OAuth": { "Google": { "ClientId": "...", "ClientSecret": "..." }, "Microsoft": { "ClientId": "...", "ClientSecret": "..." } }}In production, prefer environment variables: OAUTH_GOOGLE_CLIENT_ID / _SECRET, OAUTH_MICROSOFT_CLIENT_ID / _SECRET. See Microsoft Entra ID OAuth for the full Entra setup.
Encryption
Section titled “Encryption”| Key | Env | Purpose |
|---|---|---|
Encryption:MasterKey | ENCRYPTION_MASTER_KEY | 64 hex chars (32 bytes) — used to derive per-user keys via HKDF |
The default upstream AI provider, plus optional per-mode overrides selected by the X-Pia-Mode header.
| Key | Env | Purpose |
|---|---|---|
Ai:Provider | AI_PROVIDER | openai, azure, anthropic, mistral, … |
Ai:ApiKey | AI_API_KEY | Upstream API key |
Ai:Model | AI_MODEL | e.g. gpt-4o-mini |
Ai:Endpoint | AI_ENDPOINT | Upstream base URL |
Per-mode overrides:
| Variable | Mode |
|---|---|
AI_ASSISTANT_PROVIDER / _API_KEY / _MODEL / _ENDPOINT | Assistant |
AI_RESEARCH_PROVIDER / _API_KEY / _MODEL / _ENDPOINT | Research |
(default Ai:*) | Optimize |
If a mode override isn’t set, the default provider is used.
Knowledge, Embeddings, Chunking (knowledge base)
Section titled “Knowledge, Embeddings, Chunking (knowledge base)”The knowledge base requires both the Knowledge license feature and
Knowledge:ConnectionString set — miss either and it stays off. See
Admin → Knowledge bases for the full setup flow and
Architecture → Knowledge base for how it works.
| Key | Env | Purpose |
|---|---|---|
Knowledge:ConnectionString | Knowledge__ConnectionString | pgvector DB connection — enables the KB when set |
Knowledge:IngestApiKey | Knowledge__IngestApiKey | Instance-wide REST ingest key (X-Pia-Service-Key); empty disables the REST API |
Embeddings:ProviderId | Embeddings__ProviderId | An Ai:Providers[].Id resolving the embedding endpoint/key |
Embeddings:Model | Embeddings__Model | Embedding model (default bge-m3) |
Embeddings:Dimension | Embeddings__Dimension | Must equal the compiled schema (1024); mismatch disables the KB |
Embeddings:TimeoutSeconds | Embeddings__TimeoutSeconds | Ingestion upstream timeout (default 100) |
Chunking:Context:Enabled | Chunking__Context__Enabled | Contextual retrieval, on by default (auto-disabled if no provider) |
Chunking:Context:ProviderId | Chunking__Context__ProviderId | An Ai:Providers[].Id of a chat model for per-chunk context |
Chunking:* | Chunking__* | Semantic double-pass splitter knobs (buffer size, thresholds, chunk-size bounds) |
Per-group quotas (KnowledgeBases, KnowledgeDocuments, KnowledgeStorageBytes,
MonthlyEmbeddingTokens) live in GroupSettings.Quotas and are edited in the
group editor, not in config.
License
Section titled “License”| Key | Purpose |
|---|---|
License:Path | Path to the licence XML (default licence.xml next to the binary) |
See Licensing for how licences are issued.
Environment variable summary
Section titled “Environment variable summary”The keys most commonly set in production:
| Required | Variable |
|---|---|
| ✓ | ASPNETCORE_ENVIRONMENT (Production) |
| ✓ | Database__Provider and Database__ConnectionString |
| ✓ | JWT_SECRET_KEY |
| ✓ | ENCRYPTION_MASTER_KEY |
| ✓ (Postgres) | POSTGRES_PASSWORD (must match the password embedded in the connection string) |
| optional | AI_* |
| optional | OAUTH_*_CLIENT_ID / _SECRET |
| optional | Knowledge__ConnectionString + Embeddings__ProviderId (enable the knowledge base) |
appsettings.json is committed; .env.prod is not (and should be chmod 600).
Restart vs hot-reload
Section titled “Restart vs hot-reload”Most operator-tunable settings are read via IOptionsMonitor<T> and re-bind on file change — for example, rate limit and quota policies on the /admin/limits page apply immediately.
These settings only take effect after a restart:
Database:ProviderandConnectionStringJwt:SecretKey(changing it invalidates all outstanding tokens)Encryption:MasterKey(changing it strands all existing ciphertext — see Encryption at rest)
The admin UI surfaces a banner when a change requires a restart, with a Restart button that delegates to RestartCapability. In environments where a process restart isn’t safe (e.g. a single-replica deployment without a supervising orchestrator), the capability is no-op and the operator must restart the container manually.