Skip to content

Server Configuration

The MCP server supports configuration through a YAML file, command-line flags, and environment variables.

Configuration Priority

The server applies configuration values in the following order from highest to lowest priority:

  1. Command-line flags (highest priority).
  2. Environment variables.
  3. Configuration file.
  4. Built-in defaults (lowest priority).

Configuration File

File Locations

The server searches for its configuration file in the following order:

  1. The path specified via the -config flag.
  2. The per-user config directory at ~/.config/pgedge/ai-dba-server.yaml on Linux (honouring $XDG_CONFIG_HOME), ~/Library/Application Support/pgedge/ai-dba-server.yaml on macOS, and %AppData%\pgedge\ai-dba-server.yaml on Windows.
  3. /etc/pgedge/ai-dba-server.yaml (system-wide).

If -config is set and the file is missing, the server exits with an error. If -config is not set and none of the default locations contain a configuration file, the server uses built-in defaults silently. The server no longer searches the binary directory or the current working directory. The same search paths apply to secret_file discovery for ai-dba-server.secret; however, secret discovery is not silent. If no secret_file is set in the YAML and no ai-dba-server.secret file is present at any search path, the server exits with an error at startup.

Example Configuration

A complete example configuration file is available at examples/ai-dba-server.yaml in the project repository.

#=====================================================
# HTTP SERVER CONFIGURATION
#=====================================================
http:
  # Address to listen on (host:port or :port)
  address: ":8080"

  # TLS/HTTPS Configuration
  tls:
    enabled: false
    # cert_file: "/etc/ai-workbench/certs/cert.pem"
    # key_file: "/etc/ai-workbench/certs/key.pem"
    # chain_file: "/etc/ai-workbench/certs/chain.pem"

  # Trusted reverse proxies (CIDR ranges)
  # trusted_proxies:
  #   - "10.0.0.0/8"
  #   - "172.16.0.0/12"

  # CORS origin for cross-origin deployments
  # cors_origin: "https://workbench.example.com"

  # Authentication Configuration
  auth:
    max_failed_attempts_before_lockout: 10
    max_user_token_days: 0
    rate_limit_window_minutes: 15
    rate_limit_max_attempts: 10
    # Local username and password login
    local:
      enabled: true
    # Federated (OpenID Connect) login
    # oidc:
    #   enabled: true
    #   issuer: "https://idp.example.com"
    #   client_id: "pgedge-workbench"
    #   client_secret_file: "/etc/pgedge/oidc-client-secret.txt"
    #   redirect_url: "https://workbench.example.com/api/v1/auth/oidc/callback"
    audit_retention_days: 90

#=====================================================
# CONNECTION SECURITY
#=====================================================
connection_security:
  allow_internal_networks: false
  # allowed_hosts:
  #   - "db.example.com"
  #   - "192.168.1.0/24"
  # blocked_hosts:
  #   - "169.254.169.254"
  # ssl_cert_dir: "/etc/pgedge/ai-dba-workbench/certs"

#=====================================================
# DATABASE CONNECTION
#=====================================================
database:
  host: "localhost"
  port: 5432
  database: "ai_workbench"
  user: "postgres"
  # password: ""
  # password_file: "/etc/pgedge/password.txt"
  sslmode: "prefer"
  pool_max_conns: 20
  pool_min_conns: 0
  pool_max_conn_idle_time: "30m"
  statement_timeout: "30s"

#=====================================================
# EMBEDDING GENERATION
#=====================================================
embedding:
  enabled: false
  provider: "ollama"
  model: "nomic-embed-text"
  ollama_url: "http://localhost:11434"
  # voyage_api_key_file: "~/.voyage-api-key"
  # openai_api_key_file: "~/.openai-api-key"
  # gemini_api_key_file: "~/.gemini-api-key"

#=====================================================
# LLM CONFIGURATION (Chat Proxy and AI Analysis)
#=====================================================
llm:
  provider: "anthropic"
  model: "claude-sonnet-5"
  # anthropic_api_key_file: "~/.anthropic-api-key"
  # openai_api_key_file: "~/.openai-api-key"
  # gemini_api_key_file: "~/.gemini-api-key"
  ollama_url: "http://localhost:11434"
  max_tokens: 4096
  temperature: 0.7
  max_iterations: 50
  compact_tool_descriptions: "auto"
  # reasoning_effort: "medium"
  # prompt_caching: "auto"
  # extra_body: {}

#=====================================================
# KNOWLEDGEBASE CONFIGURATION
#=====================================================
knowledgebase:
  enabled: false
  # database_path: "/usr/share/pgedge/pgedge-ai-kb/kb-ollama-nomic-embed-text.db"
  embedding_provider: "ollama"
  embedding_model: "nomic-embed-text"
  embedding_ollama_url: "http://localhost:11434"

#=====================================================
# CHAT MEMORY CONFIGURATION
#=====================================================
memory:
  enabled: true

#=====================================================
# BUILT-IN TOOLS, RESOURCES, AND PROMPTS
#=====================================================
builtins:
  tools:
    query_database: true
    get_schema_info: true
    similarity_search: true
    execute_explain: true
    count_rows: true
    list_probes: true
    describe_probe: true
    query_metrics: true
    list_connections: true
    get_alert_history: true
    get_alert_rules: true
    get_metric_baselines: true
    get_blackouts: true
    get_timeline_events: true
    query_datastore: true
    describe_datastore: true
    generate_embedding: true
    search_knowledgebase: true
    store_memory: true
    recall_memories: true
    delete_memory: true
  resources:
    system_info: true
    connection_info: true

#=====================================================
# PATHS AND DATA DIRECTORIES
#=====================================================
# secret_file: "/etc/ai-workbench/server.secret"
# custom_definitions_path: "/etc/ai-workbench/defs.yaml"
# data_dir: "/var/lib/ai-workbench/data"

Command-Line Flags

General Options

