Lo esencial
El archivo .env es el llavero de tu casa. NUNCA lo dejas en la banqueta, es decir, nunca lo publicas en GitHub. El original lo guardas en una caja fuerte (1Password) y una copia se la das solo al sistema en el que confías (Cloudflare Secrets). Esta lección trata de cómo manejar bien las claves de API para no perder ni dinero ni reputación.
Conceptos clave
- Archivo .env: un archivo con variables de entorno; guarda secretos en tu computadora y nunca entra a Git
- process.env: la forma de leer variables del .env en el código (Node.js), o
os.environ(Python) - wrangler secret: guarda secretos de forma segura en Cloudflare Workers para producción
- 1Password: un gestor de contraseñas para guardar todas tus claves de API cifradas
- .gitignore: la lista de archivos que Git ignora (ahí va
.env) - Secretos de dev vs. prod: claves distintas para desarrollo y producción (límites, permisos)
- Rotación de claves: cambiar las claves periódicamente como medida de seguridad
Teoría
Por qué importa: el costo de un error
Historias típicas de foros y de GitHub Issues:
- Un desarrollador sube por accidente una clave de AWS en un commit → los bots encuentran esas claves en cuestión de minutos → en una noche llega una cuenta de miles de dólares
- Una clave de Anthropic en un repositorio público → alguien se gastó todo el límite en un fin de semana → el proyecto se cayó
- Una clave de API de Google sin restricciones → bots de spam la usaron para ataques
Una clave en un repositorio público de GitHub es dinero tirado en la calle. Alguien lo va a recoger.
Cómo se organiza el manejo seguro de claves
Tres niveles de almacenamiento:
1Password (almacén maestro)
↓ copias a mano
.env (desarrollo local)
↓ Claude Code lo lee con process.env
↓ NO entra a Git (.gitignore)
↓ al desplegar
Cloudflare Secrets / wrangler secret (producción)La regla de una sola fuente: 1Password es el único lugar donde viven los originales. Todo lo demás son copias temporales.
Paso 1: Crea bien tu .gitignore
Antes de crear cualquier otra cosa, crea .gitignore en la raíz del proyecto:
# Secretos: NUNCA en Git
.env
.env.local
.env.*.local
.env.production
# Logs
logs/
*.log
npm-debug.log*
# Dependencias
node_modules/
__pycache__/
*.pyc
# Del sistema
.DS_Store
.cursor/Comprueba que .env se ignora:
git status
# .env no debe aparecer en la lista de archivosSi .env ya entró a Git (un error):
git rm --cached .env
git commit -m "Remove .env from tracking"
# ¡Cambia todas las claves que había en ese archivo!La estructura real de .env en un proyecto típico
Así se ven organizadas las variables de entorno en un proyecto real:
project-root/
├── .env ← Claves reales (¡NO en Git!)
├── .env.example ← Plantilla sin valores (en Git)
├── .env.test ← Claves falsas (mock) para pruebas (no en Git)
├── .gitignore ← Contiene .env, .env.local, .env.*.local
├── validate-env.js ← Script que revisa que estén las claves
└── wrangler.toml ← Configuración de Cloudflare Workers (en proyectos nuevos Cloudflare crea wrangler.jsonc; el formato toml también se admite). Secretos de prod con wrangler secretPaso 2: Crea .env.example (plantilla sin valores)
Este archivo sí va a Git: muestra qué variables se necesitan, pero sin los valores reales:
# .env.example — COMMIT THIS FILE
# === Anthropic ===
# Dónde obtenerla: platform.claude.com → Settings → API Keys → Create Key
ANTHROPIC_API_KEY=sk-ant-your-key-here
# === Perplexity (para búsquedas) ===
# Dónde obtenerla: perplexity.ai → Settings → API
PERPLEXITY_API_KEY=pplx-your-key-here
# === Gmail API ===
# Dónde obtenerla: Google Cloud Console → Credentials → OAuth 2.0
GMAIL_CLIENT_ID=your-client-id.apps.googleusercontent.com
GMAIL_CLIENT_SECRET=GOCSPX-your-secret
GMAIL_REFRESH_TOKEN=1//your-refresh-token
# === Google Sheets ===
# El ID está en la URL de la hoja: docs.google.com/spreadsheets/d/THIS-IS-ID/edit
GOOGLE_SHEETS_ID=your-spreadsheet-id
# === Configuración de la app ===
NODE_ENV=development
LOG_LEVEL=infoLuego cópialo a tu .env real y llena los valores:
cp .env.example .env
# Abre .env y reemplaza todos los "your-key-here" con claves realesPaso 3: Lee las variables en el código
Node.js / JavaScript:
// Instala el paquete: npm install dotenv
require('dotenv').config();
// Lee las variables
const anthropicKey = process.env.ANTHROPIC_API_KEY;
const sheetsId = process.env.GOOGLE_SHEETS_ID;
// Revisa que existan antes de arrancar
function validateEnv() {
const required = ['ANTHROPIC_API_KEY', 'GMAIL_CLIENT_ID'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required env vars: ${missing.join(', ')}`);
}
}
validateEnv(); // Llámala al inicio de la appPython:
import os
from dotenv import load_dotenv
load_dotenv() # pip install python-dotenv
anthropic_key = os.environ.get('ANTHROPIC_API_KEY')
if not anthropic_key:
raise ValueError("No se encontró ANTHROPIC_API_KEY en .env")Lo que NUNCA debes hacer:
// ❌ Así no: la clave se ve en el código
const client = new Anthropic({ apiKey: "sk-ant-abc123..." });
// ✅ Así sí
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });Paso 4: Dev vs. prod, claves distintas para cada entorno
Por qué claves distintas:
- La clave de prod tiene un límite alto → un error accidental en desarrollo sale caro
- La clave de dev se puede revocar fácilmente sin tocar producción
- Permisos distintos (dev: solo lectura; prod: completos)
Estructura de archivos:
.env ← desarrollo local (no en Git)
.env.test ← para pruebas (puede tener claves falsas, no en Git)
.env.production ← no se usa directamente (los secretos van en Cloudflare)Cambiar de entorno:
const env = process.env.NODE_ENV || 'development';
console.log(`Running in ${env} mode`);
// development → lee .env
// production → los secretos llegan por el objeto env del worker (ver paso 5)Paso 5: Cloudflare Secrets para producción
Cuando despliegas en Cloudflare Workers, NO subes el .env. Usas wrangler secret:
# Guardar un secreto (wrangler te pide el valor de forma interactiva)
wrangler secret put ANTHROPIC_API_KEY
# Ver todos los secretos (solo muestra los nombres, no los valores)
wrangler secret list
# Borrar un secreto
wrangler secret delete OLD_API_KEYDespués de guardarlo con wrangler secret, en el Cloudflare Worker lo lees así:
// En un Cloudflare Worker, env es un objeto especial
export default {
async fetch(request, env) {
const key = env.ANTHROPIC_API_KEY; // ¡No process.env!
// ...
}
};Paso 6: 1Password, el almacén maestro
1Password guarda los originales de todas las claves. Una estructura que funciona:
1Password → Proyectos de IA (bóveda aparte)
├── Newsletter Automation
│ ├── Anthropic API Key (prod)
│ ├── Anthropic API Key (dev)
│ ├── Perplexity API Key
│ └── Gmail Credentials
├── Lead Gen Project
│ └── ...
└── Shared Infrastructure
├── Cloudflare API Token
└── GitHub TokenCómo usar 1Password CLI para llenar las claves automáticamente:
# Instalación: 1password.com/downloads/command-line
op signin
# Llenar .env automáticamente desde 1Password
op inject -i .env.example -o .envPara eso, en .env.example pones referencias a 1Password:
ANTHROPIC_API_KEY=op://AI-Projects/Newsletter/api-keyRotación de claves: cuándo y cómo
Cuándo cambiar las claves:
- Alguien del equipo se fue
- Sospechas una filtración
- Periódicamente, cada 3 a 6 meses (buena práctica)
- Después de cualquier incidente
El procedimiento:
- Crea una clave nueva en la consola del servicio
- Actualízala en 1Password
- Actualízala en Cloudflare con
wrangler secret put KEY_NAME - Comprueba que producción funciona
- Revoca la clave vieja
Nunca revoques primero la vieja: primero agrega la nueva, compruébala y luego quita la vieja.
Práctica
Tarea: configura de forma segura el entorno para Newsletter Automation
Crea la carpeta del proyecto e inicializa Git:
bash mkdir newsletter-automation && cd newsletter-automation git initCrea
.gitignore(copia la plantilla de esta lección)Crea
.env.examplecon todas las variables necesarias (sin valores)Cópialo a
.envy llena al menosANTHROPIC_API_KEY:bash cp .env.example .envEscribe
validate-env.js, un script que revise que todas las variables necesarias estén definidas:bash node validate-env.js # Debe mostrar: ✅ All required env vars are setHaz tu primer commit y asegúrate de que
.envno esté en la lista:bash git add . git status # .env no debe estar en la lista git commit -m "Initial setup with env template"(Opcional) Entra a 1Password, crea una bóveda aparte "AI Projects" y agrega tu clave de Anthropic
Objetivo: un entorno de trabajo donde ninguna clave entre a Git, pero todo el código las lea con process.env.
Herramientas y recursos
- Claude Console: crear y administrar claves de API de Anthropic
- 1Password: gestor de contraseñas con CLI y opción para compartir en equipo
- 1Password CLI: llena
.envautomáticamente desde la bóveda - dotenv (npm):
npm install dotenv, carga .env en Node.js - python-dotenv (pip):
pip install python-dotenv, carga .env en Python - Cloudflare Workers Secrets: guardar secretos de forma segura en producción
- wrangler:
npm install -g wrangler, la CLI para Cloudflare Workers y sus secretos - git-secrets: un hook de pre-commit que bloquea los commits con claves
- gitleaks: un escáner que busca secretos filtrados en repositorios de Git
Errores comunes
Error 1: Poner la clave en el código "solo un minuto" "Lo pruebo rápido y luego lo quito": se te olvidó, hiciste commit y la clave quedó para siempre en el historial de Git. Aunque borres el archivo, sigue en el historial de commits. La regla: ninguna clave en el código, nunca, ni por un segundo.
// ❌ NUNCA, ni siquiera "de forma temporal"
const client = new Anthropic({ apiKey: "sk-ant-abc123..." });
// ✅ SIEMPRE a través de una variable de entorno
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });Error 2: Una sola clave para dev y prod Un error en un script de prueba se acabó el límite de la clave de producción y producción se cayó. Siempre dos claves: dev con límite bajo y prod con el límite completo.
Error 3: Olvidar el .gitignore antes del primer commit .env entró en el primer commit. Ahora, aunque hagas git rm --cached .env, la clave sigue en el historial. La única solución: cambiar todas las claves de ese archivo.
Lecciones relacionadas
- Tu primer flujo de trabajo EN VIVO: uso práctico de
.enval crear un newsletter - Despliegue con Cloudflare Workers: cómo pasar los secretos de
.enva Cloudflare Workers conwrangler secret - Permisos y seguridad: prácticas avanzadas de control de acceso y rotación de claves
Ideas clave
El archivo .env es tu llavero local. A Git solo va
.env.example, una plantilla sin valores.
Nunca escribas claves directamente en el código. Ni siquiera en repositorios privados: un repositorio puede volverse público, o alguien puede obtener acceso.
Dev y prod usan claves distintas. Un error en desarrollo no debe costar dinero ni tumbar producción.
1Password es la única fuente de verdad. Todos los demás lugares son copias temporales.
Siguiente lección
La marca se guarda solo en este navegador y no se envía a ningún sitio. Mi progreso