H
Hostess

Manage Secrets Across Environments

Create, scope, sync, and compare secrets across your deployment environments

Secrets are sensitive values — API keys, database credentials, tokens — that your services need at runtime but should never be committed to source control. Hostess provides a built-in secret store that encrypts and manages these values across all your environments.

In your hostess.yml, secrets are referenced using the ${secret:NAME} syntax:

hostess.yml
services:
  backend:
    type: fastapi
    build:
      source: ./backend
    env:
      JWT_SECRET: ${secret:JWT_SECRET}
      STRIPE_KEY: ${secret:STRIPE_API_KEY}
      SENDGRID_API_KEY: ${secret:SENDGRID_API_KEY}

This guide covers how to create, manage, sync, and compare secrets using the Hostess CLI.


Creating Secrets

From an environment variable

Terminal
export API_KEY="sk_test_abc123"
hostess secrets add API_KEY
✓ Secret 'API_KEY' added to production

When --value is omitted, hostess secrets add <name> reads the value from a local environment variable with the same name. If neither --value nor $NAME is set, the command fails instead of prompting interactively.

Inline value

In CI/CD, interpolate the value from a CI secret environment variable rather than hardcoding it:

Terminal
hostess secrets add STRIPE_KEY --value "$STRIPE_KEY"

Using --value can store the secret in your shell history. Prefer exporting the value from a password manager or CI secret first, then let the CLI read $SECRET_NAME:

Terminal
export STRIPE_KEY="$STRIPE_KEY_FROM_PASSWORD_MANAGER"
hostess secrets add STRIPE_KEY

Creating multiple secrets at once

Add several secrets in quick succession:

Terminal
export JWT_SECRET="$(openssl rand -base64 32)"
hostess secrets add JWT_SECRET
hostess secrets add STRIPE_KEY --value sk_live_abc123
export SENDGRID_API_KEY="SG.abc123"
hostess secrets add SENDGRID_API_KEY
hostess secrets add SENTRY_DSN --value https://abc123@sentry.io/456

Environment Scoping

By default, a secret is available in all environments. You can scope a secret to specific environments using the --envs flag:

Terminal
# Available in production only
hostess secrets add STRIPE_LIVE_KEY --envs production --value sk_live_abc123

# Available in both staging and production
hostess secrets add DATABASE_PASSWORD --envs production,staging --value "$DATABASE_PASSWORD"

# Available in preview environments only
hostess secrets add TEST_API_KEY --envs preview --value sk_test_xyz789

Why scope secrets?

Scoping prevents test keys from leaking into production and production keys from appearing in preview environments:

SecretProductionStagingPreview
STRIPE_LIVE_KEYsk_live_...--
STRIPE_TEST_KEY-sk_test_...sk_test_...
JWT_SECRETprod-jwt-...staging-jwt-...preview-jwt-...
SENTRY_DSNhttps://...https://...-

To set different values per environment, create the same secret name with different scopes:

Terminal
# Production Stripe key
hostess secrets add STRIPE_KEY --envs production --value sk_live_abc123

# Staging and preview use test key
hostess secrets add STRIPE_KEY --envs staging,preview --value sk_test_xyz789

Syncing with Local .env Files

Hostess can sync secrets between your local .env files and the remote secret store. This is useful for keeping local development aligned with deployed environments.

Push local secrets to Hostess

Upload all secrets from a local .env file to a specific environment:

Terminal
hostess secrets sync push --env production --file .env.production

This reads your .env.production file and creates or updates each key-value pair as a secret scoped to the production environment.

Example .env.production file:

.env.production
JWT_SECRET=super-secret-production-key
STRIPE_KEY=sk_live_abc123xyz
SENDGRID_API_KEY=SG.abc123
DATABASE_URL=postgresql://user:pass@host:5432/db
Terminal
hostess secrets sync push --env production --file .env.production

Sync Summary:
------------------------------
  Added:     4
  Updated:   0
  Unchanged: 0
------------------------------
  Total:     4 secrets synced

Pull remote secrets to local

Download secrets from a Hostess environment to a local file:

Terminal
hostess secrets sync pull --env production

This creates or overwrites a .env file with the current secret values from the specified environment.

You can also specify a custom output file:

Terminal
hostess secrets sync pull --env staging --file .env.staging

Never commit .env files to version control. Make sure your .gitignore includes:

.gitignore
.env
.env.*

Comparing Secrets Across Environments

The diff command shows which secrets exist in each environment and highlights differences:

Terminal
hostess secrets diff production staging

Secret Diff: production vs staging
==================================================

