Doppler · Gestión de Secretos y Variables de Entorno

CULTIVA IA · Migración y centralización de secretos · Junio 2026
🔧 Doppler CLI ✓ 3 proyectos 🔑 11 secretos migrados ⚡ CI/CD tokens
Situación anterior
⚠️ Riesgos detectados en CULTIVA IA antes de la migración
Estructura en Doppler
📂 Árbol de proyectos y configs
📦 cultiva-api (FastAPI + Claude/GPT-4o)
● dev  — localhost, sk-test-*, debug
● stg  — staging DB, sk-test-*, warn
● prd  — prod DB, sk-live-*, sentry

📦 cultiva-worker (Celery + Redis)
● dev  — redis local, debug
● prd  — redis.prod.cultiva.ai

📦 cultiva-web (Next.js Vercel)
● preview — variables NEXT_PUBLIC_*
● prd  — variables NEXT_PUBLIC_* prod
🚀 Migración desde .env — Comandos ejecutados
# 1. Subir dev secrets desde archivo .env $ doppler secrets upload .env \ -p cultiva-api -c dev ✓ Uploaded 6 secrets to cultiva-api (dev) # 2. Verificar importación $ doppler secrets -p cultiva-api -c dev NAME VISIBILITY DATABASE_URL •••••••••••••••••• REDIS_URL •••••••••••••••••• OPENAI_API_KEY •••••••••••••••••• ANTHROPIC_API_KEY •••••••••••••••••• JWT_SECRET •••••••••••••••••• LOG_LEVEL debug # 3. Eliminar .env del repo $ echo ".env" >> .gitignore $ git rm --cached .env rm '.env'
Secretos — cultiva-api / producción
🔑 Inventario completo — cultiva-api · prd
Nombre Valor (enmascarado) Visibilidad Tipo Entorno anterior
DATABASE_URL postgresql://db.prod.cultiva.ai:5432/cult•••• normal string .env local
REDIS_URL redis://redis.prod.cultiva.ai:6379/•••• normal string .env local
OPENAI_API_KEY sk-live-•••••••••••••••••••••••••••••• restricted string GitHub Secret (expuesto)
ANTHROPIC_API_KEY sk-ant-live-•••••••••••••••••••••••••• restricted string GitHub Secret
JWT_SECRET •••••••••••••••••••••••••••••••••••••••••••••••••••••• restricted string .env (commiteado ⚠️)
LOG_LEVEL warn normal string .env local
SENTRY_DSN https://••••••@sentry.io/•••• normal string hardcoded en código 😱
Configuración de proyectos y ejecución
⚙️ Setup por servicio
# cultiva-api (FastAPI) $ doppler setup \ --project cultiva-api \ --config dev \ --no-interactive # cultiva-worker (Celery) $ doppler setup \ --project cultiva-worker \ --config dev \ --no-interactive # Configurar historial (evitar leaks en shell) $ echo "HISTIGNORE='*doppler secrets set*'" >> ~/.zshrc
▶️ Inyección de secretos en ejecución
# Antes (inseguro) source .env && uvicorn main:app --reload # Ahora (Doppler) $ doppler run -- uvicorn main:app --reload ✓ Injected 7 secrets into process # Worker Celery $ doppler run -p cultiva-worker -- \ celery -A tasks worker # Secretos como camelCase para SDK JS $ doppler run \ --name-transformer camel -- \ node scripts/sync.js # ANTHROPIC_API_KEY → anthropicApiKey
Comandos CRUD de secretos
📝 Gestión individual y bulk
# Establecer secreto restringido (API keys sensibles) $ doppler secrets set \ OPENAI_API_KEY="sk-live-xxxxxxxxxxxxxxxx" \ --visibility restricted \ -p cultiva-api -c prd # Leer valor único (para scripts de deploy) $ doppler secrets get DATABASE_URL --plain \ -p cultiva-api -c prd postgresql://db.prod.cultiva.ai:5432/cultiva # Exportar secrets como .env para emergencias $ doppler secrets download \ --no-file --format=env \ -p cultiva-api -c dev > .env.backup $ chmod 600 .env.backup
Tokens de servicio para CI/CD
🤖 Service tokens — GitHub Actions
cultiva-api · prd · github-actions
TTL 720h restricted read
dp.st.prd.AbCdEf1234567890xxxxxxxxxxxxxxxxxxxxxxxxxxxx copiar
cultiva-worker · prd · github-actions
TTL 720h restricted read
dp.st.prd.XyZaBc9876543210yyyyyyyyyyyyyyyyyyyyyyyy copiar
# Crear token con TTL de 30 días $ doppler configs tokens create github-actions \ -p cultiva-api -c prd \ --max-age 720h --plain # .github/workflows/deploy.yml env: DOPPLER_TOKEN: ${{ secrets.DOPPLER_TOKEN_CULTIVA_API }} steps: - run: doppler run -- ./deploy.sh
Integraciones Docker y Kubernetes
⚙️

