> ## Documentation Index
> Fetch the complete documentation index at: https://pgconsole-docs-faq-apache-license.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# pgconsole.toml Reference

pgconsole uses a TOML configuration file for all settings. Pass the config file with the `--config` flag. Without `--config`, pgconsole starts in [demo mode](/getting-started/quickstart#demo-mode).

<Tabs>
  <Tab title="Docker">
    ```bash theme={null}
    docker run -p 9876:9876 -v /path/to/pgconsole.toml:/etc/pgconsole.toml pgplex/pgconsole
    ```
  </Tab>

  <Tab title="npx">
    ```bash theme={null}
    npx @pgplex/pgconsole --config /path/to/pgconsole.toml
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={null}
    pgconsole --config /path/to/pgconsole.toml
    ```
  </Tab>
</Tabs>

## Complete Example

```toml pgconsole.toml theme={null}
[general]
external_url = "https://pgconsole.example.com"

[general.banner]
text = "System maintenance scheduled for Sunday 2am UTC"
link = "https://status.example.com"
color = "#7c3aed"

[branding]
logo = "https://example.com/your-logo.svg"
logo_link = "https://internal.example.com"

[[labels]]
id = "prod"
name = "Production"
color = "#ef4444"

[[labels]]
id = "staging"
name = "Staging"
color = "#f59e0b"

[[connections]]
id = "local"
name = "Local Dev"
host = "localhost"
port = 5432
database = "postgres"
username = "postgres"
password = "postgres"
ssl_mode = "prefer"

[[connections]]
id = "production"
name = "Production DB"
host = "db.example.com"
port = 5432
database = "app"
username = "readonly"
password = "secret"
ssl_mode = "verify-full"
ssl_ca = "/path/to/ca.crt"
ssl_cert = "/path/to/client.crt"
ssl_key = "/path/to/client.key"
labels = ["prod"]
lock_timeout = "5s"
statement_timeout = "30s"

[auth]
jwt_secret = "your-secret-key-at-least-32-characters-long"
signin_expiry = "7d"

[[auth.providers]]
type = "google"
client_id = "your-client-id"
client_secret = "your-client-secret"

[[auth.providers]]
type = "keycloak"
client_id = "pgconsole"
client_secret = "your-client-secret"
issuer_url = "https://keycloak.example.com/realms/your-realm"

[[auth.providers]]
type = "okta"
client_id = "0oaXXXXXXXXXXXXXX"
client_secret = "your-okta-client-secret"
issuer_url = "https://your-org.okta.com/oauth2/default"

[[users]]
email = "admin@example.com"
password = "your-password"
owner = true

[[users]]
email = "alice@example.com"

[[groups]]
id = "dev-team"
name = "Development Team"
members = ["admin@example.com", "alice@example.com"]

[[groups]]
id = "dba"
name = "Database Administrators"
members = ["admin@example.com"]

[[iam]]
connection = "*"
permissions = ["read"]
members = ["*"]

[[iam]]
connection = "local"
permissions = ["read", "write", "ddl", "admin"]
members = ["user:admin@example.com", "group:dba"]

[[ai.providers]]
id = "gpt4"
name = "GPT-4o"
vendor = "openai"
model = "gpt-4o"
api_key = "sk-..."

[[agents]]
id = "alice-claude"
token = "pgc_mcp_xxxxxxxxxxxxxxxx"
on_behalf_of = "alice@example.com"
permissions = ["read"]
```

## General

| Field          | Description                                                                                     | Required         |
| -------------- | ----------------------------------------------------------------------------------------------- | ---------------- |
| `external_url` | Public URL of the application. See [Configure External Access](/configuration/external-access). | Required for SSO |

```toml pgconsole.toml theme={null}
[general]
external_url = "https://pgconsole.example.com"
```

### Announcement Banner

Optional banner displayed at the top of the page. The banner cannot be dismissed by users.

| Field   | Description                                            | Required |
| ------- | ------------------------------------------------------ | -------- |
| `text`  | Banner message text                                    | Yes      |
| `link`  | URL that makes the banner clickable (opens in new tab) |          |
| `color` | Hex color code for the banner background               |          |

```toml pgconsole.toml theme={null}
[general.banner]
text = "System maintenance scheduled for Sunday 2am UTC"
link = "https://status.example.com"
color = "#7c3aed"
```

## Branding

Replace the pgconsole logo with your own.

| Field       | Description                                              | Required |
| ----------- | -------------------------------------------------------- | -------- |
| `logo`      | URL to your logo image                                   | Yes      |
| `logo_link` | Where the logo links to (absolute path or `http(s)` URL) |          |

When `logo_link` is omitted, the logo links to `/`.

```toml pgconsole.toml theme={null}
[branding]
logo = "https://example.com/your-logo.svg"
logo_link = "https://internal.example.com"
```

## Labels

Labels for tagging connections (e.g. Production, Staging). Referenced by the `labels` field in `[[connections]]`. Repeat for multiple labels.

| Field   | Description       | Required |
| ------- | ----------------- | -------- |
| `id`    | Unique identifier | Yes      |
| `name`  | Display name      | Yes      |
| `color` | Hex color code    | Yes      |

```toml pgconsole.toml theme={null}
[[labels]]
id = "prod"
name = "Production"
color = "#ef4444"
```

## Connections

Database connections. Repeat for multiple connections.

<Note>
  If connecting to a database on your host machine from Docker, use `host.docker.internal` instead of `localhost`.
</Note>

| Field               | Description                                                                                                                   | Required | Default        |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------- | -------------- |
| `id`                | Unique identifier                                                                                                             | Yes      |                |
| `name`              | Display name                                                                                                                  | Yes      |                |
| `host`              | PostgreSQL host                                                                                                               | Yes      |                |
| `port`              | PostgreSQL port                                                                                                               |          | `5432`         |
| `database`          | Database name                                                                                                                 | Yes      |                |
| `username`          | Database user                                                                                                                 | Yes      |                |
| `password`          | Database password                                                                                                             |          |                |
| `ssl_mode`          | `disable`, `prefer`, `require`, or `verify-full`                                                                              |          | `prefer`       |
| `ssl_ca`            | Path to CA certificate                                                                                                        |          |                |
| `ssl_cert`          | Path to client certificate                                                                                                    |          |                |
| `ssl_key`           | Path to client private key                                                                                                    |          |                |
| `labels`            | Array of label IDs                                                                                                            |          | `[]`           |
| `color`             | Hex color (e.g. `#dc2626`) that tints the header to flag the environment (e.g. red for production)                            |          |                |
| `lock_timeout`      | [`lock_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-LOCK-TIMEOUT), e.g. `"5s"`            |          | System default |
| `statement_timeout` | [`statement_timeout`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-STATEMENT-TIMEOUT), e.g. `"30s"` |          | System default |
| `lazy`              | Skip connection test on startup                                                                                               |          | `false`        |

```toml pgconsole.toml theme={null}
[[connections]]
id = "production"
name = "Production DB"
host = "db.example.com"
port = 5432
database = "app"
username = "readonly"
password = "secret"
ssl_mode = "verify-full"
ssl_ca = "/path/to/ca.crt"
ssl_cert = "/path/to/client.crt"
ssl_key = "/path/to/client.key"
labels = ["prod"]
color = "#dc2626"
lock_timeout = "5s"
statement_timeout = "30s"
```

## Authentication

<Tip>
  To run without authentication, omit the `[auth]` section entirely.
</Tip>

| Field           | Description                              | Required |
| --------------- | ---------------------------------------- | -------- |
| `jwt_secret`    | Secret key for JWT tokens (min 32 chars) | Yes      |
| `signin_expiry` | Session duration (`h`/`d`/`w`)           | Yes      |

```toml pgconsole.toml theme={null}
[auth]
jwt_secret = "your-secret-key-at-least-32-characters-long"
signin_expiry = "7d"
```

### OAuth Providers

OAuth providers are configured as an array of `[[auth.providers]]` entries. Each entry requires a `type` field. Repeat for multiple providers.

| Field           | Description                                     | Required |
| --------------- | ----------------------------------------------- | -------- |
| `type`          | Provider type: `google`, `keycloak`, or `okta`  | Yes      |
| `client_id`     | OAuth client ID                                 | Yes      |
| `client_secret` | OAuth client secret                             | Yes      |
| `issuer_url`    | Issuer URL (required for `keycloak` and `okta`) |          |

```toml pgconsole.toml theme={null}
# Google
[[auth.providers]]
type = "google"
client_id = "your-client-id.apps.googleusercontent.com"
client_secret = "your-client-secret"

# Keycloak
[[auth.providers]]
type = "keycloak"
client_id = "pgconsole"
client_secret = "your-client-secret"
issuer_url = "https://keycloak.example.com/realms/your-realm"

# Okta
[[auth.providers]]
type = "okta"
client_id = "0oaXXXXXXXXXXXXXX"
client_secret = "your-okta-client-secret"
issuer_url = "https://your-org.okta.com/oauth2/default"
```

## Users

User entries. Repeat for multiple users. Users with a `password` can sign in with basic auth. Users without a `password` are SSO-only.

| Field      | Description                                            | Required |
| ---------- | ------------------------------------------------------ | -------- |
| `email`    | User email or identifier                               | Yes      |
| `password` | Login password (omit for SSO-only users)               |          |
| `owner`    | Marks the user as an owner (shown with an Owner badge) |          |

```toml pgconsole.toml theme={null}
[[users]]
email = "admin@example.com"
password = "your-password"
owner = true

[[users]]
email = "alice@example.com"
# SSO-only user - no password
```

### Owner Role

Users with `owner = true` are marked with an Owner badge in the UI. If no user has `owner = true`, the first user entry automatically becomes the owner.

## Groups

User groups for organizing users. Repeat for multiple groups.

| Field     | Description          | Required |
| --------- | -------------------- | -------- |
| `id`      | Unique identifier    | Yes      |
| `name`    | Display name         | Yes      |
| `members` | Array of user emails | Yes      |

Members are user emails matching `[[users]]` entries.

```toml pgconsole.toml theme={null}
[[groups]]
id = "dev-team"
name = "Development Team"
members = ["admin@example.com", "alice@example.com"]
```

## Access Control (IAM)

Rules for controlling access to connections. IAM is opt-in: with no `[[iam]]` rules defined, all authenticated users have full access, and enforcement begins once you define the first rule. See [Database Access Control](/features/database-access-control) for a full guide on permissions, patterns, and examples.

| Field         | Description                                                                            | Required |
| ------------- | -------------------------------------------------------------------------------------- | -------- |
| `connection`  | Connection ID or `*` for all                                                           | Yes      |
| `permissions` | Array: `read`, `write`, `ddl`, `admin`, `explain`, `execute`, `export`, or `*` for all | Yes      |
| `members`     | Array: `user:<email>`, `group:<id>`, or `*` for all users                              | Yes      |

```toml pgconsole.toml theme={null}
[[iam]]
connection = "*"
permissions = ["read"]
members = ["*"]

[[iam]]
connection = "production"
permissions = ["read", "write"]
members = ["user:admin@example.com", "group:dev-team"]
```

### Validation

IAM rules are validated when the configuration is loaded:

* `connection` must be `*` or reference a valid connection ID
* `permissions` must only contain valid values: `read`, `write`, `ddl`, `admin`, `explain`, `execute`, `export`, or `*`
* `members` must use valid formats: `user:<email>`, `group:<id>`, or `*`
* `group:<id>` must reference a defined group

Invalid rules will cause the server to fail at startup with an error message.

## AI Providers

Configure providers for the [AI Assistant](/features/ai-assistant). Repeat for multiple providers.

| Field      | Description                                                                  | Required                               |
| ---------- | ---------------------------------------------------------------------------- | -------------------------------------- |
| `id`       | Unique identifier                                                            | Yes                                    |
| `name`     | Display name (defaults to `id`)                                              |                                        |
| `vendor`   | AI vendor: `openai`, `anthropic`, `google`, `openai-compatible`              | Yes                                    |
| `model`    | Model identifier                                                             | Yes                                    |
| `api_key`  | API key for the vendor                                                       | Yes (optional for `openai-compatible`) |
| `base_url` | Base URL of an OpenAI-compatible API (e.g. `https://api.groq.com/openai/v1`) | Required for `openai-compatible`       |

Use `vendor = "openai-compatible"` with `base_url` for any provider that implements the OpenAI API (Groq, OpenRouter, Together, Ollama, vLLM, LiteLLM, and most self-hosted gateways). `api_key` may be omitted for local providers that run without authentication (e.g. Ollama, self-hosted vLLM).

```toml pgconsole.toml theme={null}
[[ai.providers]]
id = "gpt4"
name = "GPT-4o"
vendor = "openai"
model = "gpt-4o"
api_key = "sk-..."

[[ai.providers]]
id = "groq"
name = "Llama 3.3 70B"
vendor = "openai-compatible"
model = "llama-3.3-70b-versatile"
api_key = "gsk_..."
base_url = "https://api.groq.com/openai/v1"
```

## Agents

Non-human principals that authenticate to the [MCP Server](/features/mcp-server) with a bearer token. An agent is **not** a [user](#users) — it can't log into the UI. Repeat for multiple agents.

| Field          | Description                                                                              | Required |
| -------------- | ---------------------------------------------------------------------------------------- | -------- |
| `id`           | Unique identifier, referenced in IAM rules as `agent:<id>`                               | Yes      |
| `token`        | Secret bearer token the agent sends as `Authorization: Bearer <token>` (globally unique) | Yes      |
| `name`         | Display name (defaults to `id`)                                                          |          |
| `on_behalf_of` | A [`[[users]]`](#users) email. Its presence makes the agent **delegated** — see below    |          |
| `permissions`  | Cap intersected with the user's grant; delegated agents only                             |          |
| `connections`  | Connection IDs the agent may touch; delegated agents only                                |          |

There are two kinds of agent:

* **Pure agent** (no `on_behalf_of`) — a standalone service account, e.g. a CI bot. Authorize it with normal [IAM rules](#access-control-iam) whose `members` include `agent:<id>`. It is granted *only* what those rules say (`*`/`group:`/`user:` rules never apply to agents).
* **Delegated agent** (`on_behalf_of` set) — acts on behalf of a user and **inherits that user's permissions**, optionally narrowed by the `permissions`/`connections` caps. It can never exceed the user, and automatically loses access when the user does.

An agent only sees the MCP tools its effective permissions unlock — a `read`-only agent sees the discovery and `query` tools; `write_data`/`run_ddl` appear only with those permissions. Give each agent the narrowest grant it needs.

```toml pgconsole.toml theme={null}
# Pure agent — granted by an agent: IAM rule
[[agents]]
id = "migration-bot"
name = "Nightly Migration Bot"
token = "pgc_mcp_xxxxxxxxxxxxxxxx"

[[iam]]
connection = "staging"
permissions = ["read", "ddl"]
members = ["agent:migration-bot"]

# Delegated agent — bounded by alice, capped to read-only on prod
[[agents]]
id = "alice-claude"
name = "Alice's Claude Code"
token = "pgc_mcp_yyyyyyyyyyyyyyyy"
on_behalf_of = "alice@example.com"
permissions = ["read"]
connections = ["prod"]
```