Flag Description
-config string Path to configuration file
-check-config Validate the configuration file, then exit without starting the server; see Upgrading the Workbench
-debug Enable debug logging
-data-dir string Data directory for auth and conversations
-health-check host:port Check that a TCP listener accepts connections at the given address, then exit with status 0, or 1 if it does not; the example Docker Compose files use it as the server health check
-trace-file string Path to MCP trace file

HTTP Server Options

Flag Description
-addr string HTTP address (default: :8080)
-tls Enable TLS/HTTPS
-cert string Path to TLS certificate file
-key string Path to TLS key file
-chain string Path to TLS certificate chain

Database Connection Options

Flag Description
-db-host string Database host
-db-port int Database port
-db-name string Database name
-db-user string Database user
-db-password string Database password
-db-password-file string Path to DB password file, read at start-up only; overrides the configured password
-db-sslmode string SSL mode

Connection Security Options

The following table describes the flag that sets the connection security options:

Flag Description
-connection-ssl-cert-dir string Absolute path of the directory that monitored connections' SSL certificate, key and root certificate files must be in; sets connection_security.ssl_cert_dir, and an empty value clears a directory set in the configuration file

Token Management Options

Flag Description
-add-token Add a new service token
-remove-token string Remove token by ID or hash
-list-tokens List all service tokens
-token-note string Annotation for new token
-token-expiry string Token expiry duration
-user string Owner username for the token

User Management Options

Flag Description
-add-user Add a new user
-update-user Update an existing user
-delete-user Delete a user
-list-users List all users
-enable-user Enable a user account
-disable-user Disable a user account
-add-service-account Add a service account
-username string Username for user commands
-password string Password for user commands
-full-name string Full name for the user
-email string Email address for the user
-user-note string Annotation for new user

Group Management Options

Flag Description
-add-group Add a new RBAC group
-delete-group Delete an RBAC group
-list-groups List all RBAC groups
-list-members List the members of a group
-add-member Add a user or group to a group
-remove-member Remove a member from a group
-group string Group name for group commands
-group-description string Group description for add-group
-member-group string Member group for nesting
-set-superuser Set superuser status
-unset-superuser Remove superuser status

Privilege Management Options

Flag Description
-grant-privilege Grant an MCP privilege
-revoke-privilege Revoke an MCP privilege
-grant-connection Grant connection access
-revoke-connection Revoke connection access
-list-privileges List MCP privileges
-show-group-privileges Show group privileges
-register-privilege Register a new privilege
-privilege string MCP privilege identifier
-privilege-type string Privilege type
-privilege-description string Description
-connection int Connection ID
-access-level string Access level (default: read)

Token Scope Options

Flag Description
-scope-token-connections Set connection scope
-scope-token-tools Set MCP tool scope
-clear-token-scope Clear all scope restrictions
-show-token-scope Show current token scope
-token-id int Token ID for scope commands
-scope-connections string Connection ID list
-scope-tools string Tool name list

Audit Log Options

The audit log records every change to users, groups, tokens and privileges; the Audit Log document describes the events and how to read them. The following table describes the flags that read and verify the log, along with -rechain-audit-log, which either re-hashes an inherited log or re-anchors one that no longer verifies; a re-anchor leaves the existing events as they are and appends an anchor event:

Flag Description
-list-audit List RBAC audit log events
-verify-audit-log Verify the audit log hash chain
-rechain-audit-log Re-hash an inherited audit log, or re-anchor one that no longer verifies
-confirm-rechain Confirm -rechain-audit-log without an interactive prompt
-previous-secret-file string Secret file the older audit events were written under, needed by -confirm-rechain to re-anchor them
-audit-actor string Filter events by actor name
-audit-action string Filter events by action
-audit-target-type string Filter events by target type
-audit-target-id int Filter events by target ID
-audit-outcome string Filter events by outcome
-audit-since string Earliest event time to show
-audit-until string Latest event time to show
-audit-limit int Maximum events to show (default: 50)
-json Emit output as one JSON object per line

Configuration Sections

HTTP Server (http)

Option Type Default Description
address string :8080 Listen address
tls.enabled bool false Enable TLS
tls.cert_file string Certificate file
tls.key_file string Private key file
tls.chain_file string Certificate chain
trusted_proxies list [] Trusted proxy CIDRs; required behind a reverse proxy when OIDC login is enabled
cors_origin string "" Allowed CORS origin
hsts_enabled bool false Send the Strict-Transport-Security header
auth.max_failed_attempts_before_lockout int 10 Lock after N failures (0 disables); restart required
auth.max_user_token_days int 0 Max token lifetime
auth.rate_limit_window_minutes int 15 Rate limit window
auth.rate_limit_max_attempts int 10 Max attempts per window
auth.local.enabled bool true Enable username and password login
auth.oidc.enabled bool false Enable federated login
auth.oidc.issuer string Identity provider issuer URL
auth.oidc.client_id string OAuth 2.0 client identifier
auth.oidc.client_secret string Inline client secret
auth.oidc.client_secret_file string File holding the client secret
auth.oidc.redirect_url string Callback URL registered at the provider
auth.oidc.scopes list [openid, email, profile] Scopes requested at the provider
auth.oidc.username_claim string email Claim used as the username
auth.oidc.display_name_claim string name Claim used as the display name
auth.oidc.groups_claim string groups Claim carrying group membership
auth.oidc.button_label string Sign in with your identity provider Federated login button label
auth.oidc.provision_users bool false Create an account on first login
auth.oidc.allowed_email_domains list [] Permitted verified email domains
auth.oidc.superuser_group string Provider group granting superuser
auth.oidc.group_map map {} Provider group to Workbench group map
auth.oidc.allow_unprefixed_state_cookie bool false Accept an unprefixed login state cookie behind a proxy
auth.oidc.allow_api_tokens bool false Let federated users own API tokens
auth.oidc.auth_params map {} Extra authorisation request parameters

Authentication (auth)

The auth section governs both login methods. Local username and password login is on unless auth.local.enabled is set to false, and federated login is off unless auth.oidc.enabled is set to true. The server refuses to start when neither method is available.

