Pasar de un hosting compartido a un VPS te da recursos dedicados, control total del software y la posibilidad de alojar lo que necesites, a cambio de administrar tú el servidor. La migración en sí es sencilla si se hace en orden: preparar el servidor, copiar la web mientras la antigua sigue funcionando, probarla sin tocar el DNS y hacer el cambio final con una ventana corta. En este tutorial migrarás una web PHP con MySQL (por ejemplo, WordPress) desde un hosting con cPanel a un VPS con Ubuntu 24.04, Apache, PHP 8.3 y MariaDB, y decidirás qué hacer con el correo.

Requisitos previos

Para seguir esta guía necesitas:

  • Un VPS con Ubuntu 24.04 LTS recién instalado, por ejemplo un VPS de CubePath, y un usuario no root con privilegios sudo. Para una web PHP típica basta con 2 GB de RAM.
  • Acceso al panel del hosting actual (cPanel u otro similar) y, si es posible, acceso SSH.
  • Acceso a la zona DNS del dominio: en el propio hosting, en tu registrador o en un proveedor como Cloudflare.
  • Tu dominio, al que en esta guía se llama your_domain, y la IP pública del VPS, your_server_ip.

Paso 1: Hacer inventario y bajar el TTL del DNS

Antes de copiar nada, anota lo que tiene tu hosting actual. En cPanel encontrarás casi todo en la página principal:

  • Dominios y subdominios alojados, y la carpeta de cada uno (normalmente public_html).
  • Versión de PHP (en "Seleccionar versión de PHP" o "MultiPHP Manager") y extensiones activas.
  • Bases de datos MySQL, sus usuarios y en qué archivo de la aplicación se configuran (en WordPress, wp-config.php).
  • Cuentas de correo y reenvíos.
  • Tareas cron (en "Trabajos de cron").
  • Todos los registros de la zona DNS (en "Zone Editor"): exporta o copia los registros A, AAAA, CNAME, MX y TXT (SPF, DKIM, verificaciones).

Después, entre 24 y 48 horas antes de la migración, baja el TTL de los registros A y AAAA del dominio a 300 segundos. Así, cuando cambies la IP, los resolutores dejarán de usar la antigua en unos minutos en lugar de horas. Comprueba el TTL actual:

dig +noall +answer your_domain A
your_domain.		300	IN	A	203.0.113.10

El segundo campo es el TTL en segundos.

Paso 2: Preparar el VPS

Conéctate al VPS, actualiza el sistema y activa el cortafuegos permitiendo SSH, HTTP y HTTPS:

sudo apt update && sudo apt upgrade -y
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable

Instala Apache, PHP 8.3 con las extensiones más habituales y MariaDB. Se usa Apache porque la mayoría de webs de hosting compartido dependen de archivos .htaccess, que Nginx no interpreta:

sudo apt install apache2 mariadb-server php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl php-imagick

Si la web necesitaba otras extensiones según tu inventario, instálalas también con el prefijo php-. Activa el módulo rewrite, necesario para las URL amigables:

sudo a2enmod rewrite
sudo systemctl restart apache2

Asegura la instalación de MariaDB (establece la contraseña de root si lo deseas, elimina usuarios anónimos y la base de datos de pruebas):

sudo mariadb-secure-installation

Comprueba las versiones:

php -v | head -n 1
sudo mariadb -e "SELECT VERSION();"
PHP 8.3.6 (cli) (built: ...) (NTS)

Si tu hosting usaba una versión antigua de PHP, como 7.4, prueba la web con cuidado en el paso 6: algunos plugins o temas antiguos no funcionan con PHP 8.

Paso 3: Copiar los archivos de la web

Primero copiarás la web a una carpeta de trabajo en tu directorio personal del VPS, ~/site, donde puedes escribir sin sudo. En el paso 5 la pasarás a /var/www con los permisos correctos:

mkdir -p ~/site

Opción A: con acceso SSH al hosting

Es la forma más rápida y permite repetir la sincronización en el corte final. Desde el VPS, copia public_html con rsync (sustituye cpanel_user y old_host; muchos hostings usan un puerto SSH distinto del 22, indícalo con -e "ssh -p 2222"):

rsync -avz --progress cpanel_user@old_host:public_html/ ~/site/

La barra final en public_html/ copia el contenido de la carpeta, no la carpeta en sí.

Opción B: con una copia completa de cPanel

Si no tienes SSH, en cPanel ve a "Copia de seguridad" y genera una "copia de seguridad completa". Descarga el archivo backup-...tar.gz y súbelo al VPS desde tu equipo:

scp backup-9.25.2026_10-00-00_cpanel_user.tar.gz your_user@your_server_ip:~

En el VPS, extráelo y copia la carpeta de la web:

tar -xzf backup-9.25.2026_10-00-00_cpanel_user.tar.gz
rsync -a backup-9.25.2026_10-00-00_cpanel_user/homedir/public_html/ ~/site/

