Cómo desplegar un proyecto Laravel en producción (paso a paso)

Deploy & DevOps · Por · Publicado el · Actualizado el · 7 min de lectura

Panel de conexiones con cables Ethernet azules conectados a puertos de un rack de red
Conexiones de red en un rack, evocando la infraestructura de servidores. Foto: Brett Sayles / Pexels

Este tutorial muestra, paso a paso, cómo desplegar un proyecto Laravel en producción con Nginx, PHP‑FPM, .env seguro, migraciones, colas y el programador. Saldrás con un servidor configurado, la app en funcionamiento y una checklist de verificación. Si quieres automatizar, consulta también CI/CD. El enfoque aquí es un despliegue clásico en Linux, simple y directo.

Prerequisitos y visión general del proceso

Prepararemos el servidor, instalaremos dependencias, configuraremos el código con .env, optimizaremos Laravel, habilitaremos Nginx/PHP‑FPM, aplicaremos migraciones, levantaremos las colas (Supervisor) y el programador (cron). Algunos pasos requieren sudo/root.

Si planeas automatizar el pipeline después, consulta la guía de CI/CD con GitHub Actions para PHP/Laravel.

  • Servidor Linux (Ubuntu/Debian) con acceso SSH y sudo/root.
  • Dominio apuntado al servidor (DNS A/AAAA).
  • Git habilitado y repositorio del proyecto accesible.
  • PHP‑FPM, Nginx y base de datos (MySQL/MariaDB o PostgreSQL).
  • Composer instalado; Node.js LTS si usas Vite.
  • Variables de entorno y secretos definidos para producción.

1) Preparar el servidor: paquetes esenciales

Actualiza el sistema e instala Nginx, PHP‑FPM con extensiones comunes, Composer, Git y Node.js (si vas a compilar assets con Vite). Ejecuta estos comandos como root o con sudo.

Tras la instalación, confirma que Nginx y PHP‑FPM están activos. En muchos entornos, PHP‑FPM crea un socket en /run/php/. Ajustaremos esto en Nginx más adelante.

sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx php-fpm php-cli php-zip php-mbstring php-xml php-curl php-redis php-mysql php-pgsql git unzip curl
sudo apt install -y composer
# Opcional: Node.js LTS para build com Vite
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs

2) Estructura del proyecto, usuario y permisos

Crea un usuario para el deploy y el directorio de la aplicación en /var/www/app. El grupo www-data (o el equivalente del sistema) suele ejecutar Nginx/PHP‑FPM. Aseguraremos que el servidor web tenga acceso de lectura y que storage/ y bootstrap/cache tengan permisos de escritura.

Evita permisos 777. Mantén 775/664 para carpetas/archivos, con el propietario del app y el grupo del servidor web.

sudo adduser --disabled-password --gecos "" deploy
sudo usermod -aG www-data deploy
sudo mkdir -p /var/www/app
sudo chown -R deploy:www-data /var/www/app
sudo chmod -R 775 /var/www/app

3) Código y configuración de Laravel (.env, migraciones y optimizaciones)

Clona el repositorio, instala dependencias y genera la APP_KEY. Configura el .env para producción (APP_ENV=production, APP_DEBUG=false, DB_*, CACHE_DRIVER, SESSION_DRIVER, QUEUE_CONNECTION, LOG_CHANNEL, etc.). Nunca hagas commit del .env.

Aplica las migraciones con --force para poder ejecutarlas en producción. Para buenas prácticas de versionado de esquema, consulta la Guía: versionamiento ágil de bases de datos.

Por último, crea el enlace de storage y cachea config/rutas/vistas. Si cambias variables de entorno, ejecuta php artisan optimize:clear antes de volver a cachear.

sudo -u deploy -H bash -lc '
cd /var/www/app
# Substitua <SEU_REPO_GIT> pela URL do seu repositório (SSH/HTTPS)
git clone <SEU_REPO_GIT> .
composer install --prefer-dist --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate
php artisan storage:link
# Ajuste o .env com credenciais reais antes de migrar
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
'
# Garantir permissões de escrita no runtime
sudo chown -R deploy:www-data /var/www/app
sudo find /var/www/app/storage /var/www/app/bootstrap/cache -type d -exec chmod 775 {} \;
sudo find /var/www/app/storage /var/www/app/bootstrap/cache -type f -exec chmod 664 {} \;

4) Build de frontend (Vite) – opcional

Si el proyecto usa Vite, compila los assets en modo producción. Sin build, el CSS/JS pueden no cargarse correctamente.

Tras la compilación, Laravel usará el manifest generado para servir archivos estáticos. Si cambias variables de Vite, haz un nuevo build.

cd /var/www/app
npm ci
npm run build

5) Nginx + PHP-FPM: configuración de producción

Crea un server block apuntando a public/. Usa try_files para redirigir al index.php. Ajusta el socket de PHP‑FPM según tu versión. Activa logs dedicados del sitio para facilitar diagnóstico y observabilidad.