While federated login is disabled, the server ignores every auth.oidc.* option except auth_params, which it still validates, and allow_api_tokens, which still applies to accounts linked to a provider earlier. The Single Sign-On guide describes each option in full, along with registering the Workbench at an identity provider and mapping provider groups onto Workbench groups.

The server also refuses to start with federated login enabled, an https auth.oidc.redirect_url, tls.enabled set to false and an empty trusted_proxies list. On that deployment the login state cookie cannot use the __Host- name prefix, so a sibling subdomain that can set cookies can log users in as an attacker. Set trusted_proxies to the reverse proxy's address, or set auth.oidc.allow_unprefixed_state_cookie to true to accept the risk.

The server likewise refuses to start, whether or not federated login is enabled, when auth.oidc.auth_params names a parameter the Workbench sets itself, such as state or redirect_uri; the Single Sign-On guide lists them, and gives the Google example that needs access_type: offline.

| auth.audit_retention_days | int | 90 | Days to keep RBAC audit events (0 keeps forever) |

Warning

While auth.oidc.allow_api_tokens is false, the default, an account that signs in through the identity provider cannot create API tokens, and any token such an account already owns is refused on use. Switching it on lets those tokens keep working after the person is removed at the identity provider, until each token expires or is revoked, or the Workbench account is disabled or deleted, because the provider is never consulted when a token is used. Use a local service account for automation instead.

CORS Origin (cors_origin)

The cors_origin option sets the value for the Access-Control-Allow-Origin response header. The empty default suits same-origin deployments, where the web client and the server share an origin. The server omits CORS headers entirely in that case.

Set cors_origin to an explicit origin when the web client runs on a different origin than the server. For example, use https://workbench.example.com as the value. The server returns Access-Control-Allow-Credentials: true so browsers can attach session cookies to cross-origin requests.

The server rejects a cors_origin value of "*" at startup when authentication is enabled. Browsers disallow combining Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true per the Fetch spec. Use an explicit origin, or leave the option empty for same-origin deployments.

In the following example, the http section allows cross-origin requests from a dedicated workbench host:

http:
  address: ":8443"
  cors_origin: "https://workbench.example.com"
  auth:
    local:
      enabled: true

Connection Security (connection_security)

The connection security section controls SSRF protection for user-created database connections and for the test notifications that the server sends from the Send icon of a notification channel.

Option Type Default Description
allow_internal_networks bool false Allow internal network addresses
allowed_hosts list [] Always-permitted hosts
blocked_hosts list [] Always-blocked hosts
ssl_cert_dir string "" Directory that holds connection SSL files

When allow_internal_networks is false, the server refuses a target in an internal network unless allowed_hosts permits the target. The following table lists the ranges that the server treats as internal:

Range Description
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 RFC 1918 private networks
127.0.0.0/8, ::1/128 Loopback
169.254.0.0/16, fe80::/10 Link-local, including cloud metadata services
0.0.0.0/8, ::/128 Unspecified addresses, which reach the local host
fc00::/7, fec0::/10 IPv6 unique local and deprecated site-local
::/96 IPv4-compatible IPv6, which embeds an IPv4 address
::ffff:0:0:0/96 SIIT IPv4-translated (RFC 2765), which embeds an IPv4 address
64:ff9b::/96, 64:ff9b:1::/48 NAT64 prefixes (RFC 6052 and RFC 8215)
2002::/16 6to4, which embeds an IPv4 address
100.64.0.0/10 Carrier-grade NAT (RFC 6598)
192.0.0.0/24 IETF protocol assignments
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 Documentation networks (TEST-NET-1 to TEST-NET-3)
224.0.0.0/4, ff00::/8 Multicast
240.0.0.0/4 Reserved

An IPv4-mapped IPv6 address, such as ::ffff:10.0.0.1, counts as the IPv4 address that it carries. Neither allow_internal_networks nor allowed_hosts lets the server connect to an unspecified, link-local or cloud metadata address, although a connection that names one can still be saved; see the connect-time check below. That refusal also covers an address in ::/96, ::ffff:0:0:0/96, 64:ff9b::/96 or 2002::/16 that embeds an unspecified, link-local or cloud metadata IPv4 address. For an address in the local-use NAT64 prefix 64:ff9b:1::/48, the server reads the IPv4 address at every RFC 6052 offset that a sub-prefix of the /48 can use (/48, /56, /64 and /96), and refuses the address if any reading is in 169.254.0.0/16 or is 100.100.100.200. Zero, private and public readings pass this refusal, so an ordinary server such as 64:ff9b:1::c633:6407 still connects wherever allow_internal_networks or allowed_hosts permits it. Reading every offset occasionally refuses a legitimate destination: an IPv4 address of the form x.169.254.y behind a /48 or /56 translator prefix, or x.y.169.254 behind a /48 prefix.

The NAT64 prefixes are internal in their entirety, so a deployment on an IPv6-only network that reaches IPv4 servers through NAT64 must set allow_internal_networks to true or add the prefix to allowed_hosts. By default, the alerter refuses to deliver a notification to any of these ranges, whatever the server's connection_security settings say, so an IPv6-only alerter host that reaches IPv4-only notification providers through NAT64 fails every such delivery. The alerter's own notifications.allow_internal_networks option permits these ranges, except the unspecified, link-local and cloud metadata addresses; the alerter has no allowed_hosts option. See Delivery Address Checks.

A test notification follows these rules rather than the alerter's. The server checks every address that a test send connects to, refusing unspecified, link-local and cloud metadata addresses first and then applying blocked_hosts, allowed_hosts and allow_internal_networks. The alerter reads neither allowed_hosts nor blocked_hosts, so a test send can succeed where a real delivery is refused, or the reverse. Loosening this section so that a test send reaches an internal host also loosens the checks on database connections to that host. See Test Sends.

The server applies the host checks to both the host and the hostaddr of a connection. A hostaddr must be a literal IPv4 or IPv6 address, and the server checks that address against the same blocklist, allowlist and internal network rules as a host.

