Appearance
Secrets Management
Secure handling of sensitive configuration data across all Jubiloop environments.
Overview
Jubiloop uses a multi-layered approach to secrets management:
- GitHub Secrets - Primary storage for CI/CD secrets
- Environment Variables - Runtime injection of secrets
- 1Password - Team access and secret sharing
- Automated Discovery - Scripts to identify required secrets
Secret Storage
GitHub Secrets
All deployment secrets are stored in GitHub:
- Repository-level secrets
- Environment-specific secrets
- Encrypted at rest
- Access controlled by GitHub permissions
Adding Secrets:
bash
# Via GitHub UI
Settings → Secrets and Variables → Actions → New repository secret
# Secret naming convention
{ENVIRONMENT}_{SERVICE}_{KEY_NAME}1Password Vault
Team secrets are documented in 1Password:
- Jubiloop vault for shared access
- Environment-specific sections
- Secure notes for context
- API keys and credentials
Secret Types
Application Secrets
Database Credentials
- PostgreSQL passwords
- Redis passwords
- Connection strings
API Keys
- Third-party service keys
- OAuth credentials
- Webhook secrets
Encryption Keys
- JWT secrets
- Session keys
- Encryption passwords
Infrastructure Secrets
Cloud Provider
- DigitalOcean API tokens
- Cloudflare API keys
- Terraform state credentials
Deployment
- SSH private keys
- Ansible vault passwords
- Container registry tokens
Secret Patterns
Auto-Generated Names
Using from_secrets in configuration:
yaml
DEV:
server:
APP_KEY: 'from_secrets'
# Generates: DEV_SERVER_APP_KEYExplicit References
For shared secrets between services:
yaml
DEV:
server:
DB_PASSWORD: '${{ secrets.DEV_POSTGRES_PASSWORD }}'
postgres:
POSTGRES_PASSWORD: '${{ secrets.DEV_POSTGRES_PASSWORD }}'Secret Discovery
List Required Secrets
bash
cd infra/deploy
# All secrets
node scripts/extract-config.js list-secrets
# Environment-specific
node scripts/extract-config.js list-secrets --env devVerify Secret Configuration
bash
# Check missing secrets
node scripts/generate-env-files.js DEV --list-secrets
# Generate documentation
node scripts/extract-config.js documentationSecurity Best Practices
Secret Generation
Strong Passwords:
bash
# Generate secure password
openssl rand -base64 32
# Generate hex string
openssl rand -hex 32API Key Format:
- Minimum 32 characters
- Include special characters
- Avoid predictable patterns
Access Control
Principle of Least Privilege:
- Only necessary team members
- Environment-specific access
- Regular access reviews
Secret Sharing:
- Never share via chat/email
- Use 1Password for sharing
- Document access in team wiki
Audit and Compliance
Secret Usage Tracking:
- GitHub audit logs
- Deployment logs
- Access monitoring
Regular Audits:
- Quarterly secret review
- Access permission audit
- Unused secret cleanup
Common Secret Patterns
Database URLs
yaml
# Pattern
DATABASE_URL: 'postgresql://user:${{ secrets.DB_PASS }}@host:5432/db'
# Separate components
DB_HOST: 'localhost'
DB_USER: 'app_user'
DB_PASSWORD: '${{ secrets.DEV_DB_PASSWORD }}'
DB_NAME: 'jubiloop_dev'API Configuration
yaml
# External service pattern
STRIPE_PUBLIC_KEY: 'pk_test_...'
STRIPE_SECRET_KEY: '${{ secrets.DEV_STRIPE_SECRET }}'
STRIPE_WEBHOOK_SECRET: '${{ secrets.DEV_STRIPE_WEBHOOK }}'Sanity Studio Deploy Token
For hosted Studio deployments in CI, use SANITY_STUDIO_DEPLOY_TOKEN (repo secret), mapped to SANITY_AUTH_TOKEN in the workflow step that runs:
yaml
- name: Deploy Sanity Studio
env:
SANITY_AUTH_TOKEN: ${{ secrets.SANITY_STUDIO_DEPLOY_TOKEN }}
run: npx --yes sanity@latest deploy --non-interactive --tag $ENVIRONMENTThis token is only required for the CLI deployment step and is not used by the marketing site at runtime.
Troubleshooting
Secret Not Found
- Check exact secret name (case-sensitive)
- Verify secret exists in GitHub
- Check environment spelling
- Review deployment logs
Invalid Secret Format
- Check for special characters
- Verify encoding (base64 if needed)
- Check length requirements
- Test locally with dry-run
Access Denied
- Verify GitHub permissions
- Check environment access
- Contact team admin
- Review audit logs
Emergency Procedures
Compromised Secret
Immediate Actions:
- Revoke compromised secret
- Generate new secret
- Update all environments
Investigation:
- Review access logs
- Identify exposure scope
- Document incident
Remediation:
- Deploy new secrets
- Monitor for misuse
- Update security procedures
Recovery Process
- Access 1Password backup
- Regenerate from source
- Contact service provider
- Update all references
Documentation
Required Documentation
For each secret:
- Purpose and usage
- Format requirements
- Source (if external service)
- Dependencies
Secret Inventory
Maintain inventory in 1Password:
- Service name
- Environment
- Last rotation date
- Owner/contact