← volver al blog

Migrando secretos de equipo a SOPS + Age: del caos al control

Cómo dejamos de pasarnos .env por Slack y migramos a un flujo de secretos cifrados con SOPS y Age integrado al CI.

El problema

Cada vez que un dev nuevo entraba al equipo, el onboarding de secretos era un ritual:

  1. Pedir los .env por Slack DM
  2. Copiarlos a mano en cada repo
  3. Rezar para que estuvieran actualizados
# Lo que nadie quiere ver en su historial de Slack
cat .env | pbcopy
# "te lo mando por acá rapidito"

La solución: SOPS + Age

SOPS cifra archivos de configuración manteniendo las keys en texto plano y los values cifrados. Age es el backend de cifrado — más simple que GPG, sin keyservers.

# secrets.enc.yaml — se puede commitear sin miedo
database_url: ENC[AES256_GCM,data:abc123...,type:str]
api_key: ENC[AES256_GCM,data:def456...,type:str]

Setup inicial

# Generar key de Age
age-keygen -o keys.txt

# Crear archivo de configuración de SOPS
cat > .sops.yaml << 'EOF'
creation_rules:
  - path_regex: \.enc\.(yaml|json)$
    age: >-
      age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
EOF

# Cifrar
sops -e secrets.yaml > secrets.enc.yaml

Integración con CI

En Bitbucket Pipelines, el Age key se inyecta como variable de entorno:

# bitbucket-pipelines.yml
- step:
    name: Deploy
    script:
      - export SOPS_AGE_KEY=$AGE_SECRET_KEY
      - sops -d secrets.enc.yaml > .env
      - npm run deploy

Resultado

  • Zero secretos en Slack desde la migración
  • Los .enc.yaml viven en el repo — el historial de cambios queda en git
  • Onboarding de nuevo dev: compartir un Age key, nada más