Pasar un WordPress de un hosting compartido a un VPS te da recursos dedicados, control sobre la versión de PHP y la caché, y acceso completo al servidor. La migración en sí es sencilla (copiar archivos y base de datos), pero para hacerla sin cortes ni pérdida de datos conviene seguir un orden: preparar el servidor, copiar, probar el sitio en el VPS antes de que lo vea nadie y solo entonces cambiar el DNS. En este tutorial migrarás un WordPress a un VPS con Ubuntu 24.04, Nginx, PHP 8.3-FPM y MySQL 8.0, y lo pondrás en marcha con HTTPS.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 GB de RAM y espacio en disco de sobra para el sitio y una copia.
- Un usuario no root con privilegios
sudo. - Acceso al hosting actual: panel (cPanel, Plesk o similar) con phpMyAdmin y gestor de archivos, o mejor aún acceso SSH.
- Acceso a la gestión DNS de tu dominio. En los ejemplos se usa
example.com; sustitúyelo por el tuyo yyour_server_ippor la IP del VPS.
Paso 1: Planificar la migración
Unos minutos de preparación evitan la mayoría de los problemas.
Baja el TTL del DNS. Al menos 24 horas antes de la migración, reduce el TTL de los registros A de example.com y www.example.com a 300 segundos en tu proveedor DNS. Así, cuando cambies la IP, los visitantes llegarán al VPS en minutos en lugar de horas.
Anota las versiones. En el panel de WordPress, ve a Herramientas > Salud del sitio > Información y apunta la versión de WordPress, la de PHP y el prefijo de las tablas de la base de datos. Ubuntu 24.04 trae PHP 8.3; si tu sitio funciona con PHP 7.4 o anterior, actualiza antes los plugins y el tema en el hosting actual y comprueba que son compatibles con PHP 8.
Comprueba dónde está el correo. Si tus buzones @example.com están en el hosting compartido, al migrar solo moverás la web: cambiarás únicamente los registros A y dejarás intactos los registros MX. Revisa también si el hosting te daba el DNS; en ese caso, antes de cancelar la cuenta tendrás que llevar la zona a otro proveedor.
Elige una ventana de poco tráfico. Si el sitio recibe pedidos o comentarios, todo lo que ocurra en el hosting antiguo entre la copia y el cambio de DNS se perdería. Lo resolverás con una sincronización final en el paso 9.
Paso 2: Preparar el VPS
Actualiza el sistema e instala Nginx, MySQL, PHP-FPM y las extensiones de PHP que necesita WordPress:
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx mysql-server php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd php8.3-intl php8.3-mbstring php8.3-xml php8.3-zip php-imagick unzip
Abre el firewall para SSH y para la web:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Instala WP-CLI, que usarás para ajustar la configuración y comprobar el sitio:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
Comprueba que los servicios están activos:
systemctl is-active nginx mysql php8.3-fpm
active
active
active
Paso 3: Crear la base de datos
Crea una base de datos y un usuario dedicados para WordPress. Sustituye your_strong_password por una contraseña larga y aleatoria (puedes generarla con openssl rand -base64 24):
sudo mysql
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wpuser'@'localhost';
EXIT;
Comprueba que el usuario puede conectarse:
mysql -u wpuser -p -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| wordpress |
+--------------------+
Paso 4: Exportar el sitio del hosting compartido
Necesitas dos cosas: los archivos de WordPress (sobre todo wp-content, que contiene temas, plugins y medios) y un volcado de la base de datos. Elige la opción según el acceso que te dé tu hosting.
Opción A: con acceso SSH
Es la opción más rápida y fiable. Conéctate al hosting y exporta la base de datos desde la carpeta de WordPress (normalmente public_html):
ssh your_hosting_user@your_hosting_host
cd ~/public_html
wp db export ~/wordpress.sql
Si el hosting no tiene WP-CLI, usa mysqldump con los datos de DB_NAME, DB_USER y DB_HOST que aparecen en wp-config.php:
mysqldump -h localhost -u hosting_db_user -p --single-transaction --no-tablespaces hosting_db_name > ~/wordpress.sql
Sal del hosting y, desde el VPS, trae los archivos y el volcado con rsync, que se puede reanudar si se corta la conexión:
sudo mkdir -p /var/www/example.com
sudo chown your_user:your_user /var/www/example.com
rsync -avz --progress your_hosting_user@your_hosting_host:public_html/ /var/www/example.com/
rsync -avz your_hosting_user@your_hosting_host:wordpress.sql ~/
Muchos hostings compartidos usan un puerto SSH distinto del 22; si es tu caso, añade -e 'ssh -p PUERTO' a rsync. La barra final en public_html/ copia el contenido de la carpeta, no la carpeta en sí.
Opción B: solo con el panel del hosting
- En phpMyAdmin, selecciona la base de datos de WordPress, abre Exportar, elige el método Rápido y el formato SQL, y descarga el archivo.
- En el Administrador de archivos, comprime la carpeta
public_html(o la del sitio) en un ZIP y descárgalo.
Sube ambos archivos al VPS desde tu equipo:
scp wordpress.sql public_html.zip your_user@your_server_ip:~/
Y en el VPS, descomprime el ZIP en la carpeta del sitio:
sudo mkdir -p /var/www/example.com
sudo chown your_user:your_user /var/www/example.com
unzip ~/public_html.zip -d ~/public_html_tmp
Según cómo se haya creado, el ZIP puede contener una carpeta public_html dentro. Localiza la carpeta que contiene wp-config.php y copia su contenido al destino:
find ~/public_html_tmp -maxdepth 2 -name wp-config.php
rsync -a ~/public_html_tmp/public_html/ /var/www/example.com/
Comprobar la copia
En cualquiera de los dos casos, comprueba que están los archivos clave y que el volcado no está vacío ni truncado. Un volcado completo termina con la línea -- Dump completed (mysqldump y WP-CLI) o con el cierre de la última tabla (phpMyAdmin):
ls /var/www/example.com/wp-config.php /var/www/example.com/wp-content
du -sh /var/www/example.com
tail -n 1 ~/wordpress.sql
/var/www/example.com/wp-config.php
/var/www/example.com/wp-content:
index.php languages plugins themes uploads
1.8G /var/www/example.com
-- Dump completed on 2026-09-25 10:14:02
Paso 5: Importar la base de datos
Importa el volcado en la base de datos que creaste en el paso 3:
mysql -u wpuser -p wordpress < ~/wordpress.sql
Comprueba que las tablas están y anota su prefijo:
mysql -u wpuser -p -e "SHOW TABLES;" wordpress | head -5
Tables_in_wordpress
wp_commentmeta
wp_comments
wp_links
wp_options
Si el hosting usaba un prefijo distinto de wp_ (por ejemplo wpxy_), no lo cambies: el wp-config.php que has copiado ya contiene el valor correcto en $table_prefix.
Paso 6: Ajustar wp-config.php y los permisos
El wp-config.php copiado sigue apuntando a la base de datos del hosting. Actualiza los datos de conexión con WP-CLI:
cd /var/www/example.com
wp config set DB_NAME wordpress
wp config set DB_USER wpuser
wp config set DB_PASSWORD 'your_strong_password'
wp config set DB_HOST localhost
Revisa además restos del hosting anterior que no funcionarán en el VPS:
- Carpeta
wp-content/mu-plugins: muchos hostings instalan aquí plugins propios (de caché, de su panel o de seguridad). Si ves archivos que corresponden al hosting, muévelos fuera de esa carpeta. - Archivos
wp-content/advanced-cache.phpywp-content/object-cache.php: si los creó un plugin de caché del hosting (por ejemplo LiteSpeed Cache, que depende del servidor LiteSpeed), desactiva ese plugin y borra estos archivos. - Archivo
.htaccess: Nginx no lo usa. Puedes dejarlo, pero cualquier regla personalizada que tuviera (redirecciones, bloqueos) hay que trasladarla a la configuración de Nginx.
Para desactivar un plugin de caché del hosting sin entrar al panel:
wp plugin deactivate litespeed-cache --skip-plugins --skip-themes
Asigna los archivos al usuario de Nginx y PHP-FPM, con permisos 755 para directorios y 644 para archivos:
sudo chown -R www-data:www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod 755 {} +
sudo find /var/www/example.com -type f -exec chmod 644 {} +
sudo chmod 640 /var/www/example.com/wp-config.php
Comprueba que WordPress conecta con la base de datos y lee la URL del sitio:
sudo -u www-data wp --path=/var/www/example.com option get siteurl
https://example.com
Paso 7: Configurar Nginx
Todavía no puedes obtener un certificado de Let's Encrypt porque el dominio apunta al hosting antiguo. Mientras tanto usarás el certificado autofirmado que genera Ubuntu (snakeoil), suficiente para probar el sitio. Asegúrate de que existe:
sudo apt install -y ssl-cert
ls /etc/ssl/certs/ssl-cert-snakeoil.pem
Crea el bloque de servidor:
sudo nano /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
root /var/www/example.com;
index index.php;
client_max_body_size 64m;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.(?!well-known) {
deny all;
}
}
La redirección a HTTPS está dentro de location / a propósito: así Certbot podrá añadir su ruta de validación en el paso 10 sin que la redirección la intercepte.
Activa el sitio, desactiva el sitio por defecto y recarga Nginx:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
Sube también el límite de subida de PHP para que coincida con el de Nginx:
sudo nano /etc/php/8.3/fpm/conf.d/99-wordpress.ini
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
sudo systemctl restart php8.3-fpm
Paso 8: Probar el sitio antes de cambiar el DNS
Puedes ver el sitio del VPS con su dominio real sin que el resto del mundo lo vea, haciendo que solo tu equipo resuelva example.com a la IP del VPS. Desde el servidor, compruébalo primero con curl:
curl -skI --resolve example.com:443:127.0.0.1 https://example.com/ | head -1
HTTP/2 200
Después, en tu equipo local, edita el archivo hosts (/etc/hosts en Linux y macOS, C:\Windows\System32\drivers\etc\hosts en Windows, abriendo el editor como administrador) y añade:
your_server_ip example.com www.example.com
Abre https://example.com en el navegador. Verás un aviso de certificado no válido porque es el autofirmado: acéptalo temporalmente. Revisa:
- La portada, varias entradas y páginas, y el buscador.
- Que las imágenes cargan (están en
wp-content/uploads). - El acceso a
/wp-adminy que puedes subir una imagen nueva. - Formularios, carrito y checkout si los tienes.
Mientras navegas, vigila los errores en el servidor:
sudo tail -f /var/log/nginx/error.log /var/log/php8.3-fpm.log
Cuando termines, quita la línea del archivo hosts para volver a ver el sitio real.
Paso 9: Sincronizar los últimos cambios y cambiar el DNS
Si desde la copia del paso 4 se han publicado entradas, recibido comentarios o pedidos, vuelve a copiar la base de datos justo antes del cambio. Para no perder nada entre la copia y el cambio de DNS, activa en el hosting antiguo el modo mantenimiento o evita publicar durante ese rato.
Con acceso SSH, repite la exportación en el hosting y, desde el VPS, trae el volcado y los medios nuevos:
rsync -avz your_hosting_user@your_hosting_host:wordpress.sql ~/
rsync -avz your_hosting_user@your_hosting_host:public_html/wp-content/uploads/ /tmp/uploads-sync/
sudo rsync -a --chown=www-data:www-data /tmp/uploads-sync/ /var/www/example.com/wp-content/uploads/
Si solo tienes acceso al panel, repite la exportación de phpMyAdmin, descarga las carpetas de uploads que hayan cambiado y súbelas con scp como en el paso 4.
Los volcados de mysqldump y wp db export incluyen DROP TABLE antes de cada tabla, así que reemplazan los datos anteriores al importarlos. Los de phpMyAdmin no lo incluyen por defecto: en ese caso, borra antes las tablas de WordPress con sudo -u www-data wp --path=/var/www/example.com db clean --yes. Después importa el volcado:
mysql -u wpuser -p wordpress < ~/wordpress.sql
Ahora cambia en tu proveedor DNS los registros A de example.com y www.example.com (y los AAAA si existen) a your_server_ip. No toques los registros MX ni los TXT del correo. Comprueba la resolución:
dig +short example.com
dig +short www.example.com
203.0.113.10
203.0.113.10
Con el TTL a 300 segundos, la mayoría de los visitantes llegarán al VPS en pocos minutos.
Paso 10: Obtener el certificado de Let's Encrypt
Cuando el dominio ya resuelve al VPS, sustituye el certificado autofirmado por uno válido. El plugin de Nginx de Certbot lo obtiene y lo instala en el bloque de servidor:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
Comprueba que Nginx usa ya el certificado nuevo y que la renovación automática funciona:
sudo nginx -T 2>/dev/null | grep ssl_certificate
sudo certbot renew --dry-run
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
Si el sitio del hosting usaba http://, actualiza las URL guardadas en la base de datos. Revisa primero cuántas se cambiarían con --dry-run:
sudo -u www-data wp --path=/var/www/example.com search-replace 'http://example.com' 'https://example.com' --skip-columns=guid --dry-run
Si el resultado es razonable, ejecútalo sin --dry-run. search-replace maneja correctamente los datos serializados de PHP, algo que un simple REPLACE en SQL rompería.
Paso 11: Tareas posteriores a la migración
Correo saliente. En el hosting compartido, WordPress enviaba los correos (formularios, pedidos, restablecimiento de contraseña) con el servidor de correo del hosting. El VPS no tiene uno configurado, así que esos correos no saldrán. Instala un plugin SMTP y configúralo con tu proveedor de correo o un servicio de envío transaccional usando el puerto 587 con autenticación.
WP-Cron. Para que las tareas programadas se ejecuten aunque no haya visitas, desactiva WP-Cron y lánzalo desde el cron del sistema:
sudo -u www-data wp --path=/var/www/example.com config set DISABLE_WP_CRON true --raw
echo '*/5 * * * * www-data /usr/local/bin/wp --path=/var/www/example.com cron event run --due-now --quiet' | sudo tee /etc/cron.d/wordpress
Enlaces permanentes. Si alguna URL da 404, entra en Ajustes > Enlaces permanentes y pulsa Guardar sin cambiar nada para regenerar las reglas.
No canceles el hosting todavía. Mantenlo al menos una semana: algunos visitantes con DNS en caché seguirán llegando allí durante unas horas y te servirá como copia de seguridad. Cuando canceles, conserva el volcado y el archivo de la copia en un lugar seguro fuera del VPS.
Solución de problemas
- "Error establishing a database connection": los datos de
wp-config.phpno coinciden con los del paso 3. Compruébalos conwp config get DB_USERy prueba a conectar a mano conmysql -u wpuser -p wordpress. - Pantalla en blanco o error 500: casi siempre es un plugin incompatible con PHP 8.3. Revisa
/var/log/php8.3-fpm.logy/var/log/nginx/error.log, y desactiva el plugin que aparezca conwp plugin deactivate nombre --skip-plugins. - Bucle de redirecciones: suele venir de un plugin de caché o de redirecciones del hosting, o de un
siteurlconwwwdistinto del que usas. Compruebawp option get siteurlywp option get home. - Imágenes rotas con URL del hosting antiguo: si el sitio usaba un dominio temporal o una ruta distinta, sustituye la URL antigua por la nueva con
wp search-replace. ERROR 1273 Unknown collational importar: el volcado usa una intercalación que tu servidor no reconoce. Ocurre al importar en MariaDB un volcado de MySQL 8 conutf8mb4_0900_ai_ci; con MySQL 8.0 en el VPS, como en esta guía, no pasa.
Conclusión
Has migrado WordPress de un hosting compartido a un VPS con Ubuntu 24.04: preparaste Nginx, PHP-FPM y MySQL, copiaste archivos y base de datos, probaste el sitio con el archivo hosts antes de que lo viera nadie, sincronizaste los últimos cambios, cambiaste el DNS y activaste HTTPS con Let's Encrypt. Como siguientes pasos, configura copias de seguridad automáticas fuera del servidor, añade caché de página y de objetos para aprovechar los recursos del VPS, y endurece la seguridad de WordPress ajustando permisos y protegiendo el acceso.
