Configurar .env y storage de Laravel para producción

Un archivo .env bien configurado y un storage que funcione son esenciales para cualquier aplicación Laravel. En esta guía aprendes a configurarlos correctamente para un entorno de producción.

Entender el archivo .env

El archivo .env contiene la configuración específica de cada entorno, que no debe estar en el control de versiones.

Por qué usar .env

  • Separa la configuración del código
  • Evita que haya datos sensibles en Git
  • Facilita el despliegue en distintos entornos
  • Cada entorno (dev, staging, producción) tiene su propio .env

Crear el .env

Si clonas Laravel, crea un .env:

cd ~/domains/example.nl/project
# Copia el archivo de ejemplo
cp .env.example .env
# Genera la clave de la aplicación
php artisan key:generate

Ajustes esenciales de .env

Configura estos ajustes para producción.

Ajustes de la aplicación

APP_NAME="Mijn Laravel App"
APP_ENV=production
APP_KEY=base64:gegenereerde-key-hier
APP_DEBUG=false
APP_TIMEZONE=Europe/Amsterdam
APP_URL=https://example.nl

Importante:

  • APP_ENV=production activa las optimizaciones de producción
  • APP_DEBUG=false evita que se vean los mensajes de error
  • APP_URL debe contener tu URL completa con https

Configuración de la base de datos

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=jouw_database
DB_USERNAME=jouw_user
DB_PASSWORD=jouw_wachtwoord
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

Configuración de los registros

LOG_CHANNEL=daily
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=error

Para producción:

  • daily crea un archivo de registro nuevo cada día
  • LOG_LEVEL=error registra solo los errores, no las advertencias

Caché y sesión

CACHE_STORE=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_ENCRYPT=true
SESSION_PATH=/
SESSION_DOMAIN=.example.nl

Para obtener un mejor rendimiento en un hosting compartido, file es la mejor opción.

Configuración de las colas

QUEUE_CONNECTION=database

O bien, para un hosting compartido sin workers:

QUEUE_CONNECTION=sync

Configuración del correo

MAIL_MAILER=smtp
MAIL_HOST=mail.example.nl
MAIL_PORT=587
MAIL_USERNAME=info@example.nl
MAIL_PASSWORD=je-mail-wachtwoord
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=info@example.nl
MAIL_FROM_NAME="${APP_NAME}"

Configurar el storage

Laravel usa la carpeta storage para los registros, la caché y los archivos subidos.

Estructura de storage

storage/
├── app/
│   ├── public/      # Subidas de acceso público
│   └── private/     # Archivos privados
├── framework/
│   ├── cache/       # Caché de archivos
│   ├── sessions/    # Archivos de sesión
│   └── views/       # Vistas compiladas
└── logs/            # Archivos de registro

Crear el enlace de storage

El storage público debe ser accesible a través de la web:

# Crea el enlace simbólico
php artisan storage:link

Esto crea: public/storage -> storage/app/public Comprueba que el enlace funciona:

ls -la public/
# Verás: storage -> /path/to/storage/app/public

Enlace simbólico manual

Si el comando de artisan no funciona:

cd public
ln -s ../storage/app/public storage

Configurar los permisos de storage

Asegúrate de que Laravel pueda escribir:

# Hacer escribible de forma recursiva
chmod -R 775 storage
chmod -R 775 bootstrap/cache
# Establece el propietario (si hace falta)
chown -R www-data:www-data storage
chown -R www-data:www-data bootstrap/cache

En un hosting compartido, normalmente solo hace falta chmod.

Seguridad en producción

Protege tu .env y tu storage.

Proteger el .env

El archivo .env nunca debe ser accesible públicamente:

  1. La carpeta public de Laravel es la raíz de documentos
  2. El .env está un nivel por encima
  3. .htaccess bloquea el acceso Compruébalo con:
curl https://example.nl/.env
# Debe dar 403 o 404, ¡NUNCA el contenido!

.env en .gitignore

Asegúrate de que el .env nunca llegue a Git:

.env
.env.backup
.env.production

Proteger el storage

Proteger los archivos privados subidos:

// En routes/web.php
Route::get('/download/{file}', function ($file) {
    // Comprobación de autorización
    if (!auth()->check()) {
        abort(403);
    }
    return Storage::download('private/' . $file);
});

Configuración de la caché

Optimiza la caché para producción.

Caché de configuración

php artisan config:cache

Esto combina todos los archivos de configuración en un único archivo en caché. Atención: después de config:cache, el .env ya no se lee directamente. Los cambios en el .env requieren:

php artisan config:clear
php artisan config:cache

Caché de rutas

php artisan route:cache

Acelera considerablemente la resolución de rutas.

Caché de vistas

php artisan view:cache

Precompila todas las plantillas Blade.

Todo a la vez

php artisan optimize

O durante el despliegue:

php artisan optimize:clear
php artisan optimize

Problemas frecuentes

Storage permission denied

# Restablece los permisos
chmod -R 775 storage bootstrap/cache
# Contexto de SELinux (CentOS/RHEL)
chcon -R -t httpd_sys_rw_content_t storage

El enlace simbólico no funciona

En algunos servidores, los enlaces simbólicos están desactivados:

# Copia en lugar de usar un enlace simbólico
cp -r storage/app/public/* public/storage/

O adapta el FileController para servir los archivos.

Los cambios en el .env no funcionan

# Vacía la caché de configuración
php artisan config:clear
# O si no tienes SSH
# Elimina: bootstrap/cache/config.php

Problemas con APP_KEY

Si falta tu APP_KEY o es incorrecta:

php artisan key:generate

Esto regenera la clave. Atención: los datos cifrados existentes dejan de poder leerse.

Detección del entorno

Comprueba el entorno actual en el código:

// En el código
if (app()->environment('production')) {
    // Código específico de producción
}
// En Blade
@production
    <!-- Solo en producción -->
@endproduction

Buenas prácticas

Gestión del .env

  • No uses nunca el mismo .env en dev y en producción
  • Guarda el .env de producción en un lugar seguro (gestor de contraseñas)
  • Usa contraseñas seguras y únicas
  • Cambia las credenciales con regularidad

Gestión del storage

  • Configura copias de seguridad para storage/app
  • Plantéate un almacenamiento en la nube para escalar
  • Elimina los registros antiguos con regularidad

¿Necesitas ayuda?

Estamos a tu disposición. ¿Te has encontrado con algún problema o tienes preguntas? Nuestro equipo de soporte te ayuda con mucho gusto de forma personal. Envíanos un mensaje a través del sistema de tickets: solemos responder en unas pocas horas y te ayudamos a buscar la solución.

¿Buscas una dirección de correo electrónico? Consulta nuestra oferta.