Skip to content
Specific Docs
Esc
navigateopen⌘Jpreview
On this page

Secrets and config

Parameterize sensitive and environment-specific values without hardcoding them.

Secrets and config let you parameterize values that services need, instead of hardcoding them in specific.hcl:

  • Secrets - sensitive information that should never be committed to version control: API keys, database passwords, signing keys.
  • Config - non-sensitive values that may vary between environments: log levels, feature flags, URLs.

Because every value is declared in specific.hcl, Specific knows exactly which ones are missing and prompts you for them when needed, both when starting specific dev and when deploying to the cloud. There’s no .env file to assemble by hand.

Secrets

Declare the secrets your application needs and reference them in env:

secret "stripe_api_key" {}

secret "jwt_secret" {
  generated = true
}

service "api" {
  build = build.api
  command = "./api"

  endpoint {
    public = true
  }

  env = {
    STRIPE_API_KEY = secret.stripe_api_key
    JWT_SECRET = secret.jwt_secret
  }
}

Secret fields:

  • generated - when true, auto-generates a random string if no value is set. Useful for internal secrets like JWT signing keys.
  • length - length of generated secrets (default: 64). Only applies when generated = true.

Manual secrets (no generated flag) must be given a value: locally in specific.local, in production during deployment. Generated secrets are auto-created on first run, and you can still override them manually.

Config

config "log_level" {
  default = "info"
}

service "api" {
  build = build.api
  command = "./api"

  endpoint {
    public = true
  }

  env = {
    LOG_LEVEL = config.log_level
  }
}

Config fields:

  • default - value used unless overridden by an environment or locally.

Environment overrides

Override config values per environment with environment blocks:

config "log_level" {
  default = "info"
}

environment "production" {
  config = {
    log_level = "warn"
  }
}

environment "staging" {
  config = {
    log_level = "debug"
  }
}

Local development: specific.local

Local secret and config values live in specific.local, a gitignored HCL file next to specific.hcl:

secrets {
  stripe_api_key = "sk_test_..."
}

config {
  log_level = "debug"
}

You don’t have to fill it out ahead of time: specific dev prompts for any missing secrets and config values on startup. The file is never included in deployments.

Production

During specific deploy, the CLI checks that every required value is set for the target environment and prompts you interactively for anything missing. You can enter values while builds are still running. Values can also be passed as flags: specific deploy --secret stripe_api_key=sk_live_....

  • Secrets are stored securely, never logged, and injected into services as environment variables at runtime.
  • Secrets are scoped per environment - setting a secret for staging does not affect production.
  • Update secrets and config anytime from the dashboard, without touching specific.hcl. New values take effect on the next deployment.

Preview environments

Preview environments inherit their secrets and config values from the environment they branch from, so a preview starts with the parent’s configuration without re-entering anything.

To give previews a different value for a specific secret or config, set a preview override on the parent environment’s Secrets and config page in the dashboard. Every preview branched from that environment then uses the override for that value while still inheriting the rest - handy for pointing previews at a sandbox API key or a test-only endpoint. See Preview environments.

Complete example

# External API key: must be set manually, sensitive
secret "stripe_api_key" {}

# Internal signing key: auto-generated, sensitive
secret "jwt_secret" {
  generated = true
}

# Log level: not sensitive, varies by environment
config "log_level" {
  default = "info"
}

service "api" {
  build = build.api
  command = "./api"

  endpoint {
    public = true
  }

  env = {
    STRIPE_API_KEY = secret.stripe_api_key
    JWT_SECRET = secret.jwt_secret
    LOG_LEVEL = config.log_level
  }
}

environment "production" {
  config = {
    log_level = "warn"
  }
}

Was this page helpful?