Skip to Content
ReferenceConfiguration

Configuration

Gestalt is configured from one or more YAML files. This page covers the cross-cutting config model: file structure, loading, layering, environment expansion, secret resolution, validation, and complete examples.

For provider-specific setup, use the Providers pages. For every field and validation rule, use the Config File reference.

File Structure

A Gestalt config has six top-level areas:

KeyPurpose
serverHost settings, listener configuration, encryption key, runtime defaults, and selected host providers.
providersNamed host-scoped providers for identity, authorization, storage, secrets, telemetry, audit, UI, workflow, and agent backends.
appsTool providers exposed over HTTP, MCP, and CLI, plus optional app-backed UI mounts.
authorizationStatic subject access policies shared by the host and provider-backed authorization.
runtimeNamed runtime placement backends for providers that opt into hosted execution.
workflowsConfig-managed workflow definitions and activations.
server: baseUrl: ... encryptionKey: ... providers: indexeddb: ... identity: ... authorization: ... providers: indexeddb: <name>: ... identity: <name>: ... authorization: <name>: ... externalCredentials: <name>: ... secrets: <name>: ... workflow: <name>: ... agent: <name>: ... ui: <name>: ... apps: <name>: ... authorization: models: ... relationships: ... runtime: providers: <name>: ... workflows: definitions: {}

Provider-backed entries accept source, provider-specific config, egress.allowedHosts, and optional metadata fields. App entries also support plugin-specific fields such as connections, allowedOperations, ui.path, ui.bundle, and runtime.

Where Setup Lives

Configuration is intentionally split between this page, provider guides, and the field reference:

NeedRead
App setup, operation filtering, connections, and app-backed UIsApps
Platform loginIdentity
RBAC, policies, and static grantsAuthorization configuration
Service accounts, subject-owned API tokens, and runAsService Accounts
Credential storage and upstream credentialsExternal Credentials
Persistent state providersIndexedDB
Secret manager providersSecrets
Workflow provider setupWorkflow
Agent provider setupAgent
Public app frontends (apps.<name>.static)Applications
Runtime placementRuntime
Exact YAML fieldsConfig File

Loading And Layering

When --config is not supplied, gestaltd looks for a config file in this order:

  1. GESTALT_CONFIG environment variable
  2. ./config.yaml in the working directory
  3. ~/.gestaltd/config.yaml

If nothing is found, gestaltd generates a default config at ~/.gestaltd/config.yaml with SQLite storage, no identity provider, a random encryption key, and an HTTPBin test app.

When --config is repeated, Gestalt loads the files left-to-right and merges them with these rules:

  • Maps deep-merge.
  • Later scalar values win.
  • Later lists replace inherited lists.
  • null deletes inherited keys.

Relative paths resolve from the file that declared them. The lockfile defaults to the current working directory (./gestalt.lock.json); --lockfile overrides only the lockfile path and resolves like a normal CLI path. Prepared artifact paths default to the current working directory; server.artifactsDir and --artifacts-dir override that location.

Environment And Secrets

Gestalt expands ${ENV_VAR} placeholders before YAML decoding. When a referenced variable is unset, Gestalt checks for a corresponding ENV_VAR_FILE variable and reads that file path instead. If neither is set, config loading fails. Use ${ENV_VAR:-} when an explicit empty default is intentional.

Structured secret refs are resolved through the named secret manager during bootstrap, not during YAML parsing. This lets you reference secrets from files, Vault, AWS Secrets Manager, Google Secret Manager, or Azure Key Vault without embedding them in the config file.

server: encryptionKey: secret: provider: default name: gestalt-encryption-key providers: secrets: default: source: file config: dir: /etc/gestalt-secrets

Validation And Defaults

Unknown YAML fields are rejected at load time. Validate config without starting the server:

gestaltd validate --config ./config.yaml gestaltd validate --config ./deploy/base.yaml --config ./deploy/overrides/local.yaml

Gestalt defaults server.public.port to 8080; if it is in use, gestaltd serve tries the next free port. The runtime secrets manager defaults to built-in env when providers.secrets is omitted, providers.telemetry.default to stdout, and providers.audit.default to inherit.

The required fields at serve time are providers.indexeddb, server.providers.indexeddb, and server.encryptionKey. Platform identity is optional.

server.encryptionKey is the root deployment secret. Gestalt derives token encryption and session material from it. Changing this key invalidates existing sessions and tokens, so treat it as a deployment event.

Lock, Sync, And Serve

For deterministic production deployments:

  1. Run gestaltd lock --config ./config.yaml to resolve provider packages and write gestalt.lock.json.
  2. Run gestaltd sync --locked --config ./config.yaml to prepare provider artifacts.
  3. Run gestaltd serve --locked --config ./config.yaml at runtime.

See Deploy, Docker, Helm, and the Server CLI for deployment-specific workflows.

Minimal Config

server: public: port: 8080 baseUrl: http://localhost:8080 encryptionKey: ${GESTALT_ENCRYPTION_KEY} providers: indexeddb: main providers: indexeddb: main: source: package: github.com/valon-technologies/gestalt-providers/indexeddb/relationaldb version: 0.0.1-alpha.1 config: dsn: sqlite://./gestalt.db

Set GESTALT_ENCRYPTION_KEY once with openssl rand -hex 32 before starting Gestalt. Do not use a shared placeholder value in a real deployment.

Full Example

A production deployment with OIDC identity, external credential storage, a GitHub app with subject-scoped connections, and MCP enabled:

server: baseUrl: https://gestalt.example.com encryptionKey: secret: provider: default name: gestalt-encryption-key providers: identity: oidc indexeddb: main externalCredentials: main secrets: default providers: secrets: default: source: file config: dir: /etc/gestalt-secrets indexeddb: main: source: package: github.com/valon-technologies/gestalt-providers/indexeddb/relationaldb version: 0.0.1-alpha.1 config: dsn: sqlite://./gestalt.db externalCredentials: main: source: package: github.com/valon-technologies/gestalt-providers/externalcredentials/default version: 0.0.1-alpha.1 config: indexeddb: main identity: oidc: source: package: github.com/valon-technologies/gestalt-providers/auth/oidc version: 0.0.1-alpha.1 config: issuerUrl: https://login.example.com clientId: ${OIDC_CLIENT_ID} clientSecret: secret: provider: default name: oidc-client-secret apps: github: displayName: GitHub source: package: github.com/valon-technologies/gestalt-providers/app/github version: 0.0.1-alpha.1 surfaces: openapi: baseUrl: https://api.github.com mcp: url: https://mcp.github.example.com/mcp connections: api: mode: subject auth: type: bearer credentials: - name: token label: Personal Access Token mcp: mode: subject auth: type: mcp_oauth

MCP surfaces expose upstream tools through the generic REST facade at POST /api/v1/{app}/{operation}. GET /api/v1/apps/{app}/operations lists HTTP-safe MCP tools as POST operations with transport: mcp-passthrough, and responses use the MCP CallToolResult envelope. Dynamic MCP tool catalogs are loaded lazily when request-scoped discovery is needed.