The server checks the target twice. When a user creates or updates a connection, the server resolves a host name and checks the addresses in turn; an address that allowed_hosts covers can permit the whole host name, including the name's other addresses. Each time the server connects to a monitored database, the server resolves the host name again and checks each address on its own, so a host name that later resolves to a refused address cannot reach that address; this check defeats DNS rebinding. At connect time, the server first refuses unspecified, link-local and cloud metadata addresses, whatever allowed_hosts or allow_internal_networks say, and then applies blocked_hosts, allowed_hosts and allow_internal_networks to each remaining address. An address that allowed_hosts covers permits only that address, and the server connects only to the permitted addresses. Apart from those always-refused addresses, a host name that allowed_hosts or blocked_hosts lists by name is still permitted or refused whatever the name resolves to. The save-time check does not apply the always-refused addresses first, so a connection to a link-local address can be saved under allow_internal_networks or an allowed_hosts entry but never connects. When no resolved address is permitted, the connection attempt fails with an error that says the host resolves only to addresses that connections are not permitted to. The server's own connection to the datastore is not checked.

The collector applies a fixed check of its own when the collector connects; see Connection Security Options. The collector refuses the same unspecified, link-local and cloud metadata addresses as the server, so neither component connects to a link-local target, even when allow_internal_networks is true.

The ssl_cert_dir option names the absolute directory that the SSL certificate, key and root certificate files of user-created connections must live in. The server reads these files itself when the server connects to a monitored database, so the directory limits which files a user who can create a connection can make the server open. The server checks each path when a user creates or updates a connection, and again before each connection attempt; a path must meet the following rules:

  • the path is absolute and contains no .. element or control character.
  • the path resolves, following symbolic links, to a location inside the ssl_cert_dir directory.

The directory, every file and link in it, and every parent directory must be writable only by root or the account that runs the server. The server resolves a path before the database driver opens the file, so an account that can replace a symbolic link in the directory, or replace the directory itself through a writable parent, between the two steps could still point the driver at a file outside the directory.

When ssl_cert_dir is empty, which is the default, the server refuses every connection that names an SSL file. A root certificate value of system, which selects the platform trust store, is always allowed. The server refuses to start when ssl_cert_dir holds a relative path. The server reads the option at start-up only, so a change takes effect only when the server restarts; a configuration reload does not change the directory. The PGEDGE_CONNECTION_SECURITY_SSL_CERT_DIR environment variable and the -connection-ssl-cert-dir flag also set the option.

The collector reads the same SSL files when the collector connects, and has its own connection_security.ssl_cert_dir option with the same rules. Set the collector option as well, and keep the files at the same paths on the collector host.

In the following example, the server accepts SSL files in the /etc/pgedge/ai-dba-workbench/certs directory:

connection_security:
  ssl_cert_dir: "/etc/pgedge/ai-dba-workbench/certs"

Database (database)

Option Type Default Description
host string localhost Database host
port int 5432 Database port
database string postgres Database name
user string Database user (required)
password string Database password
password_file string DB password file (if password empty)
sslmode string prefer SSL mode
pool_max_conns int 20 Max pool connections
pool_min_conns int 0 Min pool connections
pool_max_conn_idle_time string 30m Max idle time
statement_timeout string 30s Server-side statement timeout

The statement_timeout option bounds how long a single statement may run on a datastore pool connection before PostgreSQL cancels it. The server already cancels its own queries once the request that asked for them has given up, but that cancellation is a request sent over the same connection, so a lost cancel, or a backend that is not at a point where it can be interrupted, leaves the query running and holding one of the few pool connections; the server-side timeout is what actually frees the connection. The default of 30s matches the longest deadline the server grants a datastore query, so it rejects nothing that would otherwise have completed. The value accepts any Go duration string, such as 45s or 1m30s; 0 disables the timeout, which is not recommended because a single runaway query can then starve the pool.

The pool_max_conns option sets the size of the datastore connection pool that every API request shares. A single dashboard page load issues more than twenty metrics requests at once, so a small pool makes a page wait on itself and lets a few slow requests hold up the rest of the API. The default of 20 leaves room for a second user; together with the collector's default of 25 and the alerter's default of 10, it uses 55 of the 97 connections that the PostgreSQL default max_connections of 100 makes available to ordinary users. Raise the datastore's max_connections before raising any of the three pools past that total. The datastore pool is sized when the server starts, so a change takes effect on restart rather than on a SIGHUP reload. When the option is set explicitly, the same value also caps each per-session pool that the server opens to a monitored database, and a per-session pool opened after a SIGHUP reload uses the reloaded value; when the option is unset, including when the database is configured only through the -db-* command-line flags, those pools use the connection library's default.

Embedding (embedding)

The provider option accepts voyage, openai, gemini, or ollama. The model option accepts any model name the chosen provider recognises; the server passes the name through rather than checking a fixed list, so a new provider model works as soon as the provider publishes the model. Leaving model empty selects the default model for the provider. Google publishes gemini-embedding-001 (the default, 3072 dimensions) and gemini-embedding-2 (also 3072 dimensions); model availability varies by Gemini API key tier, so run ListModels to verify which embedding models a given key can access.

Because the model name is not restricted, an OpenAI-protocol-compatible local model server such as llama.cpp or vLLM can supply embeddings: set provider to openai, point openai_base_url at that server, and set model to the name the server provides.

The configured model must not produce vectors with more than 4000 dimensions. The server stores chat memory embeddings as halfvec(4000) and zero-pads each embedding to 4000 dimensions; 4000 is pgvector's HNSW index limit for the halfvec type. The server rejects a model that exceeds 4000 dimensions with a clear error rather than truncating the vector. Storing embeddings as halfvec requires pgvector 0.7.0 or newer; upgrading an existing installation against an older pgvector causes the embedding-column migration to fail.

