From 57e03472b153784aed5d62c9f3b1924573c00c59 Mon Sep 17 00:00:00 2001 From: Vlad Ilyushchenko Date: Wed, 4 Feb 2026 22:45:09 +0000 Subject: [PATCH] Document secrets from files for Kubernetes deployments Add documentation for the _FILE suffix convention that allows QuestDB to read sensitive configuration values from mounted files. This enables native integration with Kubernetes Secrets, Docker Secrets, and HashiCorp Vault. Changes: - Add "Secrets from files" section to configuration overview with usage, precedence rules, file requirements, error handling, and supported properties - Add "Using Kubernetes secrets" section with StatefulSet example - Add tip to Enterprise quick start for Kubernetes password configuration - Separate OSS and Enterprise properties in documentation Co-Authored-By: Claude Opus 4.5 --- documentation/configuration/overview.md | 93 +++++++++++++++++++ documentation/deployment/kubernetes.md | 66 +++++++++++++ .../getting-started/enterprise-quick-start.md | 9 ++ 3 files changed, 168 insertions(+) diff --git a/documentation/configuration/overview.md b/documentation/configuration/overview.md index cd48e4d12..a618efb6c 100644 --- a/documentation/configuration/overview.md +++ b/documentation/configuration/overview.md @@ -96,6 +96,99 @@ query.timeout=120s export QDB_QUERY_TIMEOUT=120s ``` +## Secrets from files + +QuestDB supports reading sensitive configuration values from files using the +`_FILE` suffix convention. This is useful in containerized environments like +Kubernetes, where secrets are typically mounted as files rather than passed as +environment variables. + +When a `_FILE` variant is set, QuestDB reads the secret value from the specified +file path. This works with both environment variables and properties in +`server.conf`. + +### Usage + +**Environment variable:** + +```shell +QDB_PG_PASSWORD_FILE=/run/secrets/pg-password +``` + +**Property file:** + +```ini title="server.conf" +pg.password.file=/run/secrets/pg-password +``` + +### Precedence + +If both a `_FILE` variant and the direct value are set, the `_FILE` variant +takes precedence. For example, if both `QDB_PG_PASSWORD_FILE` and +`QDB_PG_PASSWORD` are set, the value is read from the file. + +### File requirements + +Secret files must meet the following requirements: + +- **Maximum size**: 64KB +- **Encoding**: UTF-8 +- **Content handling**: Leading and trailing whitespace is automatically trimmed + +The following paths are not allowed for security reasons: + +- Paths containing `..` (path traversal) +- Paths starting with `/dev/`, `/proc/`, or `/sys/` +- Directories (including symlinks to directories) + +If a secret file is empty or contains only whitespace, QuestDB logs an advisory +warning, as this may weaken authentication. + +### Error handling + +If a secret file cannot be read at startup, QuestDB fails to start. This +includes cases where the file does not exist, is too large, or the path is +not allowed. + +During runtime, if `reload_config()` cannot read a secret file, the reload +fails and the previous value is retained. This ensures the server continues +operating if a secret file is temporarily unavailable. + +### Reloading secrets + +Secrets loaded from files support runtime reloading. After updating a secret +file, call `reload_config()` to apply the new value. See +[Reloadable settings](#reloadable-settings) for details. + +To verify that a secret was loaded from a file, run `SHOW PARAMETERS` and check +the `value_source` column, which displays `file` for secrets loaded from files. + +### Supported properties + +The following properties support the `_FILE` suffix: + +| Property | Environment variable | +| ---------------------- | ------------------------------- | +| `pg.password` | `QDB_PG_PASSWORD_FILE` | +| `pg.readonly.password` | `QDB_PG_READONLY_PASSWORD_FILE` | +| `http.password` | `QDB_HTTP_PASSWORD_FILE` | + +#### Enterprise properties + +The following additional properties are available in +[QuestDB Enterprise](/enterprise/): + +| Property | Environment variable | +| -------------------------------- | ----------------------------------------- | +| `acl.admin.password` | `QDB_ACL_ADMIN_PASSWORD_FILE` | +| `acl.oidc.tls.keystore.password` | `QDB_ACL_OIDC_TLS_KEYSTORE_PASSWORD_FILE` | +| `replication.object.store` | `QDB_REPLICATION_OBJECT_STORE_FILE` | +| `cold.storage.object.store` | `QDB_COLD_STORAGE_OBJECT_STORE_FILE` | +| `backup.object.store.*` | `QDB_BACKUP_OBJECT_STORE_*_FILE` | + +For Kubernetes-specific examples, see the +[Kubernetes deployment guide](/docs/deployment/kubernetes/#using-kubernetes-secrets). + ## Reloadable settings Certain configuration settings can be reloaded without having to restart the diff --git a/documentation/deployment/kubernetes.md b/documentation/deployment/kubernetes.md index 0950cc5ec..9a954bcf4 100644 --- a/documentation/deployment/kubernetes.md +++ b/documentation/deployment/kubernetes.md @@ -82,3 +82,69 @@ The QuestDB Helm chart supports a variety of configuration options. Run the foll ```shell helm show values questdb/questdb ``` + +## Using Kubernetes secrets + +QuestDB supports reading sensitive configuration values directly from mounted +secret files using the `_FILE` suffix convention. This eliminates the need for +shell scripts or init containers to inject secrets as environment variables. + +For example, to configure the PostgreSQL wire protocol password from a +Kubernetes secret: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: questdb-secrets +type: Opaque +data: + pg-password: bXktc2VjcmV0LXBhc3N3b3Jk # base64 encoded + +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: questdb +spec: + serviceName: questdb + replicas: 1 + selector: + matchLabels: + app: questdb + template: + metadata: + labels: + app: questdb + spec: + containers: + - name: questdb + image: questdb/questdb:latest + env: + - name: QDB_PG_PASSWORD_FILE + value: /run/secrets/pg-password + volumeMounts: + - name: secrets + mountPath: /run/secrets + readOnly: true + volumes: + - name: secrets + secret: + secretName: questdb-secrets + items: + - key: pg-password + path: pg-password +``` + +:::note + +This example focuses on secret mounting and omits the `volumeClaimTemplates` +needed for persistent storage. For production deployments, use the +[QuestDB Helm chart](#get-the-questdb-helm-chart) which handles storage +configuration automatically. + +::: + +For the full list of supported properties, see +[Secrets from files](/docs/configuration/overview/#secrets-from-files) in the +configuration reference. diff --git a/documentation/getting-started/enterprise-quick-start.md b/documentation/getting-started/enterprise-quick-start.md index 987997d82..03655aa13 100644 --- a/documentation/getting-started/enterprise-quick-start.md +++ b/documentation/getting-started/enterprise-quick-start.md @@ -74,6 +74,15 @@ acl.admin.user=myadmin acl.admin.password=my_very_secure_pwd ``` +:::tip Kubernetes deployments + +In Kubernetes, you can read the password from a mounted secret file instead of +hardcoding it. Set `QDB_ACL_ADMIN_PASSWORD_FILE` to the path of the mounted +secret. See [Secrets from files](/docs/configuration/overview/#secrets-from-files) +for details. + +::: + We will optionally disable this built-in administrator account later. For more on access control, see [Role-Based Access Control](/docs/security/rbac/).