Skip to content

Secrets Management

RAPID uses .envrc with direnv as the secure source of truth for project secrets. This approach ensures secrets are loaded dynamically, never stored in plaintext, and automatically available when entering a project directory.

Secure by default, easy to use.

  • Secrets are fetched just-in-time from secure vaults (1Password, HashiCorp Vault)
  • No plaintext secrets stored on disk
  • Automatic loading/unloading when entering/leaving project directories
  • Works seamlessly with dev containers
Terminal window
# macOS
brew install direnv
# Linux
sudo apt install direnv
# Add to shell (bash)
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
# Add to shell (zsh)
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
Terminal window
# macOS
brew install 1password-cli
# Sign in
eval $(op signin)
Terminal window
# Run in your project directory
rapid init

This creates a .envrc file configured for your project:

Terminal window
# .envrc - RAPID project secrets
# This file is safe to commit - it contains NO secrets, only references
# Load secrets from 1Password
export ANTHROPIC_API_KEY=$(op read "op://Development/Anthropic/api-key")
export OPENAI_API_KEY=$(op read "op://Development/OpenAI/api-key")
export GITHUB_TOKEN=$(op read "op://Development/GitHub/pat")
# Optional: Load from .env.local for non-sensitive overrides
[[ -f .env.local ]] && source_env .env.local
Terminal window
direnv allow

Now secrets automatically load when you cd into the project.


{
"secrets": {
"provider": "1password",
"vault": "Development",
"items": {
"ANTHROPIC_API_KEY": "op://Development/Anthropic/api-key",
"OPENAI_API_KEY": "op://Development/OpenAI/api-key",
"GITHUB_TOKEN": "op://Development/GitHub/pat"
},
"envrc": {
"generate": true,
"path": ".envrc"
}
}
}

When you run rapid init or rapid secrets generate, RAPID creates the .envrc from this config.


Best for individuals and teams. Secrets stored in 1Password vaults, fetched via CLI.

  1. Create a vault in 1Password (e.g., “Development”)
  2. Add items for each secret (API Credential type works well)
  3. Reference in rapid.json using op:// format
op://vault-name/item-name/field-name

Examples:

  • op://Development/Anthropic/api-key
  • op://Work/AWS/access-key-id
  • op://Personal/GitHub/token
.envrc
export ANTHROPIC_API_KEY=$(op read "op://Development/Anthropic/api-key")
export OPENAI_API_KEY=$(op read "op://Development/OpenAI/api-key")

Best for enterprise and teams with existing Vault infrastructure.

Terminal window
export VAULT_ADDR="https://vault.example.com"
vault login
{
"secrets": {
"provider": "vault",
"address": "https://vault.example.com",
"path": "secret/data/myproject",
"items": {
"ANTHROPIC_API_KEY": "anthropic_key",
"OPENAI_API_KEY": "openai_key"
}
}
}
.envrc
export VAULT_ADDR="https://vault.example.com"
export ANTHROPIC_API_KEY=$(vault kv get -field=anthropic_key secret/data/myproject)
export OPENAI_API_KEY=$(vault kv get -field=openai_key secret/data/myproject)

.env files are a security risk. They store secrets in plaintext on disk, making them vulnerable to:

  • Accidental git commits
  • Malicious npm/pip packages reading filesystem
  • Log file exposure
  • Backup/sync service leaks

RAPID will detect and load .env files, but with warnings:

{
"secrets": {
"provider": "env",
"dotenv": {
"enabled": true,
"files": [".env", ".env.local"],
"warn": true
}
}
}

Safer Alternative: .env.local for Non-Secrets

Section titled “Safer Alternative: .env.local for Non-Secrets”

Use .env.local for non-sensitive configuration only:

Terminal window
# .env.local (add to .gitignore)
# Non-sensitive overrides only!
LOG_LEVEL=debug
API_TIMEOUT=30000
# NEVER put secrets here:
# ANTHROPIC_API_KEY=sk-ant-... # DON'T DO THIS

