--- title: "Cómo configurar WordPress Multisite con Nginx en Ubuntu" description: "Convierte WordPress en una red Multisite con subdominios o subdirectorios, configura Nginx y HTTPS en Ubuntu 24.04 y gestiona los sitios con WP-CLI." category: "E-commerce y CMS" language: es source: https://cubepath.com/es/docs/e-commerce-y-cms/configuracion-multisitio-de-wordpress updated: 2026-09-25 --- # Cómo configurar WordPress Multisite con Nginx en Ubuntu 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/wordpress` con Nginx, PHP 8.3-FPM y MySQL o MariaDB. En los ejemplos se usa `example.com` como dominio: sustitúyelo por el tuyo. - Acceso al panel DNS de tu dominio. > Nota: WordPress 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: ```bash 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: ```bash ls -lh ~/backups/ ``` ```output -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: ```bash 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`: ```bash 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: ```bash sudo -u www-data wp --path=/var/www/wordpress core version ``` ```output 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: ```text example.com A your_server_ip *.example.com A your_server_ip ``` Cuando se haya propagado, cualquier subdominio debe resolver a tu servidor: ```bash dig +short cualquiercosa.example.com ``` ```output 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: ```bash 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: ```bash sudo -u www-data wp --path=/var/www/wordpress core multisite-convert --title="Mi red" --subdomains ``` ```output 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: ```bash 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): ```php 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: ```bash 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: ```bash 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: ```nginx 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: ```nginx 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: ```bash 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: ```bash 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: ```bash 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: ```bash sudo install -d -m 700 /root/.secrets sudo nano /root/.secrets/cloudflare.ini ``` ```ini dns_cloudflare_api_token = your_cloudflare_api_token ``` ```bash sudo chmod 600 /root/.secrets/cloudflare.ini ``` Solicita el certificado para el dominio y el comodín: ```bash sudo certbot certonly --dns-cloudflare \ --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \ -d example.com -d '*.example.com' ``` ```output 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: ```bash sudo nano /etc/nginx/sites-available/wordpress ``` ```nginx 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*: ```bash 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`: ```bash 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/`: ```bash sudo -u www-data wp --path=/var/www/wordpress site create --slug=tienda --title="Tienda" --email=admin@example.com ``` ```output Success: Site 2 created: https://tienda.example.com/ ``` Lista los sitios de la red: ```bash sudo -u www-data wp --path=/var/www/wordpress site list --fields=blog_id,url ``` ```output +---------+-----------------------------+ | 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: ```bash sudo -u www-data wp --path=/var/www/wordpress user create maria maria@example.com --role=editor --url=tienda.example.com ``` Para dar a un usuario existente acceso a otro sitio, o convertirlo en superadministrador de toda la red: ```bash 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 ``` > Advertencia: un 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: 1. Apunta el registro A de `otramarca.com` a la IP del servidor. 2. Añade `otramarca.com` al `server_name` de Nginx (o crea un bloque aparte) y obtén su certificado con `sudo certbot --nginx -d otramarca.com`. 3. 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): ```bash 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: ```bash 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: ```bash 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): ```bash 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! */`: ```bash sudo nano /var/www/wordpress/wp-config.php ``` ```php define( 'DISABLE_WP_CRON', true ); ``` Crea una tarea de cron que recorra todos los sitios cada cinco minutos: ```bash sudo nano /etc/cron.d/wordpress-multisite ``` ```text */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: ```bash sudo -u www-data wp --path=/var/www/wordpress cron event run --due-now --url=tienda.example.com ``` ```output 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_SITE` que no coincide con el dominio de las tablas `wp_site` y `wp_blogs` (por ejemplo, `www.example.com` frente a `example.com`). Corrige la constante para que coincida. - **Bucle de redirecciones al entrar en `/wp-admin` de un subsitio**: en redes de subdirectorios falta el bloque `if (!-e $request_filename)` en Nginx. En redes de subdominios, comprueba que el subdominio resuelve y que `server_name` incluye `*.example.com`. - **Imágenes rotas en los sitios nuevos**: los archivos de cada sitio se guardan en `wp-content/uploads/sites//`. Comprueba que `www-data` puede escribir en `wp-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.