Environment variables

Prerequisites: Container configuration

Environment variables are the primary mechanism for configuring containers in Clouve. The platform extends the standard concept with a type system that controls how each variable is stored, presented, and managed at deployment time.


Why types matter

A standard Docker Compose file treats every environment variable the same way. Clouve's type system is what lets the platform:

  • Store sensitive values in Kubernetes Secrets, encrypted at rest
  • Store non-sensitive values in Kubernetes ConfigMaps
  • Prompt business users to fill in values at deployment time
  • Resolve inter-container hostnames and generate application credentials automatically
  • Fill in URLs based on the deployment's DNS configuration

The eight variable types

static

A fixed configuration value that never changes at deployment time. Stored in a Kubernetes ConfigMap.

Use it for:

  • Application mode (production, debug)
  • Feature flags (true, false)
  • Non-sensitive configuration values
  • Database names and usernames that are not secrets
environment:
  NODE_ENV: production
  DEBUG: "false"
  DB_NAME: wordpress
  TABLE_PREFIX: wp_

x-clouve-environment-types:
  NODE_ENV: static
  DEBUG: static
  DB_NAME: static
  TABLE_PREFIX: static

secret

A sensitive value that must be stored encrypted. Stored in a Kubernetes Secret (base64-encoded and access-controlled).

Use it for:

  • Database passwords
  • API keys and tokens
  • JWT signing secrets
  • OAuth client secrets
  • Any credential or private key
environment:
  DB_PASSWORD: changeme
  JWT_SECRET: changeme
  STRIPE_API_KEY: changeme

x-clouve-environment-types:
  DB_PASSWORD: secret
  JWT_SECRET: secret
  STRIPE_API_KEY: secret

The values in the manifest are only defaults, and business users can override them at deployment time. Put placeholders in your manifest, never real secrets.


userConfigurable

A value the business user is expected to customize when deploying the application. Once the user fills it in, it is stored in a Kubernetes ConfigMap.

Use it for:

  • Admin email address
  • Site name or title
  • Application theme
  • Custom domain
  • Configuration that varies per organization
environment:
  SITE_TITLE: My WordPress Site
  ADMIN_EMAIL: admin@example.com
  APP_THEME: light
  MAX_UPLOAD_SIZE: "64M"

x-clouve-environment-types:
  SITE_TITLE: userConfigurable
  ADMIN_EMAIL: userConfigurable
  APP_THEME: userConfigurable
  MAX_UPLOAD_SIZE: userConfigurable

The value you provide is the default shown to the user in the deployment form.


containerReference

A reference to another container in the same application; the value is that container's name. Stored in a Kubernetes ConfigMap and automatically prefixed with the ticket ID at deployment time.

Use it for:

  • Database hostnames (DB_HOST, REDIS_HOST, DATABASE_URL)
  • Any variable whose value is another container's internal DNS name
# In the wordpress container:
environment:
  WORDPRESS_DB_HOST: wordpress-mariadb
  REDIS_HOST: wordpress-redis

x-clouve-environment-types:
  WORDPRESS_DB_HOST: containerReference
  REDIS_HOST: containerReference

The platform resolves the container name to the correct internal hostname in the Kubernetes namespace. Never hardcode IP addresses.

The value must exactly match the container name of the target service. If the target container is named postgres-db, the variable value must be postgres-db.


applicationUsername

A username field for the application's admin credentials. The business user fills it in on the deployment form and the platform injects it as a variable.

Use it for:

  • The admin username of a CMS (WordPress, Moodle)
  • The primary user account's username
environment:
  ADMIN_USER: admin

x-clouve-environment-types:
  ADMIN_USER: applicationUsername

The value you provide is a suggested default; the deploying user can change it.


applicationPassword

A password field for the application's admin credentials, shown to the deploying user as a masked input. Like applicationUsername, it is collected on the deployment form and injected as a variable.

Use it for:

  • The admin password of a CMS or application
  • Any credential the deploying user should set themselves
environment:
  ADMIN_PASSWORD: changeme

x-clouve-environment-types:
  ADMIN_PASSWORD: applicationPassword

applicationUrl

The full HTTPS URL at which the application will be accessible. The platform generates it from the deployment's DNS configuration and stores it in a Kubernetes ConfigMap at deployment time.

Use it when:

  • The application needs to know its own public URL, for generating links, redirects, API callbacks, or OAuth redirect URIs
  • Setting WordPress SITE_URL / HOME_URL
  • Filling any BASE_URL or APP_URL variable
environment:
  WORDPRESS_SITE_URL: ""
  APP_PUBLIC_URL: ""

x-clouve-environment-types:
  WORDPRESS_SITE_URL: applicationUrl
  APP_PUBLIC_URL: applicationUrl

