Tema
Hosting compartido con cPanel
El hosting compartido con cPanel es, por mucho, lo que más vas a encontrar con clientes pequeños: consultorios, restaurantes, despachos, escuelas. En esta lección aprenderás a moverte en cPanel como un profesional y a publicar dos tipos de proyecto: un sitio estático/VitePress y un proyecto PHP + MySQL.
Concepto
cPanel es un panel web que te permite administrar tu parte del servidor sin usar la terminal. Al contratar un plan recibes:
- Una URL de acceso, normalmente
https://tudominio.com/cpanelohttps://tudominio.com:2083. - Usuario y contraseña de cPanel.
- Datos FTP (servidor, usuario, puerto).
- Los nameservers del hosting (ver Dominios y DNS).
hPanel, Plesk, DirectAdmin
Algunos proveedores usan su propio panel (Hostinger usa hPanel) u otros como Plesk o DirectAdmin. Los conceptos son idénticos: administrador de archivos, bases de datos, correos, dominios y SSL. Solo cambian los nombres de los menús.
La carpeta más importante: public_html
txt
/home/usuario/
├── public_html/ ← lo que está aquí se ve en https://tudominio.com
│ ├── index.html
│ └── .htaccess
├── tienda.tudominio.com/ ← carpeta de un subdominio (según cómo lo crees)
├── mail/ ← buzones de correo (no tocar)
├── logs/ ← registros de acceso
└── privado/ ← archivos fuera de public_html: NO accesibles por webTodo lo que pongas en public_html es público. Archivos sensibles (configuraciones, respaldos) deben ir fuera de esa carpeta.
Tour por las secciones de cPanel
| Sección | Para qué la usarás |
|---|---|
| Administrador de archivos | Subir, editar, extraer ZIP, cambiar permisos. |
| Cuentas FTP | Crear accesos FTP (por ejemplo para otro desarrollador). |
| Bases de datos MySQL | Crear base, usuario y asignar privilegios. |
| phpMyAdmin | Importar/exportar .sql, ver tablas. |
| Cuentas de correo | Crear hola@dominio.com, ver configuración IMAP/SMTP, Webmail. |
| Dominios | Subdominios, dominios adicionales (addon). |
| Zone Editor | Editar registros DNS (si los nameservers apuntan al hosting). |
| SSL/TLS Status | Activar AutoSSL (certificado gratis). |
| MultiPHP Manager | Elegir versión de PHP por dominio. |
| Cron Jobs | Ejecutar tareas programadas. |
| Respaldos | Descargar copia completa o de la base de datos. |
Subir archivos
Opción 1: Administrador de archivos (rápido)
- Comprime tu proyecto en un ZIP en tu computadora.
- cPanel → Administrador de archivos → entra a
public_html. - Cargar → elige el ZIP.
- Clic derecho sobre el ZIP → Extraer.
- Verifica que
index.htmloindex.phpquede directamente dentro depublic_html(no en una subcarpeta). - Borra el ZIP.
Opción 2: FTP con FileZilla (cómodo para muchos archivos)
- Instala FileZilla Client.
- Archivo → Gestor de sitios → Nuevo sitio:
txt
Protocolo: FTP - Protocolo de transferencia de archivos
Servidor: ftp.tudominio.com (o la IP que te dio el hosting)
Puerto: 21
Cifrado: Requiere FTP explícito sobre TLS ← más seguro que FTP plano
Modo: Normal
Usuario: usuario@tudominio.com
Contraseña: ********- Conecta. A la izquierda tus archivos locales; a la derecha el servidor. Arrastra el contenido de tu carpeta al
public_htmlremoto.
Buena práctica
Si el hosting ofrece SFTP (puerto 22) úsalo: todo viaja cifrado. Nunca uses FTP sin TLS en una red pública.
Bases de datos MySQL
En cPanel → Bases de datos MySQL:
- Crear base de datos: escribe
tienda. cPanel le antepone tu usuario:usuario_tienda. - Agregar usuario:
usuario_appcon una contraseña fuerte (usa el generador). - Agregar usuario a la base de datos → marca TODOS LOS PRIVILEGIOS → Hacer cambios.
Apunta los datos; los usarás en tu código:
env
DB_HOST=localhost
DB_NAME=usuario_tienda
DB_USER=usuario_app
DB_PASS=La-Contraseña-GeneradaError común
Usar 127.0.0.1 o el dominio como host. En hosting compartido casi siempre es localhost. Otro clásico: olvidar el prefijo del usuario en el nombre de la base.
Correos, subdominios y SSL
Cuentas de correo
Correo electrónico → Cuentas de correo → Crear. Luego "Connect Devices" te muestra los datos IMAP/SMTP (normalmente mail.tudominio.com, IMAP 993, SMTP 465 con SSL). El cliente puede leerlo en Webmail, Outlook, Gmail o el celular.
Subdominios
Dominios → Crear un dominio nuevo (o "Subdominios" en versiones antiguas): escribe blog.tudominio.com y define su carpeta raíz (ej. public_html/blog o blog.tudominio.com).
SSL gratis
SSL/TLS Status → Run AutoSSL. En minutos tendrás certificado gratuito (Let's Encrypt o Sectigo) que se renueva solo. Requisito: que el dominio ya apunte al hosting.
Después fuerza HTTPS creando o editando public_html/.htaccess:
apache
# Redirigir todo el tráfico HTTP a HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]Versión de PHP
MultiPHP Manager → elige el dominio → PHP 8.2 o superior. En Select PHP Version (si existe) activas extensiones (pdo_mysql, mbstring, intl, gd).
Proyecto 1: subir un sitio estático o VitePress
Un sitio estático (HTML/CSS/JS, Vite, Astro, VitePress) se compila en tu computadora y solo subes el resultado.
1. Compila
Para VitePress (con el script estándar del package.json):
bash
# instala dependencias si no lo has hecho
npm install
# genera el sitio en docs/.vitepress/dist
npm run docs:buildPara un proyecto Vite/React/Vue: npm run build → carpeta dist/.
La opción base
Si el sitio va en la raíz del dominio (https://tudominio.com/) no necesitas nada. Si va en una subcarpeta (https://tudominio.com/docs/), configura base: '/docs/' en .vitepress/config.mts (o en vite.config.js) antes de compilar.
2. Sube el contenido de dist
Sube el contenido de docs/.vitepress/dist (no la carpeta dist en sí) a public_html. Debe quedar public_html/index.html, public_html/assets/, etc.
3. URLs limpias y página 404
Si en VitePress usas cleanUrls: true, las rutas no tienen .html (/guia/inicio). Apache necesita saber que debe servir inicio.html. Crea public_html/.htaccess:
apache
# Forzar HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]
# URLs limpias: /guia/inicio → /guia/inicio.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [L]
# Página de error personalizada que genera VitePress
ErrorDocument 404 /404.html
# Caché larga para archivos con hash en /assets
<IfModule mod_headers.c>
<FilesMatch "\.(js|css|woff2|svg|png|jpg|webp)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>SPA (React/Vue con router)
Para una SPA, todas las rutas deben caer en index.html:
apache
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]Proyecto 2: subir un proyecto PHP + MySQL
Supongamos un sistema de contactos con esta estructura:
txt
mi-proyecto/
├── config/
│ └── config.php ← credenciales (no debe ser público)
├── public/ ← lo único que debe ser público
│ ├── index.php
│ ├── guardar.php
│ └── css/estilos.css
└── database/
└── esquema.sql1. Exporta la base de datos local
Desde phpMyAdmin local (XAMPP/Laragon): base → Exportar → Rápido → SQL. O por terminal:
bash
mysqldump -u root -p mi_base > respaldo.sql2. Crea la base en cPanel e importa
Crea base y usuario (ver arriba). Luego phpMyAdmin → selecciona usuario_tienda → Importar → elige respaldo.sql → Continuar.
Error común
Si el .sql trae CREATE DATABASE mi_base; y USE mi_base;, bórralos antes de importar: en hosting compartido no tienes permiso para crear bases desde SQL y el nombre real lleva prefijo.
3. Configuración de conexión
Coloca config/ fuera de public_html, por ejemplo en /home/usuario/mi-proyecto/config/config.php:
php
<?php
// config/config.php — fuera de public_html
return [
'db_host' => 'localhost',
'db_name' => 'usuario_tienda',
'db_user' => 'usuario_app',
'db_pass' => 'La-Contraseña-Generada',
'debug' => false, // en producción NUNCA mostrar errores
];Y la conexión con PDO:
php
<?php
// public_html/conexion.php
$config = require __DIR__ . '/../mi-proyecto/config/config.php';
ini_set('display_errors', $config['debug'] ? '1' : '0');
try {
$pdo = new PDO(
"mysql:host={$config['db_host']};dbname={$config['db_name']};charset=utf8mb4",
$config['db_user'],
$config['db_pass'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
} catch (PDOException $e) {
error_log($e->getMessage()); // queda en el log, no en pantalla
http_response_code(500);
exit('Error interno. Intenta más tarde.');
}4. Sube los archivos
- El contenido de
public/→ apublic_html/. - La carpeta
config/→ a/home/usuario/mi-proyecto/config/.
5. Permisos
- Carpetas: 755. Archivos: 644. Archivo de configuración: 600 o 640 si el hosting lo permite.
- Nunca 777.
En el Administrador de archivos: clic derecho → Change Permissions.
6. Protege archivos sensibles con .htaccess
apache
# Bloquear acceso a archivos ocultos y de configuración
<FilesMatch "^\.|\.(env|sql|log|ini|sh)$">
Require all denied
</FilesMatch>
# Desactivar el listado de carpetas
Options -IndexesErrores típicos al subir PHP
| Síntoma | Causa probable |
|---|---|
| Página en blanco o error 500 | Error de PHP: revisa error_log en la carpeta o en Errores de cPanel. |
SQLSTATE[HY000] [1045] Access denied | Usuario/contraseña mal o usuario no agregado a la base. |
SQLSTATE[HY000] [2002] | Host incorrecto: usa localhost. |
| Acentos raros (é) | Falta charset=utf8mb4 en el DSN o las tablas no son utf8mb4. |
Call to undefined function | Versión de PHP vieja o extensión desactivada. |
Se descarga el .php en vez de ejecutarse | El dominio no tiene PHP asignado; revisa MultiPHP. |
Cron jobs
Para ejecutar un script cada día a las 3:00 a. m.: cPanel → Cron Jobs:
bash
0 3 * * * /usr/local/bin/php /home/usuario/mi-proyecto/tareas/limpiar.php >/dev/null 2>&1Ejercicios
- Crea en un hosting (o simúlalo en papel) la base
usuario_blog, el usuariousuario_blogappy escribe el array de configuración correspondiente. - Escribe un
.htaccessque fuerce HTTPS, quite elwwwy desactive el listado de carpetas. - Tu VitePress se publicará en
https://cliente.com/manual/. ¿Qué cambias antes de compilar y dónde subes los archivos?
Ver solución
php
<?php
return [
'db_host' => 'localhost',
'db_name' => 'usuario_blog',
'db_user' => 'usuario_blogapp',
'db_pass' => 'Contraseña-Fuerte',
'debug' => false,
];apache
Options -Indexes
RewriteEngine On
# Quitar www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [L,R=301]
# Forzar HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]- En
.vitepress/config.mtsagregasbase: '/manual/', compilas connpm run docs:buildy subes el contenido dedocs/.vitepress/distapublic_html/manual/.
Resumen
public_htmles la carpeta pública; lo sensible va fuera.- Sube por Administrador de archivos (ZIP) o FTP/SFTP con FileZilla.
- Base de datos: crear base + usuario + asignar privilegios; host
localhosty nombres con prefijo. - AutoSSL da HTTPS gratis; fuérzalo con
.htaccess. - Estáticos/VitePress: compila y sube el contenido de
dist. PHP: sube, importa la base, configura PDO y permisos 755/644. - Siguiente: Linux para servidores.