La copia de cPanel contiene también los volcados de las bases de datos en la carpeta mysql/, que usarás en el siguiente paso.

Con cualquiera de las dos opciones, comprueba que están los archivos esperados:

ls -la ~/site

Paso 4: Migrar la base de datos

Exporta la base de datos del hosting. Con SSH, genera el volcado allí (sustituye cpanel_db y cpanel_dbuser por los de tu inventario; -t permite que mysqldump te pida la contraseña) y tráelo al VPS:

ssh -t cpanel_user@old_host "mysqldump --single-transaction -u cpanel_dbuser -p cpanel_db > cpanel_db.sql"
scp cpanel_user@old_host:cpanel_db.sql ~/cpanel_db.sql

Sin SSH, usa el volcado mysql/cpanel_db.sql de la copia completa o exporta la base de datos desde phpMyAdmin en formato SQL.

En el VPS, crea la base de datos y un usuario con acceso solo a ella. Sustituye your_strong_password por una contraseña larga y aleatoria:

sudo mariadb
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
EXIT;

Importa el volcado:

sudo mariadb appdb < ~/cpanel_db.sql

Comprueba que las tablas están ahí:

sudo mariadb appdb -e "SHOW TABLES;" | head

Ahora actualiza la configuración de la aplicación con los datos nuevos. En WordPress, edita wp-config.php:

nano ~/site/wp-config.php
define( 'DB_NAME', 'appdb' );
define( 'DB_USER', 'appuser' );
define( 'DB_PASSWORD', 'your_strong_password' );
define( 'DB_HOST', 'localhost' );

Deja igual el prefijo de tablas ($table_prefix): debe coincidir con el de las tablas importadas.

Paso 5: Configurar Apache

Copia la web a su ubicación definitiva y da la propiedad de los archivos al usuario de Apache, con permisos 755 para directorios y 644 para archivos. WordPress necesita escribir en su carpeta para instalar actualizaciones y subir medios:

sudo mkdir -p /var/www/your_domain
sudo rsync -a ~/site/ /var/www/your_domain/
sudo chown -R www-data:www-data /var/www/your_domain
sudo find /var/www/your_domain -type d -exec chmod 755 {} +
sudo find /var/www/your_domain -type f -exec chmod 644 {} +

Crea el host virtual:

sudo nano /etc/apache2/sites-available/your_domain.conf
<VirtualHost *:80>
    ServerName your_domain
    ServerAlias www.your_domain
    DocumentRoot /var/www/your_domain

    <Directory /var/www/your_domain>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/your_domain_error.log
    CustomLog ${APACHE_LOG_DIR}/your_domain_access.log combined
</VirtualHost>

AllowOverride All permite que funcionen los .htaccess de la web. Activa el sitio, desactiva el de ejemplo y comprueba la sintaxis:

sudo a2ensite your_domain.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest
Syntax OK

Recarga Apache:

sudo systemctl reload apache2

Paso 6: Probar la web antes de cambiar el DNS

Puedes ver la web del VPS con su dominio real sin afectar a nadie más: basta con que tu equipo resuelva el dominio a la IP nueva. En tu ordenador (no en el VPS), edita el archivo hosts: /etc/hosts en Linux y macOS, o C:\Windows\System32\drivers\etc\hosts en Windows, abierto como administrador. Añade:

your_server_ip your_domain www.your_domain

Abre http://your_domain en el navegador y revisa la portada, varias páginas internas, el inicio de sesión en el panel de administración, los formularios y la subida de un archivo. Si algo falla, el log de errores tiene la causa:

sudo tail -n 50 /var/log/apache2/your_domain_error.log

Cuando termines, elimina la línea del archivo hosts.

Paso 7: Migrar las tareas cron

Las tareas cron de cPanel no se copian con los archivos. Añádelas al usuario www-data, para que se ejecuten con los mismos permisos que la web:

sudo crontab -u www-data -e

Adapta las rutas de tu inventario. Por ejemplo, el cron de WordPress cada 15 minutos:

*/15 * * * * php /var/www/your_domain/wp-cron.php > /dev/null 2>&1

Paso 8: Hacer el corte final y cambiar el DNS

Si la web recibe cambios constantes (pedidos, comentarios, usuarios), haz una última sincronización justo antes del cambio para no perder nada. Pon la web antigua en modo mantenimiento o desactiva los formularios, y repite la copia de archivos y de la base de datos:

rsync -avz --exclude=wp-config.php cpanel_user@old_host:public_html/ ~/site/
sudo rsync -a ~/site/ /var/www/your_domain/
sudo chown -R www-data:www-data /var/www/your_domain

--exclude=wp-config.php evita sobrescribir la configuración que ya adaptaste. Repite también la exportación e importación de la base de datos:

