WordPress Multisite permite gestionar varios sitios desde una sola instalación: todos comparten el núcleo, los plugins, los temas y la base de usuarios, pero cada sitio tiene su propio contenido, ajustes y administradores. Es útil para redes de marcas, sitios por idioma o departamentos de una misma organización. En este tutorial convertirás un WordPress existente en una red Multisite en Ubuntu 24.04 con Nginx y PHP-FPM, en modo subdominio o subdirectorio, le añadirás HTTPS y gestionarás los sitios con WP-CLI.
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.
- Un usuario no root con privilegios
sudo. - WordPress ya instalado y funcionando en
/var/www/wordpresscon Nginx, PHP 8.3-FPM y MySQL o MariaDB. En los ejemplos se usaexample.comcomo dominio: sustitúyelo por el tuyo. - Acceso al panel DNS de tu dominio.
NotaWordPress Multisite es una red para sitios que comparten código. Si los sitios no tienen relación entre sí o necesitan versiones distintas de plugins, es mejor mantener instalaciones separadas.
Subdominios o subdirectorios
Antes de empezar decide el tipo de red, porque cambiarlo después es laborioso:
| Tipo | URL de los sitios | DNS | Certificado TLS |
|---|---|---|---|
| Subdominios | tienda.example.com | Registro comodín *.example.com | Certificado comodín (validación DNS-01) |
| Subdirectorios | example.com/tienda | Nada adicional | Certificado normal |
Ten en cuenta dos detalles:
- En una red de subdirectorios, las entradas del sitio principal pasan a tener el prefijo
/blog/en sus enlaces permanentes para no chocar con los nombres de los sitios. Si tu sitio principal ya tiene tráfico y enlaces indexados, los subdominios evitan ese cambio. - En ambos casos puedes asignar después un dominio propio a cualquier sitio de la red (por ejemplo
otramarca.com), como se explica en el paso 7.
Paso 1: Hacer una copia de seguridad
La conversión modifica wp-config.php y crea tablas nuevas en la base de datos. Haz una copia de ambos antes de tocar nada. Sustituye wordpress y wpuser por el nombre de tu base de datos y tu usuario:
mkdir -p ~/backups
mysqldump -u wpuser -p --single-transaction wordpress > ~/backups/wordpress-$(date +%F).sql
sudo tar -czf ~/backups/wordpress-files-$(date +%F).tar.gz -C /var/www wordpress
Comprueba que los archivos existen y no están vacíos:
ls -lh ~/backups/
-rw-rw-r-- 1 your_user your_user 48M Sep 25 10:02 wordpress-2026-09-25.sql
-rw-r--r-- 1 root root 212M Sep 25 10:03 wordpress-files-2026-09-25.tar.gz
Paso 2: Instalar WP-CLI
WP-CLI es la herramienta de línea de comandos de WordPress. La usarás para convertir la instalación y gestionar la red. Descarga el archivo phar oficial y compruébalo:
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
Si muestra la versión de PHP y de WP-CLI, instálalo en el PATH:
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
Ejecutarás WP-CLI como el usuario del servidor web (www-data) para que los archivos que cree tengan el propietario correcto. Comprueba que ve tu instalación:
sudo -u www-data wp --path=/var/www/wordpress core version
6.8.2
Paso 3: Preparar el DNS
Si vas a usar subdirectorios, no necesitas cambios en el DNS y puedes pasar al paso 4.
Si vas a usar subdominios, crea en tu proveedor DNS un registro comodín que apunte a la IP del servidor, además del registro del dominio principal:
example.com A your_server_ip
*.example.com A your_server_ip
Cuando se haya propagado, cualquier subdominio debe resolver a tu servidor:
dig +short cualquiercosa.example.com
203.0.113.10
Paso 4: Convertir la instalación en una red
WordPress recomienda desactivar los plugins antes de crear la red. Guarda la lista de plugins activos para reactivarlos después:
sudo -u www-data wp --path=/var/www/wordpress plugin list --status=active --field=name | tee ~/plugins-activos.txt
sudo -u www-data wp --path=/var/www/wordpress plugin deactivate --all
Convierte la instalación. Para una red de subdominios añade --subdomains; para subdirectorios omítelo:
sudo -u www-data wp --path=/var/www/wordpress core multisite-convert --title="Mi red" --subdomains
Set up multisite database tables.
Added multisite constants to wp-config.php.
Success: Network installed. Don't forget to set up rewrite rules (and a .htaccess file, if using Apache).
El comando crea las tablas de red (wp_blogs, wp_site, wp_sitemeta y otras) y añade las constantes a wp-config.php. Ábrelo para comprobarlo:
sudo nano /var/www/wordpress/wp-config.php
Encima de la línea /* That's all, stop editing! */ debe haber un bloque como este (con SUBDOMAIN_INSTALL a false si elegiste subdirectorios):
define( 'WP_ALLOW_MULTISITE', true );
define( 'MULTISITE', true );
define( 'SUBDOMAIN_INSTALL', true );
$base = '/';
define( 'DOMAIN_CURRENT_SITE', 'example.com' );
define( 'PATH_CURRENT_SITE', '/' );
define( 'SITE_ID_CURRENT_SITE', 1 );
define( 'BLOG_ID_CURRENT_SITE', 1 );
Si wp-config.php no tenía permisos de escritura para www-data, WP-CLI mostrará el bloque en pantalla en lugar de escribirlo: cópialo tú en ese lugar. DOMAIN_CURRENT_SITE debe coincidir exactamente con el dominio que usa el sitio, con o sin www.
Reactiva los plugins en el sitio principal:
xargs -r sudo -u www-data wp --path=/var/www/wordpress plugin activate < ~/plugins-activos.txt
Paso 5: Configurar Nginx
Nginx no lee archivos .htaccess, así que las reglas de reescritura de la red van en el bloque de servidor. Abre el archivo de tu sitio:
sudo nano /etc/nginx/sites-available/wordpress
Red de subdominios
En una red de subdominios basta con que el bloque acepte cualquier subdominio: WordPress decide qué sitio servir según el host. Reemplaza el contenido por:
server {
listen 80;
listen [::]:80;
server_name example.com *.example.com;
root /var/www/wordpress;
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;
}
}
Red de subdirectorios
En una red de subdirectorios, rutas como /tienda/wp-admin/ o /tienda/wp-includes/... no existen en disco y hay que reescribirlas hacia la instalación única. Reemplaza el contenido por:
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/wordpress;
index index.php;
client_max_body_size 64m;
if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$request_uri/ permanent;
rewrite ^(/[^/]+)?(/wp-.*) $2 last;
rewrite ^(/[^/]+)?(/.*\.php) $2 last;
}
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;
}
}
En ambos casos, comprueba la sintaxis y recarga Nginx:
sudo nginx -t
sudo systemctl reload nginx
Accede a http://example.com/wp-admin/network/ con tu usuario administrador. Deberías ver el Escritorio de la red; tu usuario es ahora superadministrador.
Paso 6: Añadir HTTPS
Subdirectorios: certificado normal
Con subdirectorios todos los sitios comparten el mismo dominio, así que basta con un certificado normal obtenido con el plugin de Nginx de Certbot:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com
Subdominios: certificado comodín
Let's Encrypt solo emite certificados comodín (*.example.com) con validación DNS-01: Certbot crea un registro TXT temporal en tu DNS mediante la API del proveedor. Este ejemplo usa Cloudflare; hay plugins equivalentes para otros proveedores (apt search python3-certbot-dns).
Instala Certbot y el plugin de Cloudflare:
sudo apt install -y certbot python3-certbot-dns-cloudflare
Crea en Cloudflare un token de API con permiso Zone > DNS > Edit sobre tu zona y guárdalo en un archivo que solo pueda leer root:
sudo install -d -m 700 /root/.secrets
sudo nano /root/.secrets/cloudflare.ini
dns_cloudflare_api_token = your_cloudflare_api_token
sudo chmod 600 /root/.secrets/cloudflare.ini
Solicita el certificado para el dominio y el comodín:
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com'
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
Como certonly no toca Nginx, edita tú el bloque de servidor. Cambia el bloque de subdominios del paso 5 por estos dos: uno que redirige HTTP a HTTPS y otro que sirve HTTPS:
sudo nano /etc/nginx/sites-available/wordpress
server {
listen 80;
listen [::]:80;
server_name example.com *.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com *.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/wordpress;
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;
}
}
Recarga Nginx y comprueba que la renovación automática funciona. El temporizador de Certbot renueva también los certificados DNS-01, pero Nginx necesita recargarse para usar el certificado nuevo, así que añade un deploy hook:
sudo nginx -t && sudo systemctl reload nginx
printf '#!/bin/sh\nsystemctl reload nginx\n' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
sudo certbot renew --dry-run
Actualizar las URL de la red a HTTPS
Si la red se creó con http://, actualiza las URL guardadas en la base de datos de todos los sitios. Revisa primero los cambios con --dry-run:
sudo -u www-data wp --path=/var/www/wordpress search-replace 'http://example.com' 'https://example.com' --network --skip-columns=guid --dry-run
Si el recuento es razonable, ejecútalo sin --dry-run. En una red de subdominios repite el comando para cada subdominio existente (http://tienda.example.com), o usa una expresión regular con --regex si tienes muchos.
Paso 7: Crear sitios y usuarios
Crea un sitio nuevo. En una red de subdominios, --slug=tienda crea tienda.example.com; en una de subdirectorios, example.com/tienda/:
sudo -u www-data wp --path=/var/www/wordpress site create --slug=tienda --title="Tienda" [email protected]
Success: Site 2 created: https://tienda.example.com/
Lista los sitios de la red:
sudo -u www-data wp --path=/var/www/wordpress site list --fields=blog_id,url
+---------+-----------------------------+
| blog_id | url |
+---------+-----------------------------+
| 1 | https://example.com/ |
| 2 | https://tienda.example.com/ |
+---------+-----------------------------+
Los usuarios son comunes a toda la red, pero los roles son por sitio. Crea un editor solo para la tienda con --url, que indica a WP-CLI sobre qué sitio actuar:
sudo -u www-data wp --path=/var/www/wordpress user create maria [email protected] --role=editor --url=tienda.example.com
Para dar a un usuario existente acceso a otro sitio, o convertirlo en superadministrador de toda la red:
sudo -u www-data wp --path=/var/www/wordpress user set-role maria editor --url=example.com
sudo -u www-data wp --path=/var/www/wordpress super-admin add maria
Advertenciaun superadministrador puede instalar plugins y editar cualquier sitio. Reserva ese rol para quien administra el servidor.
Asignar un dominio propio a un sitio
WordPress permite que un sitio de la red use un dominio distinto sin plugins adicionales:
- Apunta el registro A de
otramarca.coma la IP del servidor. - Añade
otramarca.comalserver_namede Nginx (o crea un bloque aparte) y obtén su certificado consudo certbot --nginx -d otramarca.com. - En Escritorio de la red > Sitios, edita el sitio y cambia su Dirección del sitio (URL) a
https://otramarca.com.
Paso 8: Gestionar plugins y temas en la red
En Multisite solo el superadministrador instala plugins y temas; los administradores de cada sitio solo pueden activar los que la red les permite.
Instala un plugin y actívalo en toda la red (queda activo en todos los sitios y no se puede desactivar desde un sitio individual):
sudo -u www-data wp --path=/var/www/wordpress plugin install two-factor --activate-network
Si prefieres que cada sitio decida, instálalo sin activarlo y actívalo solo donde haga falta:
sudo -u www-data wp --path=/var/www/wordpress plugin install woocommerce
sudo -u www-data wp --path=/var/www/wordpress plugin activate woocommerce --url=tienda.example.com
Los temas se habilitan para la red y luego cada sitio elige el suyo:
sudo -u www-data wp --path=/var/www/wordpress theme enable twentytwentyfive --network
sudo -u www-data wp --path=/var/www/wordpress theme activate twentytwentyfive --url=tienda.example.com
Los límites de subida se guardan como ajustes de red. Por ejemplo, para permitir archivos de hasta 10 MB (el valor va en KB):
sudo -u www-data wp --path=/var/www/wordpress network meta update 1 fileupload_maxk 10240
El límite efectivo también depende de upload_max_filesize y post_max_size de PHP y de client_max_body_size de Nginx.
Paso 9: Ejecutar WP-Cron desde el sistema
WP-Cron se dispara con las visitas y, en una red, cada sitio tiene su propia cola de tareas. Los sitios con poco tráfico pueden acumular tareas atrasadas (publicaciones programadas, correos). Es más fiable desactivarlo y lanzarlo desde cron del sistema para todos los sitios.
Añade esta línea a wp-config.php, encima de /* That's all, stop editing! */:
sudo nano /var/www/wordpress/wp-config.php
define( 'DISABLE_WP_CRON', true );
Crea una tarea de cron que recorra todos los sitios cada cinco minutos:
sudo nano /etc/cron.d/wordpress-multisite
*/5 * * * * www-data /usr/local/bin/wp --path=/var/www/wordpress site list --field=url | xargs -r -I{} /usr/local/bin/wp --path=/var/www/wordpress cron event run --due-now --quiet --url={}
Comprueba que el comando funciona ejecutándolo a mano para un sitio:
sudo -u www-data wp --path=/var/www/wordpress cron event run --due-now --url=tienda.example.com
Success: Executed a total of 3 cron events.
Solución de problemas
- "Error establishing a database connection" tras la conversión: suele ser un
DOMAIN_CURRENT_SITEque no coincide con el dominio de las tablaswp_siteywp_blogs(por ejemplo,www.example.comfrente aexample.com). Corrige la constante para que coincida. - Bucle de redirecciones al entrar en
/wp-adminde un subsitio: en redes de subdirectorios falta el bloqueif (!-e $request_filename)en Nginx. En redes de subdominios, comprueba que el subdominio resuelve y queserver_nameincluye*.example.com. - Imágenes rotas en los sitios nuevos: los archivos de cada sitio se guardan en
wp-content/uploads/sites/<id>/. Comprueba quewww-datapuede escribir enwp-content/uploads. - La opción de subdirectorios aparece desactivada en el asistente web: WordPress la bloquea si el sitio tiene más de un mes, por el conflicto de enlaces descrito arriba. Con WP-CLI la conversión sí es posible, pero revisa después los enlaces permanentes del sitio principal.
Conclusión
Has convertido una instalación de WordPress en una red Multisite, has configurado Nginx para subdominios o subdirectorios, has añadido HTTPS (con certificado comodín si usas subdominios) y sabes crear sitios, asignar usuarios y controlar plugins y temas con WP-CLI. Como siguientes pasos, añade una caché de objetos con Redis compartida por toda la red, programa copias de seguridad de la base de datos y de wp-content/uploads/sites/, y revisa el endurecimiento de seguridad de WordPress, que en una red afecta a todos los sitios a la vez.
