Skip to main content

Configuration and Secrets

Use the production values example as the non-secret values file. Never put credentials, licenses, private signing keys, or registry tokens in Helm values.

Runtime Secret​

Create one Secret containing every key referenced by global.secretKeys:

kubectl -n loadouthq create secret generic loadouthq-runtime \
--from-literal=DATABASE_URL='postgresql://USER:PASSWORD@DB_HOST:5432/loadouthq?sslmode=require' \
--from-literal=REDIS_URL='rediss://:PASSWORD@VALKEY_HOST:6379/0' \
--from-literal=S3_ENDPOINT='https://s3.example.com' \
--from-literal=S3_REGION='REGION' \
--from-literal=S3_BUCKET='BUCKET' \
--from-literal=S3_ACCESS_KEY_ID='ACCESS_KEY' \
--from-literal=S3_SECRET_ACCESS_KEY='SECRET_KEY' \
--from-literal=SESSION_SECRET='AT_LEAST_32_RANDOM_CHARACTERS' \
--from-literal=ENCRYPTION_KEY='64_HEXADECIMAL_CHARACTERS' \
--from-literal=OPENAI_API_KEY='sk-...'

Prefer an external secret manager or sealed-secret workflow in production. License validation settings are part of the official API image and are not customer runtime configuration.

Omit OPENAI_API_KEY when configurable prompt checks are not used. The Helm reference is optional, so an existing runtime Secret without that key remains valid.

OpenAI skill validation​

Configurable platform and organization checks use the OpenAI Responses API. Both the secret OPENAI_API_KEY and a non-empty config.openAiValidationModel are required to enable them. Built-in package validation continues to work when OpenAI is not configured.

config:
openAiValidationModel: YOUR_RESPONSES_API_MODEL
openAiBaseUrl: https://api.openai.com/v1
validationContextMaxBytes: 524288
validationOpenAiTimeoutMs: 60000
validationOpenAiMaxAttempts: 3
validationCheckConcurrency: 3
Helm valueAPI environment variablePurpose
global.secretKeys.openAiApiKeyOPENAI_API_KEYKey name in global.existingSecret; optional
config.openAiValidationModelOPENAI_VALIDATION_MODELResponses API model used for configurable checks
config.openAiBaseUrlOPENAI_BASE_URLOpenAI-compatible API base URL
config.validationContextMaxBytesVALIDATION_CONTEXT_MAX_BYTESMaximum extracted skill context sent to a check
config.validationOpenAiTimeoutMsVALIDATION_OPENAI_TIMEOUT_MSTimeout for each provider attempt
config.validationOpenAiMaxAttemptsVALIDATION_OPENAI_MAX_ATTEMPTSMaximum provider attempts for transient errors, from 1 to 5
config.validationCheckConcurrencyVALIDATION_CHECK_CONCURRENCYConcurrent configurable checks processed by a worker

Keep the API key only in the Secret. The model identifier and tuning values are non-secret and belong in the reviewed values file. Restart the API deployment after rotating the key or changing these values.

Optional bundled Valkey​

External Valkey remains the production default. To install the official valkey-io Helm chart as a dependency, enable it in the LoadoutHQ values:

valkey:
enabled: true

The dependency uses persistent storage and ACL authentication. Add REDIS_PASSWORD to the same runtime Secret and set REDIS_URL to the dependency Service. For the default release name:

REDIS_PASSWORD='GENERATE_A_STRONG_PASSWORD'
REDIS_URL='redis://:GENERATE_A_STRONG_PASSWORD@loadouthq-valkey:6379/0'

If global.existingSecret is not loadouthq-runtime, also set valkey.auth.usersExistingSecret to the same Secret name. If the Helm release name changes, replace loadouthq-valkey with <release-name>-valkey. Treat the bundled dependency as a single-instance option; use an externally operated Valkey service when the availability or recovery requirements exceed a single persistent instance.

Required non-secret values​

ValueMeaning
config.appBaseUrlPublic SPA origin used in links and redirects
config.apiPublicUrlPublic API origin used for OIDC callbacks; normally the same origin
config.corsOriginAllowed browser origin
config.trustedProxyHopsDirect TLS-terminating proxy hops trusted for forwarded headers
config.platformAdminEmailLocal bootstrap account promoted to platform admin
config.openAiValidationModelOptional model enabling configurable prompt checks
global.existingSecretExisting Secret holding connection and application keys
imagePullSecretsSecret names granting nodes access to private images
ingress.hostPublic DNS hostname when Ingress is enabled
httpRoute.parentRefsExisting Gateway and optional listener attachment
httpRoute.hostnamesPublic DNS hostnames accepted by HTTPRoute

The API validates required environment values before serving traffic. Public URLs must match the externally reachable HTTPS address, not Kubernetes Service names.

Policy defaults​

Registration and organization creation are disabled in the production example. With orgCreationEnabled: false, the API bootstraps the organization identified by defaultOrgSlug for platformAdminEmail, then idempotently adds every active user to that organization as a reader. Existing memberships and stronger roles are preserved. The first administrator must exist before the backfill can complete; if registration is disabled, create that account through the documented administrator flow and restart the API.

When orgCreationEnabled: true, new users receive a personal organization as its owner. Changing the setting does not remove existing organizations or memberships.

The default organization settings are:

Helm valueAPI environment variablePurpose
config.defaultOrgSlugDEFAULT_ORG_SLUGStable slug used to identify the shared default organization.
config.defaultOrgNameDEFAULT_ORG_NAMEDisplay name used when the default organization is first created.
config.platformAdminEmailPLATFORM_ADMIN_EMAILAccount that owns the shared default organization. Required when organization creation is disabled.

The API refuses onboarding when the configured slug already belongs to another creator. Resolve the slug conflict or change the configured slug, then restart the deployment.

The explicit additional-organization creation endpoint and MAX_ORGS_PER_USER enforcement remain planned work; this onboarding change does not add that API flow or limit enforcement.

TLS-terminating proxies​

When HTTPS terminates at an Ingress, Gateway, or reverse proxy, set config.trustedProxyHops to the number of direct proxy hops between that terminator and the API. The standard Helm and Docker Compose layouts use 1. This allows the API to honor the trusted X-Forwarded-Proto: https header and issue secure session cookies. Do not set a value larger than the actual path length, and leave it at 0 when the API is reached directly.

Registry Secret​

kubectl -n loadouthq create secret docker-registry loadouthq-registry \
--docker-server=registry.gitlab.com \
--docker-username='DEPLOY_TOKEN_USER' \
--docker-password='DEPLOY_TOKEN'

Use a read-registry deploy token and rotate it through the customer's secret-management process.