Configuration reference
Every scalar accepts the listed QOD_* / PROXY_* environment-variable override. Sensitive defaults (passwords, secrets, keys) are flagged; rotate them before any non-local deployment.
quack-flightsql
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-flightsql.host | PROXY_HOST | 0.0.0.0 | FlightSQL edge bind address. | |
quack-flightsql.port | PROXY_PORT | 31338 | FlightSQL edge port. | |
quack-flightsql.tlsEnabled | PROXY_TLS_ENABLED | true | Enable TLS on the FlightSQL edge. | |
quack-flightsql.tlsCertChain | PROXY_TLS_CERT_CHAIN | certs/server-cert.pem | Path to the TLS certificate chain PEM (auto-generated if missing). | |
quack-flightsql.tlsPrivateKey | PROXY_TLS_PRIVATE_KEY | certs/server-key.pem | Path to the TLS private key PEM (auto-generated if missing). | |
quack-flightsql.sessionTtlSec | QOD_SESSION_TTL_SEC | 3600 | Edge session TTL in seconds before a fresh handshake is forced. | |
quack-flightsql.resumeHoldTimeoutSec | PROXY_RESUME_HOLD_TIMEOUT_SEC | 60 | Max seconds the edge holds a statement while a suspended pool cold-starts. |
quack-flightsql.acl
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-flightsql.acl.enabled | QOD_ACL_ENABLED | false | Enable table-level RBAC (per-statement EffectiveSet check). | |
quack-flightsql.acl.dialect | QOD_ACL_DIALECT | duckdb | Statement parser dialect for ACL extraction. |
quack-flightsql.auth
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-flightsql.auth.roleClaim | QOD_AUTH_ROLE_CLAIM | role | JWT claim that carries the user's role. | |
quack-flightsql.auth.database.enabled | QOD_AUTH_DB_ENABLED | true | Enable database (bcrypt) authentication for the FlightSQL edge. | |
quack-flightsql.auth.database.jdbcUrl | QOD_AUTH_DB_JDBC_URL | jdbc:postgresql://localhost:5432/qod | JDBC URL for the auth-lookup database. | |
quack-flightsql.auth.database.username | QOD_AUTH_DB_USER | postgres | Username for the auth-lookup JDBC connection. | |
quack-flightsql.auth.database.password | QOD_AUTH_DB_PASSWORD | *** | yes | Password for the auth-lookup JDBC connection. |
quack-flightsql.auth.database.systemQuery | QOD_AUTH_DB_SYSTEM_QUERY | SELECT password_hash, role, enabled FROM qodstate_user WHERE tenant IS NULL AND username = ? LIMIT 1 | SQL template for AuthScope.System (empty tenant / superuser=true). Returns (password_hash, role) and accepts one ? placeholder for username; matches WHERE tenant IS NULL. | |
quack-flightsql.auth.database.tenantQuery | QOD_AUTH_DB_TENANT_QUERY | SELECT password_hash, role, enabled FROM qodstate_user WHERE tenant = ? AND username = ? LIMIT 1 | SQL template for AuthScope.Tenant. Returns (password_hash, role) and accepts two ? placeholders in order: tenant, username. | |
quack-flightsql.auth.keycloak.enabled | QOD_AUTH_KEYCLOAK_ENABLED | false | Enable the Keycloak OIDC bearer provider. | |
quack-flightsql.auth.keycloak.baseUrl | QOD_AUTH_KEYCLOAK_BASE_URL | https://keycloak.example.com | Keycloak base URL (e.g. https://keycloak.example.com). | |
quack-flightsql.auth.keycloak.realm | QOD_AUTH_KEYCLOAK_REALM | quack | Keycloak realm name. | |
quack-flightsql.auth.keycloak.clientId | QOD_AUTH_KEYCLOAK_CLIENT_ID | (unset) | Keycloak client ID for ROPC. | |
quack-flightsql.auth.keycloak.clientSecret | QOD_AUTH_KEYCLOAK_CLIENT_SECRET | *** | yes | Keycloak client secret. |
quack-flightsql.auth.keycloak.issuer | QOD_AUTH_KEYCLOAK_ISSUER | (unset) | Override for the expected token issuer (the iss claim the bearer validator requires). Leave empty to derive it from baseUrl + realm. Set it when Keycloak's browser-facing issuer (KC_HOSTNAME_URL) differs from the in-cluster baseUrl used to fetch JWKS: tokens minted via an ingress carry iss=https://host/auth/realms/<realm> while the manager fetches JWKS in-cluster. JWKS is always derived from baseUrl, not this value. | |
quack-flightsql.auth.google.enabled | QOD_AUTH_GOOGLE_ENABLED | false | Enable the Google OIDC bearer provider. | |
quack-flightsql.auth.google.clientId | QOD_AUTH_GOOGLE_CLIENT_ID | (unset) | Google OAuth client ID. | |
quack-flightsql.auth.google.clientSecret | QOD_AUTH_GOOGLE_CLIENT_SECRET | *** | yes | Google OAuth client secret. |
quack-flightsql.auth.google.groupsLookup | QOD_AUTH_GOOGLE_GROUPS_LOOKUP | false | Resolve Google Workspace groups membership server-side. | |
quack-flightsql.auth.google.serviceAccountKeyPath | QOD_AUTH_GOOGLE_SVC_ACCT_KEY_PATH | (unset) | Path to a Google service-account JSON used for groups lookup. | |
quack-flightsql.auth.google.groupsCacheTtlSeconds | QOD_AUTH_GOOGLE_GROUPS_CACHE_TTL_SEC | 300 | Cache TTL for Google groups lookups in seconds. | |
quack-flightsql.auth.azure.enabled | QOD_AUTH_AZURE_ENABLED | false | Enable the Azure AD bearer provider. | |
quack-flightsql.auth.azure.tenantId | QOD_AUTH_AZURE_TENANT_ID | (unset) | Azure AD tenant ID. | |
quack-flightsql.auth.azure.clientId | QOD_AUTH_AZURE_CLIENT_ID | (unset) | Azure AD application (client) ID. | |
quack-flightsql.auth.azure.clientSecret | QOD_AUTH_AZURE_CLIENT_SECRET | *** | yes | Azure AD application client secret. |
quack-flightsql.auth.aws.enabled | QOD_AUTH_AWS_ENABLED | false | Enable the AWS Cognito bearer provider. | |
quack-flightsql.auth.aws.region | QOD_AUTH_AWS_REGION | us-east-1 | AWS region hosting the Cognito user pool. | |
quack-flightsql.auth.aws.userPoolId | QOD_AUTH_AWS_USER_POOL_ID | (unset) | Cognito user pool ID. | |
quack-flightsql.auth.aws.clientId | QOD_AUTH_AWS_CLIENT_ID | (unset) | Cognito app client ID. | |
quack-flightsql.auth.jwt.secretKey | JWT_SECRET_KEY | *** | yes | HMAC secret for HS256/HS512 external JWT verification. |
quack-flightsql.auth.jwt.publicKeyPath | JWT_PUBLIC_KEY_PATH | (unset) | Path to the RSA/ECDSA PEM public key for external JWT verification. | |
quack-flightsql.auth.jwt.issuer | JWT_ISSUER | (unset) | Expected 'iss' claim value (empty = not checked). | |
quack-flightsql.auth.jwt.audience | JWT_AUDIENCE | (unset) | Expected 'aud' claim value (empty = not checked). | |
quack-flightsql.auth.oauthScopes | QOD_AUTH_OAUTH_SCOPES | openid profile email | OAuth scopes requested at authorization time for the browser SQL-token flow. |
quack-flightsql.validation
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-flightsql.validation.enabled | QOD_VALIDATION_ENABLED | true | Enable per-statement SQL validation. | |
quack-flightsql.validation.allowByDefault | QOD_VALIDATION_ALLOW_BY_DEFAULT | true | When true, statements pass when no explicit rule matches. | |
quack-flightsql.validation.bypassUsers | QOD_VALIDATION_BYPASS_USERS | admin@localhost.local,admin | Comma-separated usernames that skip SQL validation entirely. |
quack-on-demand
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.host | QOD_ON_DEMAND_HOST | 0.0.0.0 | Manager REST bind address (0.0.0.0 to listen on all interfaces). | |
quack-on-demand.port | QOD_ON_DEMAND_PORT | 20900 | Manager REST + admin UI port. | |
quack-on-demand.apiKey | QOD_API_KEY | *** | yes | Static admin API key sent as X-API-Key. Unset = REST namespace is open. |
quack-on-demand.runtimeType | QOD_RUNTIME_TYPE | local | Quack node runtime backend: 'local' (child processes) or 'kubernetes'. | |
quack-on-demand.minPort | QOD_MIN_PORT | 21900 | Lower bound of the port range LocalQuackBackend allocates child nodes from. | |
quack-on-demand.maxPort | QOD_MAX_PORT | 22500 | Upper bound of the port range LocalQuackBackend allocates child nodes from. | |
quack-on-demand.maxNodesTotal | QOD_MAX_NODES_TOTAL | 50 | Hard cap on concurrent child nodes across all pools. | |
quack-on-demand.nativeClient | QOD_NATIVE_CLIENT | true | Use the JNI-backed native Quack wire client. False falls back to the embedded path. | |
quack-on-demand.stampWrites | QOD_STAMP_WRITES | true | Stamp DuckLake snapshots created by FlightSQL DML/DDL with author and commit message (native wire bracket; fail-open). Off = writes are never bracketed. | |
quack-on-demand.nodeDisableSsl | QOD_NODE_DISABLE_SSL | true | Disable TLS on the embedded path's quack_query() call. Ignored on the native path. | |
quack-on-demand.spawnScript | QOD_SPAWN_SCRIPT | ./scripts/spawn-quack-node.sh | Path to spawn-quack-node.sh invoked by LocalQuackBackend on Unix. | |
quack-on-demand.spawnScriptWindows | QOD_SPAWN_SCRIPT_WINDOWS | ./scripts/spawn-quack-node.ps1 | Path to the PowerShell spawn script (spawn-quack-node.ps1) invoked by LocalQuackBackend on Windows. | |
quack-on-demand.drainTimeoutSec | QOD_DRAIN_TIMEOUT_SEC | 60 | Seconds to wait for in-flight statements during graceful pool shutdown. | |
quack-on-demand.healthCheckIntervalSec | QOD_HEALTH_CHECK_INTERVAL_SEC | 5 | Seconds between supervisor health checks against child nodes. | |
quack-on-demand.reconcileIntervalSec | QOD_RECONCILE_INTERVAL_SEC | 30 | Seconds between supervisor reconcile passes that respawn dead nodes. 0 disables the periodic loop (reconcile still runs once at boot). | |
quack-on-demand.sessionIdleTtlSec | QOD_SESSION_IDLE_TTL_SEC | 28800 | UI session idle TTL in seconds. A session unused for this long is dropped on the next access; each successful access slides the window. Manager restart still invalidates everything (sessions are heap-only). |
quack-on-demand.admin
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.admin.username | QOD_ADMIN_USERNAME | admin@localhost.local,admin | Comma-separated admin usernames seeded into qodstate_user. | |
quack-on-demand.admin.password | QOD_ADMIN_PASSWORD | *** | yes | Bootstrap admin password (re-hashed on every boot). |
quack-on-demand.admin.role | QOD_ADMIN_ROLE | admin | Role assigned to the bootstrap admin user. |
quack-on-demand.auth
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.auth.management.identitySource | QOD_MGMT_IDENTITY_SOURCE | db | System-scope (bare /ui/) admin-UI login mode: 'db' (password form) or 'oidc' (SSO). Per-tenant login mode is read from the tenant's authProvider, not this key. | |
quack-on-demand.auth.management.sessionJwtSecret | QOD_SESSION_JWT_SECRET | *** | yes | HS256 secret used to sign UI session JWTs. Pin a stable value (>= 32 chars) to make sessions survive manager restart and to share session state across replicas. Empty = autogenerate a fresh 32-byte secret at boot (sessions die on restart, no horizontal scale). |
quack-on-demand.auth.management.sessionCookieSecure | QOD_SESSION_COOKIE_SECURE | auto | Whether the qod_session cookie carries the Secure flag. Accepts 'auto' (default, derives from the request's X-Forwarded-Proto -- https=Secure, http or absent=not Secure), 'true' (force Secure regardless of request scheme; use behind a TLS ingress that strips X-Forwarded-Proto), or 'false' (force not Secure). | |
quack-on-demand.auth.management.sessionCookiePath | QOD_SESSION_COOKIE_PATH | /api | Path attribute on the qod_session cookie. Default '/api'. Override when the manager sits behind a path-rewriting reverse proxy: the value must match the BROWSER-visible URL prefix, not the backend's. E.g. proxy at https://platform/quack/api/* -> QOD_SESSION_COOKIE_PATH=/quack/api. | |
quack-on-demand.auth.management.publicBaseUrl | QOD_MGMT_PUBLIC_BASE_URL | (unset) | Externally visible manager base URL (e.g. https://qod.example.com). Used to build OIDC redirect_uri and post_logout_redirect_uri for admin-UI SSO. When empty, derived from X-Forwarded-Proto / X-Forwarded-Host / Host. | |
quack-on-demand.auth.management.oidc.issuerUrl | QOD_MGMT_OIDC_ISSUER_URL | (unset) | OIDC issuer URL for admin-UI SSO (system scope), e.g. https://accounts.google.com or http://keycloak:8080/auth/realms/qod. Discovery reads ${issuerUrl}/.well-known/openid-configuration. Empty disables system-scope SSO. | |
quack-on-demand.auth.management.oidc.clientId | QOD_MGMT_OIDC_CLIENT_ID | (unset) | OIDC client id for admin-UI SSO (system scope). | |
quack-on-demand.auth.management.oidc.clientSecret | QOD_MGMT_OIDC_CLIENT_SECRET | *** | yes | OIDC client secret for admin-UI SSO (system scope). |
quack-on-demand.auth.management.oidc.scopes | QOD_MGMT_OIDC_SCOPES | openid email profile | OIDC scopes requested for admin-UI SSO. Default 'openid email profile'. |
quack-on-demand.catalog
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.catalog.auditCatalogReads | QOD_AUDIT_CATALOG_READS | false | Audit catalog browser reads: one catalog.read event per gated GET. Off by default (reads are chatty; mutations are always audited). | |
quack-on-demand.catalog.previewMaxRows | QOD_CATALOG_PREVIEW_MAX_ROWS | 1000 | Hard cap on rows returned by the catalog data-preview endpoint. | |
quack-on-demand.catalog.previewTimeoutSec | QOD_CATALOG_PREVIEW_TIMEOUT_SEC | 30 | Seconds before a catalog data-preview query is cancelled. | |
quack-on-demand.catalog.undropTimeoutSec | QOD_CATALOG_UNDROP_TIMEOUT_SEC | 300 | Seconds before an undrop recovery CTAS is abandoned. Larger than the preview timeout because it is a mutation over potentially large tables; on timeout the handler probes whether the table was created anyway and reports accordingly. | |
quack-on-demand.catalog.restoreTimeoutSec | QOD_CATALOG_RESTORE_TIMEOUT_SEC | 300 | Seconds before a restore CREATE OR REPLACE is abandoned. On timeout the handler probes whether the replace committed anyway and reports accordingly. |
quack-on-demand.defaultMetastore
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.defaultMetastore.pgHost | QOD_PG_HOST | localhost | Postgres host for control plane + DuckLake catalog. | |
quack-on-demand.defaultMetastore.pgPort | QOD_PG_PORT | 5432 | Postgres port. | |
quack-on-demand.defaultMetastore.pgUser | QOD_PG_USER | postgres | Postgres username used by the manager + Quack nodes. | |
quack-on-demand.defaultMetastore.pgPassword | QOD_PG_PASSWORD | *** | yes | Postgres password. |
quack-on-demand.defaultMetastore.dbName | QOD_PG_DBNAME | qod | Control-plane database name (default 'qod'). | |
quack-on-demand.defaultMetastore.schemaName | QOD_PG_SCHEMA | main | Postgres schema for control-plane tables. | |
quack-on-demand.defaultMetastore.dataPath | QOD_DUCKLAKE_DATA_PATH | ./ducklake/tpch | Root path for DuckLake parquet data files. |
quack-on-demand.federation
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.federation.secretStore | QOD_FEDERATION_SECRET_STORE | dispatch | Federation secret resolver: postgres | env | aws-sm | gcp-sm | azure-kv | vault. |
quack-on-demand.ha
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.ha.enabled | QOD_HA_ENABLED | false | Enable active-active multi-replica manager mode (Kubernetes runtime only). | |
quack-on-demand.ha.leaderRetrySec | QOD_LEADER_RETRY_SEC | 3 | Seconds between leader-lock acquisition attempts and LISTEN polls. | |
quack-on-demand.ha.topologyRefreshSec | QOD_TOPOLOGY_REFRESH_SEC | 30 | Seconds between snapshot-refresh fallback passes in HA mode. |
quack-on-demand.k8s
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.k8s.namespace | QOD_K8S_NAMESPACE | default | Kubernetes namespace KubernetesQuackBackend operates in. | |
quack-on-demand.k8s.image | QOD_K8S_IMAGE | starlakeai/quack-on-demand-node:latest-snapshot | Docker image used for spawned Quack-node pods. | |
quack-on-demand.k8s.serviceAccount | QOD_K8S_SERVICE_ACCOUNT | (unset) | ServiceAccount applied to spawned node pods (unset = default). | |
quack-on-demand.k8s.serviceType | QOD_K8S_SERVICE_TYPE | ClusterIP | Kubernetes Service type fronting node pods. | |
quack-on-demand.k8s.quackPort | QOD_K8S_QUACK_PORT | 8080 | Container port exposing each node's /quack endpoint. | |
quack-on-demand.k8s.startupTimeoutSec | QOD_K8S_STARTUP_TIMEOUT_SEC | 120 | Seconds to wait for a spawned node pod to become ready. | |
quack-on-demand.k8s.podLabel | QOD_K8S_POD_LABEL | managed-by=quack-on-demand | Label selector that identifies manager-owned node pods. | |
quack-on-demand.k8s.podTemplateEnabled | QOD_POD_TEMPLATE_ENABLED | false | Allow superusers to supply a full Pod-manifest YAML template for a pool's node pods. Off by default; raw manifests are cluster-level power. | |
quack-on-demand.k8s.runAsUser | QOD_K8S_RUN_AS_USER | 1000 | Pod-level runAsUser/fsGroup applied to spawned node pods. A pod template's own securityContext.runAsUser (if set) wins over this default. |
quack-on-demand.maintenance
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.maintenance.enabled | QOD_MAINT_ENABLED | true | Enable the maintenance scheduler + drain-loop fibers. | |
quack-on-demand.maintenance.tickSec | QOD_MAINT_TICK_SEC | 60 | Seconds between maintenance scheduler ticks (cadence + threshold checks). | |
quack-on-demand.maintenance.maxConcurrent | QOD_MAINT_MAX_CONCURRENT | 2 | Max maintenance runs executing concurrently across the manager. | |
quack-on-demand.maintenance.minIntervalMin | QOD_MAINT_MIN_INTERVAL_MIN | 30 | Minimum minutes between non-manual maintenance runs of the same tenant-db. | |
quack-on-demand.maintenance.runTimeoutMin | QOD_MAINT_RUN_TIMEOUT_MIN | 60 | Minutes without a heartbeat before a running maintenance run is swept as failed. | |
quack-on-demand.maintenance.nodeReadyTimeoutSec | QOD_MAINT_NODE_READY_TIMEOUT_SEC | 180 | Seconds to wait for the ephemeral maintenance node to accept connections after spawn before the run is failed as 'node spawn failed'. Covers cold-start extension installs. |
quack-on-demand.metrics
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.metrics.sink | QOD_METRICS_SINK | prometheus | Active metrics sink: prometheus | aws | azure | gcp | none. | |
quack-on-demand.metrics.aws.namespace | QOD_METRICS_AWS_NAMESPACE | quack-on-demand | CloudWatch namespace when metrics.sink=aws. | |
quack-on-demand.metrics.aws.stepSeconds | QOD_METRICS_AWS_STEP_SEC | 60 | CloudWatch publish step in seconds. | |
quack-on-demand.metrics.azure.instrumentationKey | QOD_METRICS_AZURE_KEY | *** | yes | Azure Monitor instrumentation key. |
quack-on-demand.metrics.azure.stepSeconds | QOD_METRICS_AZURE_STEP_SEC | 60 | Azure Monitor publish step in seconds. | |
quack-on-demand.metrics.gcp.projectId | QOD_METRICS_GCP_PROJECT_ID | (unset) | GCP project ID when metrics.sink=gcp. | |
quack-on-demand.metrics.gcp.stepSeconds | QOD_METRICS_GCP_STEP_SEC | 60 | GCP Cloud Monitoring publish step in seconds. |
quack-on-demand.telemetry
| Key | Env var | Default | Sensitive | Description |
|---|---|---|---|---|
quack-on-demand.telemetry.store | QOD_TELEMETRY_STORE | postgres | Telemetry store backing audit log (and, later, history/usage): postgres | none (record nothing). | |
quack-on-demand.telemetry.auditRetentionDays | QOD_AUDIT_RETENTION_DAYS | 90 | Days to keep audit events before the hourly purge deletes them. | |
quack-on-demand.telemetry.journalCapacity | QOD_TELEMETRY_JOURNAL_CAPACITY | 8192 | Bounded in-process telemetry journal capacity; overflow drops events (counted). | |
quack-on-demand.telemetry.stmtHistoryRetentionDays | QOD_STMT_HISTORY_RETENTION_DAYS | 7 | Days to keep statement-history rows before the periodic purge removes them. | |
quack-on-demand.telemetry.hourlyRollupRetentionDays | QOD_HOURLY_ROLLUP_RETENTION_DAYS | 90 | Days to keep hourly rollup buckets before the periodic purge removes them. | |
quack-on-demand.telemetry.rollupIntervalSec | QOD_ROLLUP_INTERVAL_SEC | 300 | Seconds between rollup computation passes that aggregate raw statement history into rollup buckets. | |
quack-on-demand.telemetry.usageRetentionDays | QOD_USAGE_RETENTION_DAYS | 400 | Days to keep daily rollup buckets (the usage-accounting ledger) before the periodic purge removes them. 400 covers a full billing year. |