Option Type Default Description
enabled bool false Enable embeddings
provider string ollama Provider name
model string varies Model name
ollama_url string http://localhost:11434 Ollama URL
voyage_api_key_file string Voyage API key path
openai_api_key_file string OpenAI API key path
gemini_api_key_file string Gemini API key path
voyage_base_url string https://api.voyageai.com/v1/embeddings Voyage base URL
openai_base_url string https://api.openai.com/v1 OpenAI base URL
gemini_base_url string https://generativelanguage.googleapis.com Gemini base URL

LLM Proxy (llm)

The LLM proxy is optional. When no valid API key is configured for the chosen provider, the server disables all AI features at startup. The web client detects the server's capabilities through the /api/v1/capabilities endpoint and hides all AI-dependent UI elements. The hidden elements include the AI Overview, Ask Ellie chat, alert analysis, chart analysis, and server analysis. The system continues to function as a monitoring tool without AI features.

For Ollama, a valid URL is sufficient because Ollama does not require an API key. For Anthropic, OpenAI, and Gemini, the corresponding API key file must contain a valid key.

The settings in this section govern every AI feature the server drives. The features include the Ask Ellie chat proxy, the AI Overview, and the server-info AI database analysis.

Option Type Default Description
provider string anthropic LLM provider
model string claude-sonnet-5 Model name
anthropic_api_key_file string Anthropic key path
openai_api_key_file string OpenAI key path
gemini_api_key_file string Gemini key path
ollama_url string http://localhost:11434 Ollama URL
max_tokens int 4096 Max output tokens per response
temperature float 0.7 Sampling temperature; 0 is honoured
max_iterations int 50 Max tool-call iterations
compact_tool_descriptions string auto Tool description mode
timeout_seconds int 120 LLM HTTP request timeout
anthropic_base_url string https://api.anthropic.com/v1 Anthropic base URL
openai_base_url string https://api.openai.com/v1 OpenAI base URL
gemini_base_url string https://generativelanguage.googleapis.com Gemini base URL
reasoning_effort string Reasoning effort level
prompt_caching string Prompt caching mode
extra_body mapping Extra request body fields (OpenAI only)
custom_headers mapping Headers sent to every provider
custom_headers_files mapping Header names mapped to secret files
anthropic_custom_headers mapping Headers sent to Anthropic only
openai_custom_headers mapping Headers sent to OpenAI only
gemini_custom_headers mapping Headers sent to Gemini only
ollama_custom_headers mapping Headers sent to Ollama only
rate_limit.overview.generations_per_hour int 60 AI Overview generations per user per hour
rate_limit.overview.burst int 20 AI Overview generations allowed in quick succession
rate_limit.overview.refresh_interval_seconds int 30 Minimum seconds between forced refreshes

Sampling Temperature (temperature)

Some models accept only their own default temperature; these include claude-sonnet-5, the default model, and OpenAI's GPT-6 models. When a model rejects the configured temperature, the server resends the request without the setting and omits the setting from later requests. The model's own default then applies, so the temperature option has no effect, and the server does not log the change.

Output Token Budget (max_tokens)

The max_tokens option caps the number of output tokens a model may generate for a single response. The budget applies to the following AI features:

  • The Ask Ellie chat proxy sends the budget with every chat request that the proxy forwards to a provider.
  • The AI Overview applies the budget to the estate summary and to each scoped summary.
  • The server-info AI database analysis applies the budget to the per-database descriptions.

The default value is 4096 tokens; a value less than or equal to zero falls back to the default. Earlier releases capped the AI Overview and the server-info analysis at 512 tokens and ignored the configured value on both paths.

A reasoning model counts its internal thinking tokens against this same budget. A budget that suits a conventional model can therefore leave no room for the answer itself. The model then returns a response that contains no text, and the affected panel has nothing to render. Raise max_tokens when a summary or an analysis comes back empty; alternatively, select a model that emits less reasoning.

The server reports an empty response instead of discarding the response silently. A scoped AI Overview request fails with an error, and the estate summary records the failure in the server log. The GET /api/v1/server-info/{id}/ai-analysis endpoint returns 502 with a message that names the likely cause.

In the following example, the llm section raises the budget for a reasoning model that a local llama.cpp server hosts:

llm:
  provider: "openai"
  model: "qwen3-8b"
  openai_base_url: "http://localhost:8080/v1"
  max_tokens: 8192

Request Timeout (timeout_seconds)

The timeout_seconds option sets the HTTP client timeout, in seconds, for every request the server makes to the configured LLM provider. The timeout applies uniformly to Anthropic, OpenAI, Gemini, and Ollama, including Ask Ellie chat requests. The default value is 120 seconds; values less than or equal to zero fall back to the default.

Increase this value when running local models on low-resource hardware or when full-context prompts regularly exceed the default; large prompts that combine schema, metrics, and connection data can take longer than 120 seconds on slow Ollama hosts. Raising the timeout to 300 prevents context deadline exceeded errors in these environments.

In the following example, the llm section extends the timeout for a slow local Ollama server:

llm:
  provider: "ollama"
  model: "llama3:latest"
  ollama_url: "http://localhost:11434"
  timeout_seconds: 300

Tool Descriptions (compact_tool_descriptions)

The compact_tool_descriptions option controls whether the server sends compact or verbose tool descriptions to the LLM. The option accepts three values:

  • auto (default) uses compact descriptions for localhost endpoints and verbose descriptions for remote APIs. Compact descriptions reduce prompt token count by approximately fifty-four percent.
  • true always sends compact tool descriptions.
  • false always sends verbose tool descriptions.

This setting affects the chat proxy (Ask Ellie) only. MCP protocol clients always receive full tool descriptions regardless of this setting.

In the following example, the llm section configures verbose tool descriptions:

llm:
  provider: "anthropic"
  model: "claude-sonnet-5"
  anthropic_api_key_file: "~/.anthropic-api-key"
  compact_tool_descriptions: "false"

Reasoning Effort (reasoning_effort)

The reasoning_effort option sets how much a reasoning model thinks before it answers. The option accepts none, minimal, low, medium, high, xhigh, or max; the server refuses to start with any other value. When the option is unset, the server leaves the setting out of each request and the model uses its own default.

