Deployment y DevOps

Cómo Configurar Secrets de Forma Segura en Vercel y Railway

2 de marzo de 2026
Vibe2Prod
5 min

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.

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

  1. Ve a tu proyecto en Vercel
  2. Settings → Environment Variables
  3. Agrega cada variable con nombre, valor y entorno de destino:
    • STRIPE_SECRET_KEYsk_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

  1. Abre tu proyecto en Railway
  2. Haz clic en "Variables"
  3. 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

  • [ ] .env en .gitignore
  • [ ] .env.example committeado (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

  1. Rótalo inmediatamente — Invalida la key comprometida en el proveedor (Stripe, OpenAI, etc.)
  2. Límpia el historial:
# Usa BFG Repo-Cleaner (más fácil que git filter-branch)
bfg --delete-files .env
  1. Fuerza push:
git push origin main --force
  1. 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:

  1. .env local con secretos
  2. .env en .gitignore
  3. .env.example committeado (sin valores reales)
  4. Secretos en Vercel/Railway dashboard
  5. Usa claves distintas en dev y producción
  6. 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