GitHub Actions

Token de servicio dp.st.prd.* en repository secrets. Doppler inyecta en cada job sin exponer valores.

🐳

Docker Compose

doppler run -- docker compose up pasa secretos como env vars al contenedor sin escribir archivos en disco.

☸️

Kubernetes Secret

kubectl create secret generic app-secrets --from-env-file <(doppler secrets download --format docker)

Onboarding equipo (3 developers)
👩‍💻 Guía de incorporación — 4 pasos, 2 minutos
PASO 1 — INSTALAR CLI brew install dopplerhq/cli/doppler
PASO 2 — AUTENTICARSE doppler login   # abre browser → OAuth con cuenta de empresa
PASO 3 — VINCULAR PROYECTO cd ~/projects/cultiva-api && doppler setup   # selecciona cultiva-api → dev
PASO 4 — ARRANCAR LA APP doppler run -- uvicorn main:app --reload   # ✓ sin .env, sin copiar nada, siempre actualizado
Comparativa antes vs. ahora
📊 .env files vs. Doppler centralizado
Característica .env files (antes) Doppler (ahora)
Secretos en git Riesgo real (ocurrió) Imposible por diseño
Sincronización equipo Manual, propenso a errores Automática en tiempo real
Rotación de secretos Actualizar N archivos Un cambio, todos los envs
Auditoría de accesos Ninguna Log completo en dashboard
CI/CD tokens ~ GitHub Secrets sin TTL Tokens con max-age rotables
Onboarding nuevo dev Pedir .env manualmente doppler login + setup
Secretos en Docker/K8s ~ Archivos en disco Inyección en memoria, sin archivos
Flujo completo de migración
🗂️ Pasos ejecutados — cultiva-api
1
Instalar Doppler CLI y autenticar
brew install + doppler login con cuenta corporativa alvarogimeno2002@gmail.com
$ doppler me Name: Álvaro Gimeno Email: alvarogimeno2002@gmail.com Workplace: CULTIVA IA
2
Subir secretos existentes desde .env
Importación masiva preservando nombres exactos. Sin tocar el código.
$ doppler secrets upload .env.prd \ -p cultiva-api -c prd ✓ Uploaded 7 secrets successfully
3
Marcar secretos sensibles como restricted
OPENAI_API_KEY, ANTHROPIC_API_KEY y JWT_SECRET solo visibles para admins.
$ doppler secrets set \ JWT_SECRET="$(openssl rand -hex 32)" \ --visibility restricted \ -p cultiva-api -c prd
4
Crear tokens de servicio para GitHub Actions
Token con TTL 720h (30 días) para el pipeline de deploy automático.
$ doppler configs tokens create github-deploy \ -p cultiva-api -c prd \ --max-age 720h --plain
5
Limpiar .env del repositorio
Eliminar archivos sensibles del historial de git y añadir al .gitignore.
$ git rm --cached .env .env.prd $ echo ".env*" >> .gitignore ✓ .env files removed from git tracking