Apariencia
Variables de entorno
Referencia exhaustiva de cada variable que debe estar definida en producción, dividida en backend (Laravel) y frontend (Next.js).
Nunca commitear
.env, .env.production, .env.local — todos están en .gitignore. Si un secret se filtra al repo, rota la key inmediatamente y borra el commit del historial (git filter-repo).
Backend
Ubicación: humae_backend/.env en el servidor de producción.
Copia humae_backend/.env.example como punto de partida y reemplaza valores.
Aplicación
| Variable | Valor prod | Descripción |
|---|---|---|
APP_NAME | HUMAE | Nombre de la app (aparece en correos) |
APP_ENV | production | Habilita optimizaciones de Laravel |
APP_KEY | base64:... | Generar con php artisan key:generate |
APP_DEBUG | false | Crítico: true en prod expone stacktraces |
APP_URL | https://api.humae.com.mx | URL base del backend |
APP_TIMEZONE | America/Mexico_City | Para timestamps server-side |
APP_LOCALE | es_MX | Mensajes de validación en español |
Frontend coupling (CORS + Sanctum)
| Variable | Valor prod |
|---|---|
FRONTEND_URL | https://humae.com.mx |
SANCTUM_STATEFUL_DOMAINS | humae.com.mx,www.humae.com.mx |
SESSION_DOMAIN | .humae.com.mx |
SESSION_SECURE_COOKIE | true |
SESSION_SAME_SITE | lax |
CORS
El backend solo acepta requests desde FRONTEND_URL. Si agregas un dominio adicional (preview, staging), debes ampliar la lista en config/cors.php y SANCTUM_STATEFUL_DOMAINS.
Base de datos
| Variable | Valor prod |
|---|---|
DB_CONNECTION | mysql |
DB_HOST | IP o hostname del servidor MySQL |
DB_PORT | 3306 |
DB_DATABASE | humae_production |
DB_USERNAME | usuario con acceso solo a esa DB |
DB_PASSWORD | password fuerte (≥24 chars) |
DB_SOCKET | (vacío salvo uso de socket) |
Redis (cache + queue + sesiones)
| Variable | Valor prod |
|---|---|
REDIS_HOST | IP o hostname |
REDIS_PORT | 6379 |
REDIS_PASSWORD | password (obligatorio en prod) |
REDIS_CLIENT | predis |
REDIS_DB | 0 |
REDIS_CACHE_DB | 1 |
Drivers de servicios internos
| Variable | Valor prod | Nota |
|---|---|---|
QUEUE_CONNECTION | redis | Encola notifications + jobs |
CACHE_STORE | redis | Cache de config + query cache |
SESSION_DRIVER | redis | Sesiones Sanctum SPA |
BROADCAST_CONNECTION | log | (Fase 2: cambiar a pusher si se agrega realtime) |
FILESYSTEM_DISK | public | Uploads van al disco local (storage/app/public); documentos privados al disco local |
Logging
| Variable | Valor prod |
|---|---|
LOG_CHANNEL | daily |
LOG_DAILY_DAYS | 14 |
LOG_LEVEL | warning |
LOG_DEPRECATIONS_CHANNEL | null |
Stripe (pagos)
| Variable | Valor prod | Cómo obtenerla |
|---|---|---|
STRIPE_KEY | pk_live_... | Stripe Dashboard → Developers → API keys |
STRIPE_SECRET | sk_live_... | Ídem. No exponer al frontend. |
STRIPE_WEBHOOK_SECRET | whsec_... | Stripe Dashboard → Webhooks → endpoint → Signing secret |
STRIPE_CURRENCY | mxn | Código ISO 4217 |
STRIPE_PRICE_CANDIDATE_6M | (opcional) | price_... si se pre-crea el precio |
Almacenamiento local (archivos)
| Variable | Valor prod | Nota |
|---|---|---|
FILESYSTEM_DISK | public | Disco default; documentos sensibles van explícitos al local |
No hay credenciales — todo es filesystem del propio servidor.
Antes de exponer al tráfico
Ejecutar una vez php artisan storage:link y confirmar que storage/ pertenece al usuario de PHP-FPM (chown -R www-data:www-data storage && chmod -R 775 storage). Sin symlink, las URLs /storage/... devuelven 404.
Ver: Storage local →.
SMTP local (correos)
| Variable | Valor prod | Nota |
|---|---|---|
MAIL_MAILER | smtp | — |
MAIL_HOST | 127.0.0.1 | Postfix corre en el mismo host |
MAIL_PORT | 25 | — |
MAIL_USERNAME | (vacío) | Postfix local sin auth cuando escucha en loopback |
MAIL_PASSWORD | (vacío) | — |
MAIL_ENCRYPTION | null | Encripta sólo el hop Postfix → MTA destino (via smtp_tls_security_level) |
MAIL_FROM_ADDRESS | no-reply@humae.com.mx | — |
MAIL_FROM_NAME | HUMAE | — |
MAIL_REPLY_TO | soporte@humae.com.mx | Dirección monitoreada |
Ver: SMTP local →.
Observabilidad opcional
| Variable | Valor | Cuándo activar |
|---|---|---|
SENTRY_LARAVEL_DSN | https://...@sentry.io/... | Si usas Sentry para error tracking |
SENTRY_TRACES_SAMPLE_RATE | 0.1 | Porcentaje de traces a muestrear |
TELESCOPE_ENABLED | false | Siempre false en prod (Telescope es dev-only) |
Frontend
Ubicación: humae_frontend/.env.production o variables en Vercel/Netlify/Cloudflare Pages dashboard.
| Variable | Valor prod | Nota |
|---|---|---|
NEXT_PUBLIC_API_URL | https://api.humae.com.mx/api/v1 | URL base del backend |
NEXT_PUBLIC_SITE_URL | https://humae.com.mx | URL pública del frontend |
NEXT_PUBLIC_SENTRY_DSN | https://...@sentry.io/... | Opcional: error tracking client-side |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY | pk_live_... | Solo si usas Elements embebidos; para Checkout hosted no es necesario |
NEXT_PUBLIC prefix
Cualquier variable expuesta al cliente debe llevar NEXT_PUBLIC_. Las variables sin ese prefijo son solo accesibles en server components. Nunca pongas STRIPE_SECRET ni credenciales del servidor de correo en el frontend.
Docs (opcional)
Si despliegas humae_docs/ a Cloudflare Pages o similar, no requiere variables en el MVP (es un sitio estático puro).
Verificación rápida
Después de setear las variables, corre estos checks antes de exponer al público:
Backend
bash
# Dentro del servidor backend
cd /path/to/humae_backend
# Verificar que APP_KEY exista
php artisan tinker --execute="echo config('app.key');"
# Verificar conexión a DB
php artisan tinker --execute="\DB::connection()->getPdo();"
# Verificar Redis
php artisan tinker --execute="\Illuminate\Support\Facades\Cache::put('check', 'ok', 60); echo \Cache::get('check');"
# Verificar Stripe (crea una Checkout session de prueba)
php artisan tinker --execute="app(\App\Helpers\StripeClient::class)->createCheckoutSession([/*...*/]);"
# Verificar disco local (debe devolver 'ok')
php artisan tinker --execute="Storage::disk('public')->put('check.txt','ok'); echo Storage::disk('public')->get('check.txt');"
# Verificar SMTP local (revisar /var/log/mail.log que el mensaje saliera)
php artisan tinker --execute="Mail::raw('humae smoke test', fn(\$m) => \$m->to('admin@humae.com.mx')->subject('smoke'));"
# Verificar que el scheduler esté activo
php artisan schedule:listFrontend
bash
# Verificar build
cd /path/to/humae_frontend
npm run build
# Verificar que se conecta al API
curl $NEXT_PUBLIC_API_URL/health
# → { "success": true, "data": { "app": "ok", ... } }Rotación de secrets
Cada 90 días o ante sospecha de compromiso:
- Generar nuevo secret en el provider (Stripe) o rotar DKIM en OpenDKIM.
- Actualizar
.enven producción. - No reiniciar hasta cambiar también cualquier referencia hardcoded (no debería haber).
- Reiniciar workers:
supervisorctl restart humae-queue:*. - Revocar el secret viejo en el provider / retirar el selector DKIM antiguo del DNS tras 24 h de solapamiento.
Para APP_KEY: rotarlo invalida todas las sesiones activas y tokens cifrados. Coordinar mantenimiento.
Para STRIPE_WEBHOOK_SECRET: rotarlo invalida webhooks en curso. Pausar brevemente el endpoint durante la rotación.
Siguiente
Setup paso-a-paso de cada provider externo: Servicios externos →