The setting applies to Ask Ellie, the AI Overview, and the server-info AI database analysis. Each provider translates the level into its own request field:

  • OpenAI sends the level as reasoning_effort.
  • Anthropic enables adaptive thinking at the given effort, treating minimal as low; none turns thinking off.
  • Gemini sends the level as the thinking level, treating none as minimal, and xhigh and max as high.
  • Ollama ignores the setting.

Which levels a model accepts varies by model. When a model rejects a level, the server retries the request without the setting. A model counts its thinking tokens against max_tokens, so a higher effort may need a larger output budget.

Prompt Caching (prompt_caching)

The prompt_caching option accepts auto or off; an unset value means off. With auto, Anthropic caches the tool list, the system prompt, and the conversation so far, so each step of an Ask Ellie tool loop reads the unchanged part of the prompt from the cache instead of paying the full input rate for the part again. OpenAI and Gemini cache prompts automatically, so the option makes no difference for those providers; Ollama ignores the option.

Anthropic charges more than the normal input rate to write a prompt to the cache, so leave the option off when requests rarely repeat a prompt.

Extra Request Fields (extra_body)

The extra_body option adds fields to the JSON body of every chat request the server sends through the openai provider. Use the option to pass a setting that the server does not model, such as the options of an OpenAI-compatible gateway. A field in extra_body replaces any field of the same name that the server builds. The Anthropic, Gemini, and Ollama providers ignore the option.

The server refuses to start when extra_body sets stream, which the server chooses for each request, or contains a value that cannot be sent as JSON. The server never logs the values in extra_body, but you should still store a credential in an API key file rather than in this option.

In the following example, the llm section asks a reasoning model for low effort and passes a caching option to an OpenAI-compatible gateway:

llm:
  provider: "openai"
  model: "anthropic/claude-sonnet-5"
  openai_base_url: "https://gateway.example.com/v1"
  reasoning_effort: "low"
  extra_body:
    providerOptions:
      gateway:
        caching: "auto"

The server reads these three options at startup only; restart the server to apply a change.

OpenAI-Compatible Local Servers

The openai provider works with any server that implements the OpenAI-compatible API. Set openai_base_url to point at a local inference server. The API key is optional when using a custom base URL.

The following local inference servers are compatible:

  • Docker Model Runner uses http://localhost:12434/engines/llama.cpp/v1 as the default endpoint.
  • llama.cpp uses http://localhost:8080/v1 as the default endpoint.
  • LM Studio uses http://localhost:1234/v1 as the default endpoint.
  • EXO uses http://localhost:52415/v1 as the default endpoint.

In the following example, the llm section configures a local llama.cpp server:

llm:
  provider: "openai"
  model: "my-local-model"
  openai_base_url: "http://localhost:8080/v1"

A local server that hosts a reasoning model usually needs a larger output budget than the default. For details, see Output Token Budget.

Custom HTTP Headers (custom_headers)

The custom header options add HTTP headers to every request the server sends to the LLM provider. Use them when requests pass through an LLM gateway or proxy that needs an authentication token or a routing header. The headers apply to every AI feature the server drives, including the Ask Ellie chat proxy and the AI Overview.

The server builds the headers for a request from the following sources, in order; a later source replaces a header of the same name from an earlier one:

  1. The custom_headers map supplies headers for every provider.
  2. The custom_headers_files map names a header and the path to a file that holds its value.
  3. The LLM_CUSTOM_HEADERS environment variable supplies headers for every provider.
  4. The anthropic_custom_headers, openai_custom_headers, gemini_custom_headers, or ollama_custom_headers map supplies headers for the matching provider only.
  5. The LLM_ANTHROPIC_CUSTOM_HEADERS, LLM_OPENAI_CUSTOM_HEADERS, LLM_GEMINI_CUSTOM_HEADERS, or LLM_OLLAMA_CUSTOM_HEADERS environment variable supplies headers for the matching provider only.

Each environment variable holds a comma-separated list of NAME=value pairs, such as X-Team=dba,X-Route=primary. The first = in a pair separates the name from the value; the server skips an entry with no =. A header with an empty value in one of the first three sources is ignored.

Use custom_headers_files for a secret value, such as a gateway token, so that the secret stays out of the configuration file. The server expands a leading ~ in the path, removes the trailing newline from the value, and logs a warning when the group or other users can access the file. The Ask Ellie chat proxy reads each file once, when the server starts, so restart the server after replacing a file; the other AI features read the file each time they call the provider. When a file is missing, unreadable, or empty, the server logs an error and sends the affected requests without any custom headers.

In the following example, the llm section sends a gateway token from a file with every request, and adds a routing header to Anthropic requests:

llm:
  provider: "anthropic"
  model: "claude-sonnet-5"
  anthropic_api_key_file: "~/.anthropic-api-key"
  anthropic_base_url: "https://llm-gateway.example.com/v1"
  custom_headers:
    X-Team: "dba"
  custom_headers_files:
    X-Gateway-Token: "/etc/ai-workbench/gateway-token"
  anthropic_custom_headers:
    X-Route: "anthropic-primary"

AI Overview Rate Limits (rate_limit.overview)

The server limits how many AI Overview summaries each user can cause it to generate, so that a script calling the overview endpoints in a loop, or a browser tab that keeps reconnecting, cannot run up the bill on the LLM account. The limits apply per user to the /api/v1/overview and /api/v1/overview/stream endpoints. Reading the estate-wide summary, which the server regenerates on its own schedule and shares between users, is not counted, although forcing a refresh of it is; a user over the limit who asks for one is served the current estate summary instead.

Each user may trigger burst generations in quick succession, after which the allowance refills at generations_per_hour. A request that a fresh cached summary answers costs nothing. When a user has no generations left, the server serves the cached summary for the scope even if it is stale; only when no summary is cached does it return an HTTP 429 Too Many Requests response with a Retry-After header that gives the wait in seconds.

