{"id":7466,"date":"2025-12-31T13:39:29","date_gmt":"2025-12-31T12:39:29","guid":{"rendered":"https:\/\/www.hostingtg.com\/blog\/?p=7466"},"modified":"2025-12-31T13:39:31","modified_gmt":"2025-12-31T12:39:31","slug":"instalar-node-js-en-cpanel","status":"publish","type":"post","link":"https:\/\/www.hostingtg.com\/blog\/instalar-node-js-en-cpanel\/","title":{"rendered":"Instalar Node.js en cPanel: gu\u00eda pr\u00e1ctica para crear y desplegar tu app"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Requisitos y elegir cPanel para Node.js<\/h2>\n\n\n\n<p>Si lo que quieres es <strong>poner una app en producci\u00f3n sin pelearte con un VPS<\/strong>, <a href=\"https:\/\/www.hostingtg.com\/blog\/panel-de-control-cpanel\/\">cPanel es tu mejor amigo<\/a>. A m\u00ed instalar Node.js en cPanel y desplegar desde un entorno tan conocido me <strong>facilita la vida<\/strong>: pasas de configurar procesos, puertos y permisos a <strong>hacer clics y rellenar campos<\/strong>. No es magia, pero <strong>reduce much\u00edsimo la complejidad inicial<\/strong> y te permite enfocarte en que la app responda bien.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ventajas y l\u00edmites frente a VPS<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Ventajas<\/strong>\n<ul class=\"wp-block-list\">\n<li>Setup guiado con \u201cSetup Node.js App\u201d.<\/li>\n\n\n\n<li>Reinicios y gesti\u00f3n de variables de entorno sin tocar <code>systemd<\/code> ni <code>pm2<\/code>.<\/li>\n\n\n\n<li>Logs accesibles desde el panel y terminal integrada.<\/li>\n\n\n\n<li>Entornos <strong>Development\/Production<\/strong> sin complicaciones.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>L\u00edmites<\/strong>\n<ul class=\"wp-block-list\">\n<li>Menos control fino (puertos, demonios, kernel).<\/li>\n\n\n\n<li>Dependencia del entorno del hosting (versiones disponibles, l\u00edmites de memoria\/CPU).<\/li>\n\n\n\n<li>Algunas arquitecturas SSR muy exigentes pueden requerir VPS m\u00e1s adelante.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>Mi recomendaci\u00f3n:<\/strong> para <strong>proyectos peque\u00f1os y medianos<\/strong>, cPanel es una <strong>soluci\u00f3n intermedia, estable y accesible<\/strong>. Cuando el tr\u00e1fico crezca mucho o necesites features del sistema m\u00e1s avanzadas, ya saltar\u00e1s a <a href=\"https:\/\/www.hostingtg.com\/servidores-vps\/\">servidor VPS<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Versiones de Node y compatibilidad<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Elige la <strong>versi\u00f3n LTS<\/strong> m\u00e1s reciente disponible en tu hosting para producci\u00f3n.<\/li>\n\n\n\n<li>Verifica que tu framework (Express, Nest, Next, Astro, Vite\u2026) soporta esa versi\u00f3n.<\/li>\n\n\n\n<li>Si vienes de CommonJS y empiezas a usar ESM, revisa tu <code>package.json<\/code> (<code>\"type\": \"module\"<\/code>) y el <code>startup file<\/code>.<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Lo que m\u00e1s valoro del proceso es tener claro el orden: <strong>elegir la versi\u00f3n<\/strong>, <strong>definir el punto de entrada<\/strong> y <strong>gestionar dependencias<\/strong> sin pelearme con la terminal.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.hostingtg.com\/blog\/wp-content\/uploads\/2025\/12\/node-js-cpanel.webp\"><img fetchpriority=\"high\" decoding=\"async\" width=\"963\" height=\"600\" src=\"https:\/\/www.hostingtg.com\/blog\/wp-content\/uploads\/2025\/12\/node-js-cpanel.webp\" alt=\"node js cpanel\" class=\"wp-image-7468\" title=\"\"><\/a><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Crear la aplicaci\u00f3n en Setup Node.js App<\/h2>\n\n\n\n<p>Accede al gestor y crea tu app<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Entra al cPanel y abre <strong>Application Manager<\/strong> o <strong>Setup Node.js App<\/strong>.<\/li>\n\n\n\n<li>Pulsa <strong>Create Application<\/strong> (o \u201cCreate\/Setup\u201d) y completa los campos principales:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.hostingtg.com\/blog\/wp-content\/uploads\/2025\/12\/aplication-manager.webp\"><img decoding=\"async\" width=\"900\" height=\"314\" src=\"https:\/\/www.hostingtg.com\/blog\/wp-content\/uploads\/2025\/12\/aplication-manager.webp\" alt=\"aplication manager\" class=\"wp-image-7469\" title=\"\"><\/a><\/figure>\n\n\n\n<p><strong>a) Application Root (ruta de la app)<\/strong><br>La carpeta <em>real<\/em> donde vive tu proyecto. Evita <code>public_html<\/code>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ejemplos v\u00e1lidos:\n<ul class=\"wp-block-list\">\n<li><code>\/home\/usuario\/apps\/mi-api<\/code><\/li>\n\n\n\n<li><code>\/home\/usuario\/domains\/midominio.com\/node<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>b) Application URL (dominio\/subdominio)<\/strong><br>El dominio o subdominio que servir\u00e1 tu app.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ejemplos:\n<ul class=\"wp-block-list\">\n<li><code>https:\/\/api.midominio.com<\/code><\/li>\n\n\n\n<li><code>https:\/\/midominio.com\/app<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>c) Application Startup File (archivo de arranque)<\/strong><br>El archivo que <strong>inicia<\/strong> el servidor Node (no la build ni el HTML).<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Comunes: <code>index.js<\/code>, <code>app.js<\/code>, <code>server.js<\/code><\/li>\n\n\n\n<li>Si compilas TypeScript o bundlers: apunta al <strong>resultado<\/strong> (<code>dist\/server.js<\/code>).<\/li>\n<\/ul>\n\n\n\n<p><strong>d) Node.js Version (versi\u00f3n del runtime)<\/strong><br>Selecciona la <strong>LTS<\/strong> disponible (estabilidad y soporte).<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Si tu app exige una versi\u00f3n concreta, alin\u00e9ala aqu\u00ed y en <code>engines<\/code> de <code>package.json<\/code> (opcional).<\/li>\n<\/ul>\n\n\n\n<p><strong>e) Environment (modo)<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Production<\/strong> para desplegar estable.<\/li>\n\n\n\n<li><strong>Development<\/strong> solo para pruebas puntuales (no recomendado en sitios p\u00fablicos).<\/li>\n<\/ul>\n\n\n\n<p><strong>f) Variables de entorno (opcional de inicio, recomendable)<\/strong><br>A\u00f1ade clave\/valor aqu\u00ed para no exponer secretos en el repo.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ejemplo: <code>NODE_ENV=production<\/code>, <code>JWT_SECRET=\u2026<\/code>, <code>DATABASE_URL=\u2026<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>Guarda\/crea la aplicaci\u00f3n. Ver\u00e1s controles para <strong>instalar dependencias<\/strong>, <strong>reiniciar<\/strong> y consultar <strong>logs<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Sube el c\u00f3digo y vinc\u00falalo a la app<\/h3>\n\n\n\n<p>Tienes tres caminos sencillos (elige el que m\u00e1s te convenga):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ZIP + File Manager<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Sube un <code>.zip<\/code> a tu <strong>Application Root<\/strong> y descompr\u00edmelo.<\/li>\n\n\n\n<li>Verifica que <code>package.json<\/code> y tu <code>startup file<\/code> est\u00e1n en esa carpeta.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong><a href=\"https:\/\/www.hostingtg.com\/blog\/instalar-git-en-ubuntu\/\">Git<\/a> (recomendado para iterar)<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Clona el repo en el <strong>Application Root<\/strong>.<\/li>\n\n\n\n<li><code>git pull<\/code> para futuras actualizaciones.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>SSH\/SFTP<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Copia archivos a la ruta exacta del <strong>Application Root<\/strong>.<\/li>\n\n\n\n<li>\u00datil para proyectos ya empaquetados o migraciones.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Importante: que el <strong>Application Root<\/strong> coincida con la carpeta donde est\u00e9 tu <code>package.json<\/code> y tu <code>startup file<\/code>.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Instala dependencias y compila (si aplica)<\/h3>\n\n\n\n<p>Dentro del panel de tu app ver\u00e1s acciones tipo <strong>Run NPM install<\/strong>. \u00dasalas:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Run NPM install<\/strong>: instala dependencias del <code>package.json<\/code> en el servidor.<\/li>\n\n\n\n<li>Si usas TS o un bundler (Vite, Next, Nest, etc.), ejecuta tambi\u00e9n tu <strong>build<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Puedes lanzar <code>npm run build<\/code> desde la terminal de cPanel o configurar un script de post-deploy.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>Ejemplo de <code>package.json<\/code> b\u00e1sico:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"scripts\": {\n    \"start\": \"node index.js\",\n    \"build\": \"tsc\",\n    \"start:prod\": \"NODE_ENV=production node dist\/index.js\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Comprueba tu <strong>startup file<\/strong> (con ejemplos pr\u00e1cticos)<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">A) Express (API cl\u00e1sica)<\/h4>\n\n\n\n<p><strong>Archivo:<\/strong> <code>index.js<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import express from \"express\";\nconst app = express();\nconst port = process.env.PORT || 3000;\n\napp.get(\"\/health\", (_, res) => res.json({ ok: true }));\napp.listen(port, () => console.log(`Servidor listo en puerto ${port}`));\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Startup file<\/strong> en el panel: <code>index.js<\/code>.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">B) NestJS (modo tradicional)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>npm run build<\/code> genera <code>dist\/main.js<\/code>.<\/li>\n\n\n\n<li><strong>Startup file<\/strong>: <code>dist\/main.js<\/code> (no el <code>src\/main.ts<\/code>).<\/li>\n\n\n\n<li>En <code>main.ts<\/code> aseg\u00farate de escuchar <code>process.env.PORT<\/code>.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">C) Next.js (SSR seg\u00fan proveedor)<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Si tu hosting permite Next SSR: el startup suele apuntar a un archivo servidor (custom) que arranca la app, o usas el comando que el proveedor habilita.<\/li>\n\n\n\n<li>Alternativa universal: <strong>export est\u00e1tico<\/strong> (<code>next export<\/code>) y servir est\u00e1ticos desde una carpeta p\u00fablica (sin Node SSR).<\/li>\n<\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Truco: si ves la p\u00e1gina gen\u00e9rica \u201cIt works!\u201d o un 404, casi siempre el <strong>startup file<\/strong> o la <strong>ruta<\/strong> no apuntan al servidor correcto.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Configura variables de entorno y secretos<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A\u00f1ade variables en la secci\u00f3n de <strong>Environment Variables<\/strong> de tu app.<\/li>\n\n\n\n<li>L\u00e9elas con <code>process.env.MI_VARIABLE<\/code>.<\/li>\n\n\n\n<li>Reinicia para que apliquen.<\/li>\n\n\n\n<li>No imprimas secretos en logs; loguea solo lo necesario (por ejemplo, el entorno y el puerto).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Reinicia, verifica y revisa logs<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tras instalar dependencias o cambiar configuraci\u00f3n, pulsa <strong>Restart App<\/strong>.<\/li>\n\n\n\n<li>Visita la <strong>Application URL<\/strong> y prueba <code>\/health<\/code> (o una ruta conocida).<\/li>\n\n\n\n<li>Si falla, abre <strong>Logs\/Passenger log<\/strong> en el panel: ver\u00e1s errores de m\u00f3dulos, rutas o puertos.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Errores t\u00edpicos (y c\u00f3mo los solucionas r\u00e1pido)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>P\u00e1gina \u201cIt works!\u201d<\/strong> \u2192 <code>Application Root<\/code> o <code>Startup File<\/code> mal definidos. Corrige y <strong>Restart App<\/strong>.<\/li>\n\n\n\n<li><strong>Cannot find module<\/strong> \u2192 Faltan dependencias del servidor. Ejecuta <strong>Run NPM install<\/strong> (o <code>npm ci<\/code>).<\/li>\n\n\n\n<li><strong>Arranca local, no en servidor<\/strong> \u2192 Desajuste de <strong>versi\u00f3n de Node<\/strong> o <strong>ESM\/CommonJS<\/strong>. Alinea versi\u00f3n y revisa <code>\"type\": \"module\"<\/code>.<\/li>\n\n\n\n<li><strong>Puerto ocupado\/no escucha<\/strong> \u2192 Usa <code>process.env.PORT<\/code> en lugar de puertos fijos.<\/li>\n\n\n\n<li><strong>Rutas SPA rompen al refrescar<\/strong> \u2192 Sirves est\u00e1ticos: a\u00f1ade reglas de reescritura para devolver <code>index.html<\/code>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Campos clave: Application root, URL y startup file (con ejemplos)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Application root<\/strong>: carpeta donde vive tu app, por ejemplo:<br><code>\/home\/usuario\/apps\/mi-api<\/code> o <code>\/home\/usuario\/domains\/midominio.com\/node<\/code><\/li>\n\n\n\n<li><strong>Application URL<\/strong>: dominio o subdominio que servir\u00e1 la app:<br><code>https:\/\/api.midominio.com<\/code> o <code>https:\/\/midominio.com\/app<\/code><\/li>\n\n\n\n<li><strong>Application startup file<\/strong>: el punto de entrada que arranca tu servidor:<br><code>index.js<\/code>, <code>app.js<\/code>, <code>server.js<\/code> o <code>dist\/server.js<\/code> si compilas antes.<\/li>\n<\/ul>\n\n\n\n<p><strong>Ejemplo Express minimal:<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ index.js\nimport express from \"express\";\nconst app = express();\nconst port = process.env.PORT || 3000;\n\napp.get(\"\/health\", (_, res) => res.json({ok: true}));\n\napp.listen(port, () => console.log(`Ready on :${port}`));\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Entornos Development vs Production y reinicios<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Development<\/strong>: para pruebas r\u00e1pidas (ojo con hot-reload, no siempre procede).<\/li>\n\n\n\n<li><strong>Production<\/strong>: valor por defecto para producci\u00f3n.<br>Cada cambio gordo (paquetes, build, startup file) \u2192 <strong>Restart App<\/strong>. Ese flujo de \u201c<strong>subir \u2192 instalar paquetes \u2192 reiniciar<\/strong>\u201d se vuelve natural y ordenado.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Subir el c\u00f3digo y gestionar dependencias<\/h2>\n\n\n\n<p>Tienes varias v\u00edas para subir c\u00f3digo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>ZIP + File Manager<\/strong> de cPanel (r\u00e1pido para la primera subida).<\/li>\n\n\n\n<li><strong>Git<\/strong> (ideal para actualizaciones).<\/li>\n\n\n\n<li><strong>SSH\/SFTP<\/strong> si prefieres la terminal.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">ZIP\/Git\/SSH y estructura de carpetas (evitar <code>public_html<\/code>)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mant\u00e9n tu app <strong>fuera de <code>public_html<\/code><\/strong>; deja <code>public_html<\/code> para est\u00e1ticos si los necesitas.<\/li>\n\n\n\n<li>Estructura sugerida:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>\/home\/usuario\/apps\/mi-app\n  \u251c\u2500 src\/ o app\/\n  \u251c\u2500 dist\/ (si compilas)\n  \u251c\u2500 package.json\n  \u2514\u2500 .env (opcional; considera guardarlo en cPanel vars)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Run NPM install, scripts (build, start) y logs<\/h3>\n\n\n\n<p>En la interfaz ver\u00e1s un bot\u00f3n tipo <strong>\u201cRun NPM install\u201d<\/strong> dentro de tu app.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Instala dependencias <strong>en el servidor<\/strong> (no subas <code>node_modules<\/code>).<\/li>\n\n\n\n<li>Scripts t\u00edpicos:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"scripts\": {\n    \"build\": \"tsc &amp;&amp; vite build\",\n    \"start\": \"node index.js\",\n    \"start:prod\": \"NODE_ENV=production node index.js\"\n  }\n}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Revisa <strong>Logs<\/strong> y <strong>Passenger log<\/strong> cuando algo no arranque a la primera.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Variables de entorno y secretos<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><code>process.env<\/code> y buenas pr\u00e1cticas<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Define variables desde la pantalla de la app en cPanel (clave\/valor).<\/li>\n\n\n\n<li>Accede desde tu c\u00f3digo con <code>process.env.MI_VAR<\/code>.<\/li>\n\n\n\n<li>Evita comprometer secretos en el repo; usa variables del panel.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Passenger log y diagn\u00f3stico de errores<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Si ves p\u00e1gina gen\u00e9rica o error 500, abre <strong>Passenger log<\/strong>.<\/li>\n\n\n\n<li>Busca errores de m\u00f3dulo, rutas mal mapeadas o un <code>startup file<\/code> equivocado.<\/li>\n\n\n\n<li>A\u00f1ade logs de arranque (puerto, rutas registradas, modo) para trazar problemas.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Despliegue por tipo de proyecto<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">API \/ Express<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Startup file<\/strong> apunta a <code>index.js<\/code> que <strong>escucha el puerto<\/strong>.<\/li>\n\n\n\n<li>Verifica CORS si sirves a frontends externos.<\/li>\n\n\n\n<li>Healthcheck (<code>\/health<\/code>) para verificar despliegue.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">SPA (React\/Vite) sin romper rutas (.htaccess)<\/h3>\n\n\n\n<p>Para SPAs servidas como est\u00e1ticos:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>npm run build<\/code> \u2192 carpeta <code>dist<\/code>.<\/li>\n\n\n\n<li>Sirve <code>dist<\/code> desde una ruta o subdominio.<\/li>\n\n\n\n<li>Asegura que el servidor devuelve <code>index.html<\/code> para rutas del router:<\/li>\n<\/ol>\n\n\n\n<p><strong>.htaccess ejemplo (en la carpeta p\u00fablica de la SPA)<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RewriteEngine On\nRewriteBase \/\nRewriteRule ^index\\.html$ - &#91;L]\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . \/index.html &#91;L]\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">SSR (Next.js) y consideraciones<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Muchos hostings con cPanel ya soportan Next en <strong>modo server<\/strong> si el proveedor lo permite.<\/li>\n\n\n\n<li>Si no, despliegue <strong>est\u00e1tico<\/strong> (<code>next export<\/code>) o middleware de compatibilidad.<\/li>\n\n\n\n<li>Aseg\u00farate de compilar en el servidor (<code>npm ci &amp;&amp; npm run build<\/code>) y que el <strong>startup file<\/strong> invoque el servidor de Next (o tu adaptador).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Checklist de actualizaci\u00f3n segura<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Pull\/Upload<\/strong> de cambios (Git o ZIP).<\/li>\n\n\n\n<li><strong>Instalar dependencias<\/strong>: \u201cRun NPM install\u201d o <code>npm ci<\/code>.<\/li>\n\n\n\n<li><strong>Build<\/strong> si aplica: <code>npm run build<\/code>.<\/li>\n\n\n\n<li>Verificar <strong>variables de entorno<\/strong>.<\/li>\n\n\n\n<li><strong>Restart App<\/strong>.<\/li>\n\n\n\n<li>Probar <strong>\/health<\/strong> o una ruta de verificaci\u00f3n.<\/li>\n\n\n\n<li>Revisar <strong>Logs<\/strong> y <strong>Passenger log<\/strong>.<\/li>\n\n\n\n<li>Si algo falla, <strong>rollback<\/strong> con el commit anterior o ZIP previo.<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Errores comunes y soluciones r\u00e1pidas<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>S\u00edntoma<\/th><th>Causa probable<\/th><th>Soluci\u00f3n<\/th><\/tr><\/thead><tbody><tr><td>Veo \u201cIt works!\u201d en lugar de mi app<\/td><td><code>startup file<\/code> incorrecto o ruta mal puesta<\/td><td>Ajusta <strong>Application root<\/strong> y <strong>startup file<\/strong> al <code>index.js<\/code> real; reinicia.<\/td><\/tr><tr><td>Error \u201cCannot find module \u2026\u201d<\/td><td>Faltan dependencias en servidor<\/td><td>Ejecuta <strong>Run NPM install<\/strong>; borra <code>node_modules<\/code> subidos por error.<\/td><\/tr><tr><td>App arranca local, pero no en cPanel<\/td><td>Diferencia de versi\u00f3n Node\/ESM vs CJS<\/td><td>Alinea Node LTS, revisa <code>\"type\": \"module\"<\/code> y los imports.<\/td><\/tr><tr><td>404 al refrescar rutas en SPA<\/td><td>Falta reescritura a <code>index.html<\/code><\/td><td>A\u00f1ade <code>.htaccess<\/code> de SPA o configura reescrituras en el panel.<\/td><\/tr><tr><td>Variables <code>process.env<\/code> vac\u00edas<\/td><td>No definidas en panel o mal nombradas<\/td><td>Define en cPanel y reinicia; loguea <code>process.env<\/code> clave (sin secretos en logs).<\/td><\/tr><tr><td>Build falla en servidor<\/td><td>Dependencias de build no instaladas<\/td><td>Usa <code>npm ci<\/code>\/<code>npm install --production=false<\/code>; revisa versi\u00f3n Node.<\/td><\/tr><tr><td>Timeout al levantar<\/td><td>App no escucha <code>process.env.PORT<\/code><\/td><td>Usa <code>process.env.PORT<\/code> y confirma que el server hace <code>listen<\/code>.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Para m\u00ed, la gracia de cPanel es que el flujo <strong>subir c\u00f3digo \u2192 instalar paquetes \u2192 reiniciar<\/strong> es tan natural que <strong>reduce errores habituales<\/strong> (rutas mal configuradas, procesos colgados). Si luego necesitas elasticidad extra, te pasas a VPS.<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Preguntas frecuentes<\/h2>\n\n\n\n<p><strong>\u00bfD\u00f3nde poner Application root y URL?<\/strong><br>Root apunta a la <strong>carpeta<\/strong> de tu app; URL al <strong>dominio\/subdominio<\/strong> que servir\u00e1 el tr\u00e1fico.<\/p>\n\n\n\n<p><strong>\u00bfQu\u00e9 pongo en Application startup file?<\/strong><br>Tu archivo que <strong>inicia<\/strong> el servidor: <code>index.js<\/code>, <code>app.js<\/code>, <code>server.js<\/code> o el generado en <code>dist\/<\/code>.<\/p>\n\n\n\n<p><strong>\u00bfDebo subir <code>node_modules<\/code>?<\/strong><br>No. S\u00fabelo sin <code>node_modules<\/code> y usa <strong>Run NPM install<\/strong> en el servidor.<\/p>\n\n\n\n<p><strong>\u00bfPor qu\u00e9 aparece \u201cIt works!\u201d?<\/strong><br>Porque el <code>startup file<\/code> o el root no apuntan a tu servidor. Corrige rutas y reinicia.<\/p>\n\n\n\n<p><strong>\u00bfC\u00f3mo gestiono variables de entorno y logs?<\/strong><br>Variables desde el panel; logs en <strong>Passenger log<\/strong> y registros de la app (a\u00f1ade <code>console.log<\/code> inteligentes al arrancar).<\/p>\n\n\n\n<p><strong>\u00bfESM o CommonJS?<\/strong><br>Elige uno y s\u00e9 consistente. Si usas ESM, marca <code>\"type\": \"module\"<\/code> y cambia <code>require<\/code> por <code>import<\/code>.<\/p>\n\n\n\n<p><strong>\u00bfCu\u00e1ndo conviene un VPS?<\/strong><br>Cuando necesitas <strong>libertad total<\/strong>, puertos personalizados, <strong>PM2<\/strong> avanzado, workers, colas, WebSockets a gran escala o pol\u00edticas de seguridad estrictas.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Instalar node.js en cpanel en VPS o Hosting<\/h2>\n\n\n\n<p>cPanel no pretende reemplazar a un VPS, pero ah\u00ed est\u00e1 su <strong>virtud<\/strong>: te da una <strong>rampa de entrada<\/strong> s\u00f3lida para desplegar Node.js sin fricci\u00f3n, con <strong>un panel gr\u00e1fico que reduce much\u00edsimo la complejidad inicial<\/strong>. En mi d\u00eda a d\u00eda, lo clave es tener claras tres cosas: <strong>versi\u00f3n de Node<\/strong>, <strong>startup file<\/strong> y <strong>dependencias<\/strong>. A partir de ah\u00ed, el ciclo <strong>subir \u2192 instalar \u2192 reiniciar<\/strong> te permite evolucionar tu proyecto con confianza. Para <strong>proyectos peque\u00f1os y medianos<\/strong>, es justo lo que necesitas para pasar de \u201ctengo c\u00f3digo\u201d a \u201ctengo producci\u00f3n\u201d.<\/p>\n\n\n\n<p><strong>Opini\u00f3n Personal<\/strong><\/p>\n\n\n\n<p>Instalar Node.js en cPanel me ha reconciliado con los despliegues \u201cr\u00e1pidos y sin drama\u201d. Durante a\u00f1os asoci\u00e9 Node a VPS, puertos, daemons y una lista infinita de peque\u00f1as batallas. Con cPanel, el proceso se vuelve l\u00f3gico: eliges versi\u00f3n LTS, apuntas el <strong>startup file<\/strong>, instalas dependencias, reinicias\u2026 y listo. Esa curva de entrada m\u00e1s suave me permite centrarme en lo que importa: que la app responda y que actualizar no sea una ruleta rusa.<\/p>\n\n\n\n<p>\u00bfEs perfecto? No. Si buscas control total de sistema, orquestaci\u00f3n avanzada o cargas bestias, un VPS sigue siendo el camino. Pero para proyectos peque\u00f1os y medianos, o para equipos que no quieren pelearse con la infraestructura desde el minuto uno, cPanel ofrece justo lo que necesito: <strong>una rampa de lanzamiento estable<\/strong>. Me encanta que el flujo <strong>subir \u2192 instalar \u2192 reiniciar<\/strong> reduzca errores tontos (rutas mal puestas, <code>node_modules<\/code> arrastrados, variables sin definir) y que el panel te gu\u00ede sin esconder lo esencial.<\/p>\n\n\n\n<p>Tambi\u00e9n valoro la claridad conceptual: separar <strong>Application root<\/strong>, <strong>URL<\/strong> y <strong>startup file<\/strong> te obliga a pensar la estructura. Y el hecho de que puedas gestionar variables de entorno y revisar logs desde el panel elimina muchas excusas. \u00bfLimitaciones? Las hay: versiones de Node atadas al proveedor, menos elasticidad con SSR exigente y poca gracia para experimentos raros. Pero esa es la gracia: no pretende serlo todo, pretende <strong>funcionar hoy<\/strong>.<\/p>\n\n\n\n<p>En resumen, cPanel no sustituye el poder de un servidor autogestionado, pero s\u00ed <strong>democratiza<\/strong> el despliegue de Node.js. Si tu prioridad es publicar r\u00e1pido, con orden y sin convertirte en SRE de la noche a la ma\u00f1ana, es una decisi\u00f3n que volver\u00eda a tomar.<\/p>\n\n\n\n<p>\u00bfT\u00fa qu\u00e9 opinas? \u00bfTe ha simplificado la vida o te has topado con l\u00edmites dolorosos? <strong>Cu\u00e9ntame tu experiencia y deja tus comentarios abajo<\/strong>: qu\u00e9 hosting usas, qu\u00e9 versi\u00f3n de Node, qu\u00e9 problemas te salieron y c\u00f3mo los resolviste. Tu feedback puede ayudar a m\u00e1s gente.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Requisitos y elegir cPanel para Node.js Si lo que quieres es poner una app en producci\u00f3n sin pelearte con un VPS, cPanel es tu mejor amigo. A m\u00ed instalar Node.js en cPanel y desplegar desde un entorno tan conocido me facilita la vida: pasas de configurar procesos, puertos y permisos a hacer clics y rellenar [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":7467,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[952],"tags":[689,319,1092,779,1249],"class_list":["post-7466","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guias","tag-cpanel","tag-instalar","tag-java","tag-linux","tag-node-js"],"_links":{"self":[{"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/posts\/7466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/comments?post=7466"}],"version-history":[{"count":1,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/posts\/7466\/revisions"}],"predecessor-version":[{"id":7470,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/posts\/7466\/revisions\/7470"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/media\/7467"}],"wp:attachment":[{"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/media?parent=7466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/categories?post=7466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hostingtg.com\/blog\/wp-json\/wp\/v2\/tags?post=7466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}