Desarrollo y bases de datos

Instalar Laravel en un hosting con cPanel (Laravel 13 y 12)

Revisado el 18 min de lectura instalacion composer laravel

Puedes instalar Laravel en un hosting con cPanel usando Composer y acceso SSH. En esta guía crearemos un proyecto nuevo, prepararemos su base de datos, configuraremos el dominio para que publique únicamente la carpeta public y dejaremos listas las piezas que suele necesitar una aplicación en producción: scheduler, colas, sesiones, caché y, si hace falta, Horizon y WebSockets.

Si ya tienes una aplicación en un repositorio, no necesitas crear otra: conecta el repositorio con Deploy+ y sigue esta guía desde el apartado de la base de datos.

1. Elige la versión de PHP y comprueba la de la terminal

Laravel 13 necesita PHP 8.3 o superior, y Laravel 12, PHP 8.2 o superior, siempre dentro de lo que admitan tus dependencias. La versión de la web se elige en el selector de PHP; en una web publicada con Deploy+, se fija en el .htaccess de tu repositorio, como explicamos en versión de PHP con Deploy+.

Abre SSH o la terminal de cPanel y comprueba qué versión ejecutan los comandos:

php -v
composer --version

El php de la terminal no siempre es la versión de tu web: hemos visto cuentas en las que respondía PHP 8.1 con el selector en 8.4. Si no coincide, llama al binario de tu versión por su ruta completa, por ejemplo /opt/alt/php84/usr/bin/php artisan migrate, y ejecuta Composer con él:

/opt/alt/php84/usr/bin/php "$(command -v composer)" install

En el resto de la guía escribimos php para abreviar: sustitúyelo por la ruta completa si tu terminal da otra versión. En el cron y en los procesos persistentes usa siempre la ruta completa.

Los requisitos de Laravel incluyen Ctype, cURL, DOM, Fileinfo, Filter, Hash, Mbstring, OpenSSL, PCRE, PDO, Session, Tokenizer y XML; la base de datos elegida requiere además su controlador PHP. Las extensiones se activan por versión: si Composer indica ext-fileinfo is missing, actívala en la versión que ejecuta el comando. No omitas las comprobaciones con --ignore-platform-reqs: instalar dependencias incompatibles no hará que la aplicación funcione.

Los valores de cada versión, como memory_limit, max_execution_time, upload_max_filesize o max_input_vars, también se ajustan a lo que necesite tu aplicación: desde la pestaña Límites de la ficha de la web en el área de clientes o desde Options en el selector de cPanel, como explica PHP, seleccionar versión, módulos y configuración. max_execution_time solo limita las peticiones web: Artisan, el scheduler y los workers no tienen ese tiempo máximo.

2. Crea el proyecto fuera del directorio público

Desde la raíz de tu cuenta, crea una carpeta nueva que no exista todavía:

cd ~
composer create-project laravel/laravel mi-proyecto "^13.0"
cd mi-proyecto
php artisan --version
composer check-platform-reqs

La comprobación de Artisan debe identificar Laravel 13; la de Composer, confirmar los requisitos del entorno. No ejecutes create-project sobre una web existente.

Si la aplicación o una integración requiere Laravel 12, usa otra carpeta nueva con composer create-project laravel/laravel mi-proyecto-12 "^12.0". Su calendario oficial mantiene las correcciones de seguridad hasta el 24 de febrero de 2027; consulta la política de soporte de Laravel al elegir versión. Para un proyecto que ya existe, usa su composer.lock con composer install; no lo sustituyas por una instalación nueva ni cambies de versión mayor sin revisar la actualización.

Si prefieres un starter kit (React, Vue, Svelte o Livewire), instala el instalador oficial con composer global require laravel/installer, añade al PATH la ruta que devuelve composer global config bin-dir --absolute y usa laravel new otro-proyecto en una carpeta nueva. Consulta laravel new --help antes de automatizar opciones.

3. Configura la base de datos

Una instalación nueva puede empezar con SQLite si PHP tiene su controlador. Para usar MySQL, crea la base y su usuario desde el asistente de bases de datos de cPanel. Si despliegas con Deploy+, puede crear la base y escribir la conexión en el .env al conectar el repositorio.

Edita .env dentro del proyecto con los datos reales de esa base:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=miusuario_proyecto
DB_USERNAME=miusuario_app
DB_PASSWORD="sustituye_por_la_clave_de_la_base"

Usa los nombres completos que muestra cPanel, incluido su prefijo. No publiques .env ni lo subas al repositorio. En el proyecto nuevo, ejecuta:

php artisan config:clear
php artisan migrate