Only in production (1):
  - SENDGRID_API_KEY = SG.***123

Only in staging (1):
  + TEST_MODE = ***

Different values (1):
  JWT_SECRET:
    production: pro***ret
    staging: sta***ret

Identical (1):
  = SENTRY_DSN

This is especially useful before promoting staging to production, to ensure all required secrets are present.


Editing and Rotating Secrets

Update an existing secret

To change a secret's value, use hostess secrets edit. The add command skips environments where that secret already exists and tells you to use edit instead.

Terminal
export JWT_SECRET="$(openssl rand -base64 32)"
hostess secrets edit JWT_SECRET
✓ Secret 'JWT_SECRET' updated in production
✓ Secret 'JWT_SECRET' updated in staging

Rotation workflow

When rotating a secret (e.g., after a key compromise or on a regular schedule):

Update the secret value

Terminal
hostess secrets edit STRIPE_KEY --envs production --value sk_live_new_key

Redeploy to apply

Secrets are injected at deploy time. After updating a secret, redeploy the affected services:

Terminal
hostess deploy

Or deploy only the services that use the rotated secret:

Terminal
hostess deploy -s backend -s worker

Verify the service is running with the new value

Check your deployment status in Studio or via the CLI:

Terminal
hostess deployments list

Updating a secret does not automatically redeploy your services. You must trigger a new deployment for the updated value to take effect.


Listing Secrets

View all secrets for your project:

Terminal
hostess secrets get
Environment: production
--------------------------------------------------
KEY         | VALUE
----------------------
JWT_SECRET  | pro***ret
STRIPE_KEY  | sk_***xyz


Environment: staging
--------------------------------------------------
KEY              | VALUE
---------------------------
JWT_SECRET       | sta***ret
STRIPE_TEST_KEY  | sk_***789

By default, secret values are masked in the CLI. Use hostess secrets get --show-values when you need to reveal values (treat output like a password).


Deleting Secrets

Remove a secret that is no longer needed:

Terminal
hostess secrets delete OLD_API_KEY
✓ Secret 'OLD_API_KEY' deleted from production
✓ Secret 'OLD_API_KEY' deleted from staging

Deleting a secret that is still referenced in hostess.yml will cause your next deployment to fail. Remove the ${secret:NAME} reference from your configuration before deleting the secret.


Referencing Secrets in hostess.yml

Secrets are referenced in environment variables using the ${secret:NAME} syntax:

hostess.yml
services:
  backend:
    type: fastapi
    build:
      source: ./backend
    env:
      # Secret references
      JWT_SECRET: ${secret:JWT_SECRET}
      STRIPE_KEY: ${secret:STRIPE_KEY}
      SENDGRID_API_KEY: ${secret:SENDGRID_API_KEY}

      # Regular environment variables (not secrets)
      LOG_LEVEL: info
      NODE_ENV: production

      # Magic variables (service discovery, not secrets)
      DATABASE_URL: ${database.url}
      REDIS_URL: ${cache.url}

If a referenced secret does not exist in the Hostess secret store, the deployment will fail with a clear error message telling you which secret is missing.


Best Practices

Naming conventions

Use consistent, uppercase naming with underscores:

GoodBad
STRIPE_API_KEYstripe-api-key
DATABASE_PASSWORDdbPassword
SENDGRID_API_KEYSendGrid_Key
JWT_SIGNING_SECRETjwt

Prefix secrets by service or provider for clarity:

Terminal
STRIPE_API_KEY
STRIPE_WEBHOOK_SECRET
SENDGRID_API_KEY
SENDGRID_TEMPLATE_ID
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
SENTRY_DSN

Rotation schedule

Set up a regular rotation schedule for sensitive credentials:

Secret TypeRecommended Rotation
API keys (third-party)Every 90 days
JWT signing secretsEvery 90 days
Database passwordsEvery 180 days
Webhook secretsWhen compromised
OAuth client secretsEvery 90 days

Environment separation

  • Never share production API keys with preview or staging environments
  • Use test/sandbox keys from third-party services for non-production environments
  • Scope secrets to the minimum number of environments they need

Do not duplicate database URLs

Hostess automatically provides database connection URLs via magic variables like ${database.url}. Do not store database URLs as secrets — use magic variables instead:

hostess.yml
services:
  backend:
    env:
      # Correct — use magic variable
      DATABASE_URL: ${database.url}

      # Incorrect — do not store as a secret
      # DATABASE_URL: ${secret:DATABASE_URL}
Manage Secrets Across Environments | Hostess Docs