A forced refresh (refresh=true) is also throttled to one per refresh_interval_seconds for each user. A refresh within that interval is treated as an ordinary request and is answered from the cache where possible.

Set generations_per_hour or refresh_interval_seconds to 0 to disable that limit. The server reads these settings at start-up, so a change takes effect on restart rather than on a SIGHUP reload.

In the following example, each user can trigger ten generations at once, then thirty an hour, and refresh at most once a minute:

llm:
  rate_limit:
    overview:
      generations_per_hour: 30
      burst: 10
      refresh_interval_seconds: 60

Knowledgebase (knowledgebase)

The pgedge-ai-kb packages install one knowledgebase database per embedding provider and model. On Linux these files live in /usr/share/pgedge/pgedge-ai-kb/, and each file is named kb-<provider>-<model>.db. The <provider> and <model> parts match the configured embedding_provider and embedding_model values. For the default ollama provider with the nomic-embed-text model, the file is kb-ollama-nomic-embed-text.db. The full default path is therefore /usr/share/pgedge/pgedge-ai-kb/kb-ollama-nomic-embed-text.db. The exact location can vary by deployment method and operating system.

The built-in database_path default still points at the legacy /usr/share/pgedge/postgres-mcp-kb/kb.db location. Set database_path explicitly when you use the current pgedge-ai-kb packages, so the server reads the installed file.

The embedding_provider option accepts voyage, openai, gemini, or ollama, and embedding_model accepts any model name the chosen provider recognises. Google publishes gemini-embedding-001 (the default, 3072 dimensions) and gemini-embedding-2 (also 3072 dimensions); model availability varies by Gemini API key tier, so run ListModels to verify which embedding models a given key can access.

When Gemini provides the knowledgebase embeddings, the configured embedding_model must match the model that the KB Builder used to produce the knowledgebase. The KB Builder uses gemini-embedding-001; selecting a different model produces incompatible embeddings and breaks similarity search.

Option Type Default Description
enabled bool false Enable knowledgebase
database_path string /usr/share/pgedge/postgres-mcp-kb/kb.db (legacy; see note above) SQLite knowledgebase database path
embedding_provider string ollama Embedding provider
embedding_model string nomic-embed-text Embedding model
embedding_ollama_url string http://localhost:11434 Ollama URL
embedding_voyage_api_key_file string Voyage API key path
embedding_openai_api_key_file string OpenAI key path
embedding_gemini_api_key_file string Gemini key path
embedding_voyage_base_url string https://api.voyageai.com/v1/embeddings Voyage base URL
embedding_openai_base_url string https://api.openai.com/v1 OpenAI base URL
embedding_gemini_base_url string https://generativelanguage.googleapis.com Gemini base URL

Memory (memory)

The memory section controls the chat memory feature for Ask Ellie. Chat memory allows Ellie to store and recall information across conversations.

Option Type Default Description
enabled bool true Enable chat memory

The memory feature requires a configured PostgreSQL datastore connection. The server stores memories in the datastore alongside other persistent data. When memory is disabled, the three memory tools (store_memory, recall_memories, delete_memory) are unavailable even when enabled in the builtins.tools section.

Creating system-scoped memories requires the store_system_memory admin permission. Administrators assign this permission to groups through the admin panel. Users without the permission can only create user-scoped memories.

In the following example, the memory section disables chat memory:

memory:
  enabled: false

The PGEDGE_MEMORY_ENABLED environment variable can also control this setting; see Environment Variables for details.

Built-in Features (builtins)

The builtins section enables or disables individual tools and resources.

Two tools are always enabled and cannot be turned off through the builtins.tools section. The test_query tool validates SQL without executing the query, and the server asks Ellie to check every statement through that tool before presenting the statement to a user. The read_resource tool backs resource listing, so resources become unreachable without the tool.

builtins:
  tools:
    query_database: true
    get_schema_info: true
    similarity_search: true
    execute_explain: true
    count_rows: true
    list_probes: true
    describe_probe: true
    query_metrics: true
    list_connections: true
    get_alert_history: true
    get_alert_rules: true
    get_metric_baselines: true
    get_blackouts: true
    get_timeline_events: true
    query_datastore: true
    describe_datastore: true
    generate_embedding: true
    search_knowledgebase: true
    store_memory: true
    recall_memories: true
    delete_memory: true
  resources:
    system_info: true
    connection_info: true

Datastore Query Tools

The query_datastore tool runs structured queries against the datastore, and the describe_datastore tool lists the sources that query_datastore can read and describes their columns. Both tools default to true. The query_datastore tool does not accept SQL, and the tool limits connection-specific rows to the connections the caller can access, whilst estate-wide configuration rows remain readable; the MCP Tools and Resources page describes the tool's parameters.

In the following example, the configuration disables both datastore query tools:

builtins:
  tools:
    query_datastore: false
    describe_datastore: false

Memory Tools

The memory tools (store_memory, recall_memories, delete_memory) allow Ellie to store and recall information across conversations. The server stores memories in the PostgreSQL datastore. When embedding generation is enabled, the recall_memories tool uses semantic similarity for searching. The tool falls back to text matching when embeddings are unavailable.

Set any memory tool to false in the builtins.tools section to disable the tool.

In the following example, the configuration disables the store_memory and delete_memory tools while keeping recall_memories enabled:

builtins:
  tools:
    store_memory: false
    delete_memory: false
    recall_memories: true

Paths and Directories

Option Type Default Description
secret_file string /etc/pgedge/ai-dba-server.secret Encryption secret path
custom_definitions_path string Custom prompts file path
data_dir string ./data/ Auth and conversation data
trace_file string MCP trace file path

Data Directory

The data directory stores persistent data files:

  • auth.db stores authentication data in SQLite.
  • conversations.db stores chat history in SQLite.

The default location is ./data/ relative to the server binary.

In the following example, the -data-dir flag specifies a custom location:

./ai-dba-server -data-dir /var/lib/ai-workbench/data