Si estás desplegando una aplicación con datos existentes, revisa las migraciones y conserva una copia antes de aplicarlas. No uses migrate:fresh: elimina las tablas.

4. Publica solo la carpeta public

El dominio debe servir /home/tu_usuario/mi-proyecto/public, no /home/tu_usuario/mi-proyecto. Así los archivos de configuración y el código privado quedan fuera de la raíz web.

Para un dominio adicional o subdominio, revisa su directorio desde cPanel > Dominios > Administrar y, si la configuración lo permite, selecciona la carpeta public del proyecto. No muevas index.php a la raíz para evitar este paso.

En el dominio principal, cPanel normalmente utiliza public_html. Si necesitas sustituir ese directorio por un enlace al public de Laravel, planifica antes qué contiene, su copia y la vuelta atrás; no renombres ni borres public_html sin comprobar si ya aloja una web u otros dominios. Con Deploy+, el perfil Laravel publica la carpeta public del repositorio en la carpeta que elijas, que tiene que estar vacía en el primer despliegue.

5. Prepara y comprueba la aplicación

En .env, configura la URL real y desactiva la depuración pública:

APP_ENV=production
APP_DEBUG=false
APP_URL=https://tudominio.com

La instalación debe tener una clave APP_KEY. En un proyecto nuevo sin clave, genera una con php artisan key:generate. No la regeneres en una aplicación existente: podrías dejar inaccesibles datos cifrados.

Si tu proyecto utiliza Vite, compila sus recursos con una versión de Node.js compatible con su package.json: npm install y npm run build en una instalación nueva; npm ci y npm run build en despliegues con package-lock.json. Node.js está en el Gestor de paquetes y sirve para compilar; consulta Node.js para compilar assets.

Comprueba que storage y bootstrap/cache sean escribibles por la aplicación, sin aplicar permisos 777 de forma general, y ejecuta php artisan optimize.

Abre el dominio por HTTPS y comprueba portada, rutas interiores y funciones que consulten la base de datos. Verifica también que /.env no entregue el archivo. Si aparece un error 500, consulta storage/logs/laravel.log y los registros del hosting; no actives la depuración pública para mostrar el error a todos los visitantes.

6. Programa el scheduler

Si publicas el proyecto con Deploy+, el asistente lo hace por ti: deja marcado Programar el scheduler de Laravel y la tarea se añade al terminar el primer despliegue, como explicamos en Deploy+. Compruébala igualmente con php artisan schedule:list.

Si no, en cPanel > Trabajos de cron, añade una tarea que se ejecute cada minuto con el PHP de tu aplicación:

* * * * * /opt/alt/php84/usr/bin/php /home/tu_usuario/mi-proyecto/artisan schedule:run > /dev/null 2>&1

Cambia php84 por tu versión y la ruta por la de tu proyecto; con Deploy+ es /home/tu_usuario/deploy/nombre-repo/current/artisan. No uses /usr/local/bin/php ni el php a secas: pueden ser otra versión de PHP, con otras extensiones, y el scheduler lanza las tareas programadas con el mismo PHP con el que arranca.

Antes de dejarla, ejecuta ese mismo comando a mano, sin descartar la salida, y revisa php artisan schedule:list. Tienes más detalles sobre el cron en tareas cron en cPanel.

7. Colas

Desde Laravel 11, un proyecto nuevo guarda los trabajos en la base de datos (QUEUE_CONNECTION=database). En un proyecto anterior, crea antes la tabla con php artisan queue:table y migra. Lo que cambia según tu plan es quién los procesa.

Con procesos persistentes (Avanza, Max y Elástico)

Crea un Worker de colas en Herramientas > Procesos, con la carpeta de la aplicación y su versión de PHP. Se queda en marcha, procesa cada trabajo en cuanto llega y vuelve a arrancar solo si se cae. Al publicar una versión con Deploy+, se reinicia solo para recoger el código nuevo. Todo el detalle está en procesos persistentes.

Sin procesos persistentes

En cualquier plan, el scheduler puede lanzar cada minuto un worker que procesa lo pendiente y termina. En routes/console.php:

use Illuminate\Support\Facades\Schedule;

Schedule::command('queue:work --stop-when-empty --tries=3 --max-time=300')
    ->everyMinute()
    ->withoutOverlapping(10)
    ->runInBackground();

withoutOverlapping(10) evita que se junten dos workers y libera el bloqueo a los 10 minutos si uno se corta a medias; runInBackground() deja que el resto de tareas programadas se ejecuten a su hora. Un trabajo puede esperar hasta un minuto antes de procesarse.

Si prefieres no depender del scheduler, una tarea cron con flock hace lo mismo sin solaparse:

* * * * * cd /home/tu_usuario/mi-proyecto && /usr/bin/flock -n /home/tu_usuario/.cola-mi-proyecto.lock /opt/alt/php84/usr/bin/php artisan queue:work --stop-when-empty --max-time=300 > /dev/null 2>&1

En los dos casos, revisa los trabajos fallidos con php artisan queue:failed.

8. Sesiones, caché y Redis

Dónde guardar cada cosa:

  • Sesiones: en la base de datos (SESSION_DRIVER=database) en cualquier plan; desde Avanza, también en el Redis persistente (redis).
  • Colas: en la base de datos (QUEUE_CONNECTION=database) en cualquier plan; desde Avanza, también en el Redis persistente (redis).
  • Caché: en la base de datos (CACHE_STORE=database) o en Redis Cache, en cualquier plan.
  • Horizon: solo con el Redis persistente, desde Avanza.

Los dos Redis no sirven para lo mismo:

  • Redis Cache, en todos los planes, es solo caché: empieza vacío al reiniciarse y descarta claves al llenarse. Úsalo para CACHE_STORE=redis y nunca para sesiones ni colas. Configuración en Redis como caché de objetos.
  • Redis persistente, desde Avanza, guarda sus datos en disco y no los descarta: es el sitio para colas, sesiones y Horizon. Se activa en el Gestor de paquetes y se conecta por un socket de tu cuenta. Configuración en Redis persistente.

Puedes usar los dos a la vez: la caché en Redis Cache y las colas y sesiones en el Redis persistente. Las sesiones en la base de datos son la opción por defecto desde Laravel 11 y sirven en cualquier plan; en un proyecto anterior, crea su tabla con php artisan session:table.

9. Horizon

Horizon necesita colas en Redis y un proceso en marcha, así que funciona desde el plan Avanza: activa el Redis persistente, pon QUEUE_CONNECTION=redis, instala laravel/horizon y crea un proceso persistente de tipo Horizon. Ajusta maxProcesses en config/horizon.php a los recursos de tu plan. Con Deploy+, Horizon se reinicia solo tras activar cada versión; si publicas de otra forma, ejecuta php artisan horizon:terminate cuando el código nuevo ya esté en su sitio. Los pasos están en Redis persistente para colas, sesiones y Horizon.

Horizon sobre Redis Cache no es seguro: si esa caché se vacía o se llena, se pierden trabajos.

10. Broadcasting y WebSockets

Reverb no lo ofrecemos en el hosting: es un servidor que escucha en su propio puerto, y no damos soporte a programas así, como explicamos en procesos persistentes. Para notificaciones y eventos en tiempo real, conecta tu aplicación a un servicio compatible con el protocolo de Pusher, como Pusher Channels o Ably, que Laravel soporta de serie. Tu aplicación solo hace peticiones HTTPS salientes y los navegadores se conectan al servicio. Comparativa y configuración en WebSockets en Laravel.

Qué no encaja en el hosting

  • Octane: aquí PHP lo sirve LiteSpeed, y Octane necesita su propio servidor de aplicación delante (Swoole, RoadRunner o FrankenPHP).
  • Reverb u otro servidor de WebSockets propio: usa un servicio compatible con Pusher.
  • Node.js como servidor: Node está para compilar assets. El SSR de Inertia necesita un servidor Node en marcha; sin él, Inertia renderiza en el navegador como siempre.
  • Servicios del sistema o acceso root. Si tu proyecto los necesita, cuéntanos el caso antes de contratar.

Livewire, Inertia, Filament, Sanctum, Socialite o Scout funcionan sin nada especial.

Publicar los siguientes cambios con Deploy+

Cuando el proyecto esté en Git, Deploy+ publica cada versión en su propia carpeta, con archivos compartidos y versiones a las que volver. Un script de despliegue para Laravel:

composer install --no-dev --optimize-autoloader --no-interaction
php artisan migrate --force
php artisan optimize

Si compilas assets, añade las líneas de npm que indica la guía de Deploy+. No hace falta queue:restart ni horizon:terminate: tras activar cada versión, y también al volver a una anterior, Deploy+ reinicia los procesos persistentes de la aplicación. Una reversión de código no deshace automáticamente cambios de base de datos: diseña las migraciones teniendo en cuenta esa diferencia.

El script recomendado, qué procesos admite el hosting y la comparación con un VPS están resumidos en hosting para Laravel con Deploy+.

Referencias: instalación de Laravel, colas y recomendaciones de despliegue.

También te puede ayudar

¿Algo no cuadra o ha cambiado? Cuéntanoslo y lo revisamos.