Para formatos de logs más adecuados en producción, consulta Logs estructurados (JSON) y correlación.

sudo tee /etc/nginx/sites-available/laravel.conf > /dev/null <<'NGINX'
server {
    listen 80;
    server_name exemplo.com www.exemplo.com;

    root /var/www/app/public;
    index index.php;

    access_log /var/log/nginx/laravel_access.log;
    error_log  /var/log/nginx/laravel_error.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php-fpm.sock; # ajuste para sua versão, ex.: /run/php/php8.2-fpm.sock
        fastcgi_param PHP_VALUE "opcache.validate_timestamps=0";
    }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2?)$ {
        expires 7d;
        access_log off;
        try_files $uri $uri/ @laravel;
    }

    location @laravel {
        rewrite ^/(.*)$ /index.php?$query_string last;
    }

    client_max_body_size 10M;
}
NGINX
sudo ln -s /etc/nginx/sites-available/laravel.conf /etc/nginx/sites-enabled/laravel.conf
sudo nginx -t && sudo systemctl reload nginx

6) Colas con Supervisor (queue:work resiliente)

Usa Supervisor para mantener los workers de colas siempre activos. Define usuario, directorio y parámetros de estabilidad (tries, timeout, max-time). Tras configurar, recarga Supervisor y verifica el estado.

Para estrategias de observabilidad en PHP (APM, traces), revisa el comparativo de Observabilidad PHP.

sudo apt install -y supervisor
sudo tee /etc/supervisor/conf.d/laravel-worker.conf > /dev/null <<'SUP'
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan queue:work --sleep=3 --tries=3 --max-time=3600 --timeout=120
autostart=true
autorestart=true
user=deploy
numprocs=2
redirect_stderr=true
stdout_logfile=/var/log/supervisor/laravel-worker.log
stopwaitsecs=600
SUP
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status

7) Programador (cron) y verificación final del deploy

El scheduler de Laravel debe ejecutarse cada minuto vía cron. Añádelo al crontab del usuario que ejecuta la app. Después, valida Nginx, realiza una petición HTTP y revisa logs/colas.

Si quieres profundizar en recomendaciones oficiales, consulta la documentación de Laravel sobre despliegue, colas y scheduling:

Sugerencias de resolución de problemas comunes:

- 502 Bad Gateway: socket/puerto de PHP‑FPM incorrecto; ajusta fastcgi_pass y verifica el servicio php-fpm.

- 500 en producción: comprueba APP_KEY en el .env y los permisos de storage/ y bootstrap/cache.

- CSS/JS rotos: ejecuta npm run build y verifica las URLs de los assets.

- Cambiaste .env y no sucede nada? Ejecuta php artisan optimize:clear y vuelve a cachear.

# Agendador do Laravel (executa a cada minuto)
( crontab -l 2>/dev/null; echo "* * * * * cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1" ) | crontab -u deploy -

# Verificações rápidas
systemctl status nginx --no-pager
curl -I http://exemplo.com
tail -n 50 /var/log/nginx/laravel_error.log
php /var/www/app/artisan queue:failed

Preguntas frecuentes

¿Es posible hacer despliegue sin downtime con este flujo?

Sí. Usa una estrategia de releases con symlink (p. ej., carpetas releases/current) y el cambio atómico del enlace después del build y las migraciones. Combínalo con health-checks antes del switch y rollback rápido al release anterior. Automatizarlo con CI/CD es lo recomendado.

¿Cómo hago rollback si algo falla tras el deploy?

Vuelve al commit/tag anterior, aplica php artisan migrate:rollback si es necesario (con cautela respecto a los datos) y limpia caches (php artisan optimize:clear). Luego recarga Nginx y reinicia los workers. Tener releases versionadas y backup de la base de datos facilita un retorno seguro.

¿Dónde configuro los logs en producción en Laravel?

En el .env ajusta LOG_CHANNEL (stack, daily, stderr, etc.) y el nivel LOG_LEVEL. En Nginx, mantén access/error logs por sitio. Estandarizar logs en JSON y usar correlación ayuda a depurar y trazar solicitudes.

¿Necesito Node.js en producción para Laravel con Vite?

Necesitas Node.js solo para compilar los assets (npm run build). En producción, una vez generado el build, el servidor entrega los archivos estáticos. En entornos CI/CD, la compilación se hace en el pipeline y el servidor recibe los artefactos listos.

¿Cómo manejar secretos (contraseñas de base, claves) en el .env?

No versiones el .env. Carga secretos vía variables de entorno y restringe permisos. En infra más avanzada, usa gestores de secretos del proveedor cloud. Revisa siempre quién tiene acceso al servidor y al repositorio.

¿Quieres evolucionar tu deploy hacia CI/CD?

Este paso a paso pone tu Laravel en marcha con seguridad. Si necesitas revisar el proceso, estandarizar entornos y automatizar releases, hablemos.

Hablar sobre pipeline de despliegue

Ver también