Skip to main content

Config and Secrets

Openlane uses a layered configuration system built on koanf. Configuration values are resolved through a three-stage hierarchy where each stage can override the previous one.

Loading Hierarchy

  1. Struct defaults -- the default struct tags on the Go config type provide baseline values
  2. YAML config file -- loaded from ./config/.config.yaml by default. If the file is missing, the system logs a warning and continues with defaults
  3. Environment variables -- override everything. Prefixed with CORE_ and mapped to nested fields via underscore-to-dot transformation

Environment Variable Mapping

Environment variables follow the pattern CORE_<SECTION>_<FIELD>:

Environment VariableConfig PathExample Value
CORE_SERVER_LISTENserver.listen:17608
CORE_DB_PRIMARYDBSOURCEdb.primarydbsourcepostgres://user:pass@localhost/openlane
CORE_AUTH_TOKEN_ACCESSDURATIONauth.token.accessduration15m
CORE_REDIS_ADDRESSredis.addresslocalhost:6379
CORE_ENTITLEMENTS_ENABLEDentitlements.enabledtrue

The transformation strips the CORE_ prefix, lowercases the remainder, and converts underscores to dots for nesting.

Config Structure

The root config struct in config/config.go contains all server configuration organized by concern:

SectionKey FieldsPurpose
Serverlisten, debug, tls, cors, csrf, timeoutsHTTP server behavior
DBprimarydbsource, secondarydbsourceDatabase connections
Authenabled, token, supportedproviders, providersAuthentication settings
AuthzOpenFGA configurationAuthorization service
RedisaddressCache and session store
EmailProvider config, template pathsEmail delivery
SessionsCookie config, expiryUser session management
ObjectStorageProvider config (S3, R2, Disk, Database)File storage
EntitlementsStripe keys, webhook secretsBilling and subscription
WorkflowsEngine configurationWorkflow execution
SlackWebhook URL, message templatesSlack notifications
KeywatcherKey directory, secret manager integrationJWT signing key management

Domain Inheritance

A convenience feature for deployment: setting the top-level Domain field automatically propagates to all config fields tagged with domain:"inherit".

domain: example.com

Fields tagged with domainPrefix or domainSuffix get the domain with a prefix or suffix applied:

  • domainPrefix:"api" resolves to api.example.com
  • domainPrefix:"auth" resolves to auth.example.com

This means you can configure a single domain value and have API URLs, auth URLs, and CDN URLs all derive from it automatically.

Sensitive Fields

Fields tagged with sensitive:"true" receive special handling:

WebhookURL string `json:"webhookurl" koanf:"webhookurl" sensitive:"true"`

Sensitive fields are:

  • Excluded from generated example configs and logged output
  • Mapped to Kubernetes secrets via External Secrets Operator in production
  • Sourced from GCP Secret Manager (or equivalent) rather than config files or plain environment variables

Current sensitive fields include Stripe webhook secrets, Slack webhook URLs, and GCP Secret Manager secret names.

Secret Management in Production

  1. Secret values are stored in an external secret manager (GCP Secret Manager)
  2. The External Secrets Operator syncs them into Kubernetes secrets
  3. Kubernetes injects them as environment variables
  4. The application's koanf loader picks them up through the standard CORE_ prefix mapping

Generated Artifacts

The configuration system generates deployment artifacts automatically:

ArtifactPurpose
helm-values.yamlHelm chart values derived from config struct
config.example.yamlExample configuration with defaults (sensitive fields omitted)
ConfigMap templatesKubernetes ConfigMap manifests for non-sensitive config
External Secrets templatesExternalSecret manifests for sensitive fields

Build Automation

CI workflows detect changes to the config struct and automatically:

  1. Regenerate Helm values and External Secrets templates
  2. Create a draft PR against the infrastructure repository
  3. Notify via Slack that config changes need review

This prevents drift between the application's config expectations and the deployed infrastructure.