The platform ignores the value you provide and replaces it with the actual deployment URL at runtime, for example https://myworkspace.clouve.dev.


applicationHost

The hostname (without protocol) at which the application will be accessible, also generated by the platform and stored in a Kubernetes ConfigMap at deployment time.

Use it when:

  • Your application needs just the hostname portion, for CORS configuration or a TLS cert subject
  • You need the hostname separately from the URL
environment:
  APP_HOST: ""
  CORS_ORIGIN: ""

x-clouve-environment-types:
  APP_HOST: applicationHost
  CORS_ORIGIN: applicationHost

Type reference

TypeStorageUser Fills In?Platform Generates?Use For
staticConfigMapNoNoFixed config
secretSecretAt deploy (optional)NoPasswords, keys
userConfigurableConfigMapYesNoPer-org settings
containerReferenceConfigMapNoResolvedInter-container hostnames
applicationUsernameFormYesNoAdmin username
applicationPasswordSecretYesNoAdmin password
applicationUrlConfigMapNoYesApp's own URL
applicationHostConfigMapNoYesApp's own hostname

A note on applicationPassword storage: the user fills it in on the deploy form, but the value is written into the Kubernetes Secret (not the ConfigMap) alongside secret-typed variables. Tropo's GetSecretVars includes both types. Treat it as a credential at rest.

UI labels and manifest values

The manifest and API use the canonical type strings above. The container-configuration UI shows friendlier labels:

UI labelManifest / API value
Staticstatic
Secretsecret
User InputuserConfigurable
Container ReferencecontainerReference
Application UsernameapplicationUsername
Application PasswordapplicationPassword
Application URLapplicationUrl
Application HostapplicationHost

Either form is valid in the YAML upload. The downloader always normalizes to the lowercase manifest value, so the file is round-trip stable.


Naming conventions

Environment variable names must be valid shell variable names. UPPERCASE_SNAKE_CASE is both the convention and a requirement: use only alphanumeric characters and underscores, start with a letter or underscore, and avoid spaces, hyphens, and dots.

✅ DATABASE_URL
✅ JWT_SECRET
✅ ADMIN_EMAIL_ADDRESS
✅ MAX_CONNECTIONS

❌ database-url
❌ jwt.secret
❌ 1_INVALID

Security best practices

  1. Never use static for sensitive data. If a value is a credential, store it as secret, even when it looks innocuous.

  2. Use placeholder values for secrets in your manifest. The manifest may sit in version control or be reviewed by others, so write changeme or <replace-me> instead of a real secret.

  3. Mark every password as secret or applicationPassword so it is stored in a Kubernetes Secret and not exposed in a ConfigMap.

  4. Use applicationUrl for self-referencing URLs. Deployments use dynamically assigned subdomains, so never hardcode a domain.

  5. Fill in the description field for every variable. Business users see this description when deploying.


Complete example: Node.js backend

environment:
  # Database connection
  DB_HOST: postgres-db
  DB_PORT: "5432"
  DB_NAME: appdb
  DB_USER: appuser
  DB_PASSWORD: changeme

  # Application config
  NODE_ENV: production
  PORT: "3000"
  LOG_LEVEL: info

  # Auth
  JWT_SECRET: changeme
  JWT_EXPIRES_IN: 7d

  # External service
  STRIPE_SECRET_KEY: changeme
  SENDGRID_API_KEY: changeme

  # Self-reference
  API_BASE_URL: ""

  # User-customizable
  MAX_CONNECTIONS: "100"
  ALLOWED_ORIGINS: ""

x-clouve-environment-types:
  DB_HOST: containerReference
  DB_PORT: static
  DB_NAME: static
  DB_USER: static
  DB_PASSWORD: secret

  NODE_ENV: static
  PORT: static
  LOG_LEVEL: static

  JWT_SECRET: secret
  JWT_EXPIRES_IN: static

  STRIPE_SECRET_KEY: secret
  SENDGRID_API_KEY: secret

  API_BASE_URL: applicationUrl

  MAX_CONNECTIONS: userConfigurable
  ALLOWED_ORIGINS: userConfigurable

Troubleshooting

Container can't connect to the database. Check that DB_HOST (or its equivalent) is typed as containerReference and that its value exactly matches the database container's name.

Application uses the wrong URL in generated links. Add an applicationUrl-typed variable and inject it into your application as the base URL. Do not hardcode a domain.

Secrets are visible in logs. Make sure your application does not log secret-typed variables; add filtering to your logging middleware.

A user-configurable variable shows the wrong default. The value field in your manifest is the default shown to users. Set it to a sensible default, or an empty string if there is no good one.


Next steps