Secrets in Production¶
Manage API keys, database passwords, and other secrets securely with forge.
The Problem¶
Hardcoding secrets is insecure. Environment variables are better but don't scale. You need a consistent way to load and validate secrets without exposing them in logs.
The Solution¶
forge's config module treats secret values as first-class citizens with automatic masking in logs.
Using SecretStr¶
from pydantic import BaseModel, Field
from pydantic import SecretStr
class DatabaseConfig(BaseModel):
url: SecretStr
password: SecretStr
Environment Variable Loading¶
# .env (never committed to git)
DATABASE_URL=postgresql://user:password@prod-db:5432/myapp
OPENAI_API_KEY=sk-proj-...
REDIS_URL=redis://:password@prod-redis:6379/0
from forge.config import ForgeConfig
config = ForgeConfig()
# Secrets are automatically loaded from environment
Secret Masking in Logs¶
forge automatically masks secret values in all log output:
logger.info("Connecting to database", url=config.database.url)
# Log output: {"url": "postgresql://user:****@prod-db:5432/myapp"}
Validation at Startup¶
Ensure required secrets are present before the app starts:
from forge.config import require
require(
"DATABASE_URL",
"OPENAI_API_KEY",
"REDIS_URL",
"JWT_SECRET",
)
# Raises ConfigurationError with clear message if any are missing
Production Best Practices¶
- Use a secrets manager (AWS Secrets Manager, Vault, GCP Secret Manager) in production
- Never commit
.envfiles to version control - Use
forge check configin CI to validate configuration before deployment - Rotate secrets regularly — forge's config module supports hot-reload
- Set
FORGE_DEBUG=falsein production to prevent accidental secret exposure