ssh -t cpanel_user@old_host "mysqldump --single-transaction -u cpanel_dbuser -p cpanel_db > cpanel_db.sql"
scp cpanel_user@old_host:cpanel_db.sql ~/cpanel_db.sql
sudo mariadb appdb < ~/cpanel_db.sql

El volcado incluye DROP TABLE IF EXISTS para cada tabla, así que sustituye limpiamente los datos importados en el paso 4. Después, en tu proveedor de DNS, cambia los registros A de your_domain y www a your_server_ip. Si tenías un registro AAAA apuntando al hosting antiguo, cámbialo por la IPv6 del VPS o elimínalo. No toques todavía los registros MX (lo verás en el paso 10).

Comprueba la propagación con resolutores públicos:

dig +short your_domain A @1.1.1.1
dig +short your_domain A @8.8.8.8

Ambos deben devolver your_server_ip. Con el TTL de 300 segundos, la mayoría de visitantes estará en el VPS en pocos minutos.

Paso 9: Activar HTTPS con Let's Encrypt

No intentes llevarte el certificado del hosting: en el VPS generarás uno nuevo y gratuito con Certbot, que se renueva solo. Espera a que el DNS apunte al VPS (Let's Encrypt valida el dominio contra la IP real) e instala Certbot con su plugin para Apache:

sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d your_domain -d www.your_domain

Certbot pedirá un correo para avisos de caducidad, obtendrá el certificado y creará un host virtual HTTPS con redirección desde HTTP. Comprueba la renovación automática:

sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/your_domain/fullchain.pem (success)

Abre https://your_domain y confirma que el candado aparece sin avisos de contenido mixto. Si WordPress tenía guardada la URL con http://, actualízala en "Ajustes > Generales".

Paso 10: Decidir qué hacer con el correo

El hosting compartido suele incluir el correo del dominio. Montar un servidor de correo propio en un VPS (Postfix, Dovecot, antispam, reputación de la IP) es un proyecto en sí mismo, así que tienes tres opciones:

  • Mantener el correo en el hosting actual. Deja los registros MX como están y no canceles el plan de hosting. Es lo más sencillo a corto plazo.
  • Mover el correo a un proveedor dedicado (Google Workspace, Microsoft 365, Zoho u otro). Es la opción recomendada si vas a cancelar el hosting.
  • Montar tu propio servidor de correo en el VPS, solo si tienes experiencia administrándolos.

Si cambias de proveedor, crea las cuentas en el nuevo servicio y copia los buzones por IMAP con imapsync, que está en los repositorios de Ubuntu:

sudo apt install imapsync

Guarda cada contraseña en un archivo temporal para que no quede en el historial de la shell ni en la lista de procesos:

nano ~/pass1
nano ~/pass2
chmod 600 ~/pass1 ~/pass2

Copia el buzón (sustituye servidores y usuarios por los tuyos):

imapsync --host1 mail.your_domain --user1 info@your_domain --passfile1 ~/pass1 --ssl1 \
         --host2 imap.new_provider.com --user2 info@your_domain --passfile2 ~/pass2 --ssl2

imapsync puede repetirse sin duplicar mensajes. Ejecútalo una vez antes de cambiar los registros MX y otra justo después, para copiar lo que llegó entretanto. Luego borra los archivos de contraseñas y actualiza los registros MX, SPF y DKIM según las instrucciones del nuevo proveedor.

Un último detalle: la función mail() de PHP no enviará correo desde el VPS porque no hay un servidor de correo local. Configura la web para enviar por SMTP autenticado (en WordPress, con un plugin SMTP) usando tu proveedor de correo o un servicio de envío transaccional.

Solución de problemas

"Error establishing a database connection". Los datos de wp-config.php no coinciden con el usuario creado en el paso 4. Compruébalos con mariadb -u appuser -p appdb.

Las páginas internas dan 404 pero la portada funciona. El módulo rewrite no está activo o falta AllowOverride All. Revisa el paso 2 y el paso 5.

La web redirige a la IP antigua o al dominio temporal del hosting. La URL está guardada en la base de datos. En WordPress, revisa siteurl y home en la tabla wp_options.

Certbot falla con unauthorized o Timeout during connect. El DNS aún apunta al hosting antiguo o el puerto 80 está cerrado. Comprueba dig +short your_domain y sudo ufw status.

Conclusión

Tu web funciona ahora en un VPS con Ubuntu 24.04 bajo tu control, con Apache, PHP 8.3, MariaDB y HTTPS automático, y el cambio se ha hecho con un corte de pocos minutos. Mantén el hosting antiguo activo al menos una semana por si necesitas recuperar algo y cancélalo cuando confirmes que todo, incluido el correo, funciona. Como siguientes pasos, configura copias de seguridad automáticas del VPS, instala Fail2ban para proteger SSH y activa las actualizaciones de seguridad desatendidas con unattended-upgrades.