Reference in .envrc:

.envrc
# Load secrets securely from 1Password
export ANTHROPIC_API_KEY=$(op read "op://Development/Anthropic/api-key")
# Load non-sensitive config from .env.local
[[ -f .env.local ]] && source_env .env.local

Generate .envrc from rapid.json configuration:

Terminal window
rapid secrets generate

Output:

Generated .envrc with 3 secrets
Run 'direnv allow' to activate

Verify all secrets are accessible:

Terminal window
rapid secrets verify

Output:

Verifying secrets...
ANTHROPIC_API_KEY (1password)
OPENAI_API_KEY (1password)
GITHUB_TOKEN (1password)
All secrets verified.

List configured secrets (names only, not values):

Terminal window
rapid secrets list

Output:

Configured secrets:
ANTHROPIC_API_KEY op://Development/Anthropic/api-key
OPENAI_API_KEY op://Development/OpenAI/api-key
GITHUB_TOKEN op://Development/GitHub/pat

  • Use 1Password or Vault for all secrets
  • Commit .envrc to git (it contains no secrets, only references)
  • Add .env* to .gitignore
  • Use separate vaults for dev/staging/prod
  • Rotate API keys periodically
  • Audit secret access in your vault
  • Store secrets in .env files
  • Commit any file containing actual secret values
  • Share API keys between projects
  • Use the same keys across environments
  • Log or print secret values
  • Store secrets in rapid.json
Terminal window
# Secrets - NEVER commit these
.env
.env.local
.env.*.local
*.pem
*.key
# .envrc is safe to commit (contains only references)
# !.envrc

When rapid start runs, it:

  1. Sources .envrc to get current secrets
  2. Passes them as environment variables to the container
  3. Secrets are available inside the container without being written to disk
Terminal window
# rapid start internally does something like:
source .envrc
devcontainer up --env ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
--env OPENAI_API_KEY="$OPENAI_API_KEY"

Secrets never touch the container filesystem - they exist only in memory as environment variables.


  1. Create a shared 1Password vault: “Team-ProjectName”
  2. Add team members to the vault
  3. Everyone uses the same .envrc:
Terminal window
# .envrc (committed to repo)
export ANTHROPIC_API_KEY=$(op read "op://Team-ProjectName/Anthropic/api-key")
export OPENAI_API_KEY=$(op read "op://Team-ProjectName/OpenAI/api-key")

Developers can override with personal credentials using .envrc.local:

Terminal window
# .envrc.local (gitignored)
export ANTHROPIC_API_KEY=$(op read "op://Personal/Anthropic/api-key")

Update .envrc to load it:

.envrc
export ANTHROPIC_API_KEY=$(op read "op://Team-ProjectName/Anthropic/api-key")
# Allow personal overrides
[[ -f .envrc.local ]] && source_env .envrc.local

Terminal window
direnv allow
Terminal window
eval $(op signin)

Verify the reference path:

Terminal window
op item get "Anthropic" --vault "Development"
Terminal window
# Verify they're loaded on host
echo $ANTHROPIC_API_KEY
# Verify rapid sees them
rapid secrets verify
# Restart container
rapid stop && rapid start

1Password caches credentials. If fetching is slow:

Terminal window
# Sign in again to refresh session
eval $(op signin)

If you have existing .env files:

For each secret in .env:

  1. Create an item in 1Password
  2. Add the secret value
{
"secrets": {
"provider": "1password",
"vault": "Development",
"items": {
"ANTHROPIC_API_KEY": "op://Development/Anthropic/api-key"
}
}
}
Terminal window
rapid secrets generate
direnv allow
Terminal window
rm .env

Ensure .env* patterns are in .gitignore.



MethodSecurityConvenienceRecommended
.envrc + 1PasswordHighHighYes
.envrc + VaultHighMediumYes (enterprise)
.env filesLowHighNo
Environment exportMediumLowFallback only

Use .envrc with 1Password or Vault. It’s secure, easy, and works seamlessly with RAPID and dev containers.