Cómo Configurar Secrets de Forma Segura en Vercel y Railway
Tus API keys, contraseñas de BD y tokens de autenticación son el activo más valioso de tu app. Aquí te explico paso a paso cómo configurarlos correctamente en Vercel y Railway para evitar filtraciones.
Tabla de contenidos
- El error más común
- Conceptos básicos
- Configuración en Vercel
- Paso 1: Crea un archivo .env.local
- Paso 2: Agrega .env.local a .gitignore
- Paso 3: Agrega los secrets en el panel de Vercel
- Paso 4: Variables diferentes por entorno
- Paso 5: Accede en tu código
- Configuración en Railway
- Paso 1: Deploy conectando con GitHub
- Paso 2: Variables en Railway Dashboard
- Paso 3: Referencias entre variables
- Paso 4: Entornos separados
- Buenas prácticas
- 1. Nunca commitees .env
- 2. Crea .env.example
- 3. Rota los secrets con regularidad
- 4. Usa NEXTPUBLIC solo para data no sensible
- 5. Valida que los secrets existan al iniciar
- 6. Usa herramientas para detectar leaks
- Checklist
- Si ya committeaste un secret
- Resumen
- Referencias
Tus API keys, contraseñas de BD y tokens de autenticación son el activo más valioso de tu app.
Perderlos equivale a perder el control total de tu aplicación.
Aquí te muestro cómo mantenerlos seguros en Vercel y Railway.
El error más común
// ❌ NUNCA HAGAS ESTO
const STRIPE_KEY = "sk_live_1234567890abcdef";
const DB_PASSWORD = "MyPassword123!";
const JWT_SECRET = "supersecret";
export { STRIPE_KEY, DB_PASSWORD, JWT_SECRET };
Luego lo commiteas a GitHub. Y listo: tu app está comprometida.
Aunque lo borres después, el historial de Git lo conserva para siempre. Hay bots que escanean repositorios buscando exactamente patrones como sk_live_ o DB_PASSWORD.
Conceptos básicos
Variables de entorno (.env):
- Archivo local que NO commiteas a Git
- Almacena configuración sensible
- Su contenido varía entre dev y producción
Secretos en Vercel/Railway:
- Variables sincronizadas entre deployments
- Nunca visibles en logs
- Cifradas en reposo y en tránsito
Configuración en Vercel
Paso 1: Crea un archivo .env.local
En la raíz de tu proyecto:
NEXT_PUBLIC_API_URL=http://localhost:3000
STRIPE_SECRET_KEY=sk_test_123456
DATABASE_URL=postgresql://user:password@localhost/dbname
JWT_SECRET=my-super-secret-key-change-this-en-prod
API_KEY=sk_test_abc123
Importante: Solo usa NEXT_PUBLIC_ para variables que necesitan estar disponibles en el cliente (browser). El resto se mantienen privadas.
Paso 2: Agrega .env.local a .gitignore
# .gitignore
.env.local
.env.*.local
.env
Paso 3: Agrega los secrets en el panel de Vercel
- Ve a tu proyecto en Vercel
- Settings → Environment Variables
- Agrega cada variable con nombre, valor y entorno de destino:
STRIPE_SECRET_KEY→sk_live_1234567890abcdef→ Production
Repite esto para cada secret que tenga tu app.
Paso 4: Variables diferentes por entorno
En Vercel puedes tener valores diferentes por entorno:
Entorno: Development
STRIPE_SECRET_KEY=sk_test_123456
Entorno: Production
STRIPE_SECRET_KEY=sk_live_abcdef
Esto evita accidentalmente usar claves de producción en desarrollo.
Paso 5: Accede en tu código
// Privado (solo servidor)
const stripeKey = process.env.STRIPE_SECRET_KEY;
// Público (disponible en cliente)
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
Configuración en Railway
Paso 1: Deploy conectando con GitHub
Railway detecta tu proyecto automáticamente del repositorio.
Paso 2: Variables en Railway Dashboard
- Abre tu proyecto en Railway
- Haz clic en "Variables"
- Agrega con el editor RAW (JSON) o uno por uno
JSON editor:
{
"STRIPE_SECRET_KEY": "sk_live_1234567890abcdef",
"DATABASE_URL": "postgresql://user:pass@host/db",
"JWT_SECRET": "my-secret",
"NODE_ENV": "production"
}
Paso 3: Referencias entre variables
Railway permite referenciar otras variables:
DATABASE_URL=postgresql://user:${{ POSTGRES_PASSWORD }}@localhost/db
Paso 4: Entornos separados
Crea entornos separados para development y production, cada uno con sus propias variables.
Buenas prácticas
1. Nunca commitees .env
# .gitignore
.env
.env.local
.env.*.local
*.pem
2. Crea .env.example
Documenta qué variables se necesitan sin incluir valores reales:
# .env.example (commitea ESTO, no el .env real)
NEXT_PUBLIC_API_URL=http://localhost:3000
STRIPE_SECRET_KEY=sk_test_xxx
DATABASE_URL=postgresql://user:password@host/db
JWT_SECRET=your-secret-here
3. Rota los secrets con regularidad
- API keys: Cada 6 meses
- Contraseñas de BD: Cada 3 meses
- JWT secrets: Al cambiar versión mayor
4. Usa NEXT_PUBLIC_ solo para data no sensible
// ✅ OK (público)
NEXT_PUBLIC_API_URL=https://api.example.com
NEXT_PUBLIC_GA_ID=G-1234567890
// ❌ NUNCA (privado)
STRIPE_SECRET_KEY=sk_live_...
DATABASE_PASSWORD=...
5. Valida que los secrets existan al iniciar
// pages/api/webhook.ts
if (!process.env.STRIPE_SECRET_KEY) {
throw new Error('STRIPE_SECRET_KEY no está configurada');
}
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
Esto hace que el servidor falle rápido con un mensaje claro, en lugar de fallar en producción con un error críptico.
6. Usa herramientas para detectar leaks
# Escanea tu código en busca de secretos
npx @secretlint/secretlint "**/*"
# O usa Gitleaks
gitleaks detect --source . --verbose
Checklist
- [ ]
.enven.gitignore - [ ]
.env.examplecommitteado (sin secretos reales) - [ ] Todas las variables sensibles configuradas en Vercel/Railway
- [ ]
NEXT_PUBLIC_solo para data pública - [ ] Verificaste que no hay secrets en el historial de Git
- [ ] Claves diferentes para dev y producción
- [ ] Proceso de rotación de secretos definido
Si ya committeaste un secret
- Rótalo inmediatamente — Invalida la key comprometida en el proveedor (Stripe, OpenAI, etc.)
- Límpia el historial:
# Usa BFG Repo-Cleaner (más fácil que git filter-branch)
bfg --delete-files .env
- Fuerza push:
git push origin main --force
- Comunícalo a tu equipo — Todos deben hacer pull nuevamente
Resumen
Los secretos son críticos. Protégelos igual que tu contraseña bancaria.
Tl;dr:
.envlocal con secretos.enven.gitignore.env.examplecommitteado (sin valores reales)- Secretos en Vercel/Railway dashboard
- Usa claves distintas en dev y producción
- Rota periódicamente
Si necesitas auditoría de seguridad, contacta conmigo.
Referencias
[1] Next.js. (2024). Environment Variables. https://nextjs.org/docs/basic-features/environment-variables
[2] Railway. (2024). Environment Variables. https://docs.railway.app/develop/variables
[3] OWASP. (2024). Secrets Management Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html
¿Necesitas ayuda con tu app?
Si quieres revisar código, configuración o despliegue antes de abrir producción, vemos tu caso en una llamada de 30 minutos.
Agenda una llamada