The data directory can also be set in the configuration file:

data_dir: "/var/lib/ai-workbench/data"

MCP Tracing

The server can log all MCP requests and responses to a trace file for debugging purposes.

In the following example, the -trace-file flag enables tracing:

./ai-dba-server \
    -trace-file /var/log/ai-workbench/mcp-trace.log

The trace file can also be set in the configuration file:

trace_file: "/var/log/ai-workbench/mcp-trace.log"

Configuration Examples

Development Configuration

http:
  address: ":8080"
  tls:
    enabled: false
  auth:
    local:
      enabled: true
connection_security:
  allow_internal_networks: true
database:
  host: "localhost"
  port: 5432
  database: "ai_workbench"
  user: "postgres"
  sslmode: "disable"
embedding:
  enabled: true
  provider: "ollama"
  model: "nomic-embed-text"
llm:
  provider: "ollama"
  model: "llama3:latest"

Production Configuration

http:
  address: ":8443"
  tls:
    enabled: true
    cert_file: "/etc/ai-workbench/certs/cert.pem"
    key_file: "/etc/ai-workbench/certs/key.pem"
  trusted_proxies:
    - "10.0.0.0/8"
    - "172.16.0.0/12"
  cors_origin: "https://workbench.example.com"
  auth:
    local:
      enabled: true
    max_failed_attempts_before_lockout: 5
    max_user_token_days: 90
connection_security:
  allow_internal_networks: false
  allowed_hosts:
    - "db.internal.example.com"
  blocked_hosts:
    - "169.254.169.254"
database:
  host: "db.internal.example.com"
  port: 5432
  database: "ai_workbench_prod"
  user: "ai_workbench"
  sslmode: "verify-full"
  pool_max_conns: 20
embedding:
  enabled: true
  provider: "voyage"
  model: "voyage-3"
  voyage_api_key_file: "/etc/ai-workbench/voyage-key"
llm:
  provider: "anthropic"
  model: "claude-sonnet-5"
  anthropic_api_key_file: "/etc/ai-workbench/ant-key"
secret_file: "/etc/ai-workbench/server.secret"
data_dir: "/var/lib/ai-workbench/data"

Environment Variables

The server reads the following environment variables at startup.

PGEDGE_POSTGRES_CONNECTION_STRING

The PGEDGE_POSTGRES_CONNECTION_STRING variable provides a PostgreSQL connection string for the datastore. The server uses this variable as a fallback when the configuration file does not specify database settings.

The server applies connection settings in the following priority order:

  1. Database configuration from the YAML file or command-line flags.
  2. The PGEDGE_POSTGRES_CONNECTION_STRING variable.
  3. The default value postgres://localhost/postgres?sslmode=disable.

In the following example, the variable specifies a remote database:

export PGEDGE_POSTGRES_CONNECTION_STRING=\
"postgres://user:[email protected]:5432/\
ai_workbench?sslmode=require"

The server reads a + in a query parameter value as a literal plus sign, as libpq does; write a space in a value as %20.

PGEDGE_CONNECTION_SECURITY_SSL_CERT_DIR

The PGEDGE_CONNECTION_SECURITY_SSL_CERT_DIR variable sets the connection_security.ssl_cert_dir option, the absolute directory that monitored connections' SSL certificate, key and root certificate files must live in. A non-empty value overrides the configuration file, and the -connection-ssl-cert-dir flag overrides the variable. The server reads the variable at start-up only. See Connection Security for the rules that the server applies to each path.

In the following example, the variable names the certificate directory:

export PGEDGE_CONNECTION_SECURITY_SSL_CERT_DIR=\
/etc/pgedge/ai-dba-workbench/certs

PGEDGE_DB_LOG_LEVEL

The PGEDGE_DB_LOG_LEVEL variable controls the verbosity of database operation logging. The server writes database log messages to stderr with a [DATABASE] prefix.

The following values are supported:

  • none disables all database logging (default).
  • info logs connections, queries, and errors.
  • debug logs metadata, pool details, and queries.
  • trace logs full queries, row counts, and timings.

An empty or unrecognized value defaults to none.

In the following example, the variable enables debug logging:

export PGEDGE_DB_LOG_LEVEL=debug

PGEDGE_MEMORY_ENABLED

The PGEDGE_MEMORY_ENABLED variable controls the chat memory feature for Ask Ellie. The server reads this variable at startup and applies the value as an override to the memory.enabled configuration option.

The following values are supported:

  • true enables chat memory (default).
  • false disables chat memory.

In the following example, the variable disables chat memory:

export PGEDGE_MEMORY_ENABLED=false

PGEDGE_AUDIT_RETENTION_DAYS

The PGEDGE_AUDIT_RETENTION_DAYS variable controls how many days of RBAC audit events the server keeps. The server reads this variable at startup and applies the value as an override to the http.auth.audit_retention_days configuration option. A value of 0 keeps audit events forever.

In the following example, the variable keeps a year of audit events:

export PGEDGE_AUDIT_RETENTION_DAYS=365

Configuration Reload

The server supports runtime configuration reload via SIGHUP:

kill -SIGHUP $(pgrep ai-dba-server)

A SIGHUP signal reloads the following settings:

  • Database connection settings.
  • LLM proxy settings, except the AI Overview rate limits under llm.rate_limit, which need a restart.
  • Knowledgebase settings.
  • The federated login policy under http.auth.oidc, as described in Single Sign-On.

A database setting given on the command line at start-up, such as -db-host, keeps priority over the configuration file on every reload, as it does at start-up.

The other authentication settings and the HTTP server settings require a full restart. A reload keeps the value the server started with and warns about each of the settings whose change it detects, among them http.auth.max_failed_attempts_before_lockout, which the authentication store reads once at start-up, so account lockout stays as configured at the last restart until the server is restarted again.

The connection_security.ssl_cert_dir option also requires a restart; a reload keeps the directory the server started with, and does not warn about a change to the option. A reload that finds a relative ssl_cert_dir fails, and the server keeps its current configuration.