--- title: "Cómo configurar server blocks en Nginx en Ubuntu 24.04" description: "Aloja varios dominios en un servidor con server blocks de Nginx en Ubuntu 24.04: sitio por defecto, redirección www, PHP-FPM, proxy inverso y HTTPS con Certbot." category: "Servidores Web" language: es source: https://cubepath.com/es/docs/servidores-web/configuracion-de-server-blocks-en-nginx updated: 2026-09-25 --- # Cómo configurar server blocks en Nginx en Ubuntu 24.04 Los server blocks son el equivalente en Nginx a los virtual hosts de Apache: permiten que un único servidor sirva varios dominios, cada uno con su configuración, su directorio y sus logs. En este tutorial configurarás en Ubuntu 24.04 un server block por defecto que rechaza nombres desconocidos, dos sitios con su propio dominio, una redirección de `www`, PHP-FPM en uno de ellos, un proxy inverso hacia una aplicación y HTTPS para todos. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS y Nginx instalado desde los repositorios de Ubuntu, con el perfil `Nginx Full` permitido en UFW. Si aún no lo tienes, sigue primero la guía de instalación de Nginx en Ubuntu 24.04. - Un usuario no root con privilegios `sudo`. - Dos dominios con registros DNS `A` que apunten a la IP pública del servidor, para el dominio raíz y para `www`. En esta guía se usan `site1.your_domain` y `site2.your_domain`: sustitúyelos por los tuyos. ## Cómo elige Nginx el server block Para cada petición, Nginx primero filtra los server blocks por la dirección y el puerto de `listen` y, entre ellos, compara la cabecera `Host` con `server_name` en este orden: 1. Nombre exacto, como `site1.your_domain`. 2. Comodín al principio más largo, como `*.site1.your_domain`. 3. Comodín al final más largo, como `site1.*`. 4. Primera expresión regular que coincida, en el orden en que aparecen en la configuración (por ejemplo `~^(?.+)\.your_domain$`). Si nada coincide, responde el server block marcado como `default_server` en ese puerto, o el primero que cargó si no hay ninguno marcado. Por eso conviene definir uno explícito, como harás en el paso 1. ## Paso 1: Crear un server block por defecto Si alguien accede por la IP o con un dominio que no has configurado, es mejor cerrar la conexión que mostrar uno de tus sitios. Ubuntu trae el sitio `default`, que muestra la página de bienvenida. Desactívalo: ```bash sudo rm /etc/nginx/sites-enabled/default ``` Crea en su lugar un server block que responda con el código especial `444`, con el que Nginx cierra la conexión sin enviar respuesta: ```bash sudo nano /etc/nginx/sites-available/000-catchall ``` ```nginx server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 444; } ``` `server_name _;` es solo un nombre que nunca coincide con un dominio real; lo que convierte a este bloque en el predeterminado es `default_server`. Actívalo y recarga: ```bash sudo ln -s /etc/nginx/sites-available/000-catchall /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` Comprueba que las peticiones por IP se cierran: ```bash curl -I http://127.0.0.1 ``` ```output curl: (52) Empty reply from server ``` ## Paso 2: Crear los directorios de los sitios ```bash sudo mkdir -p /var/www/site1.your_domain/html /var/www/site2.your_domain/html sudo chown -R $USER:$USER /var/www/site1.your_domain /var/www/site2.your_domain echo '

Sitio 1 funciona

' > /var/www/site1.your_domain/html/index.html echo '

Sitio 2 funciona

' > /var/www/site2.your_domain/html/index.html ``` Nginx trabaja como `www-data` y solo necesita leer: los permisos por defecto (755 en directorios, 644 en archivos) son suficientes. Si una aplicación necesita escribir en un directorio concreto, da permisos a `www-data` solo en ese directorio, nunca `chmod 777`. ## Paso 3: Crear el server block del primer sitio Crea el archivo en `sites-available`: ```bash sudo nano /etc/nginx/sites-available/site1.your_domain ``` ```nginx server { listen 80; listen [::]:80; server_name site1.your_domain www.site1.your_domain; root /var/www/site1.your_domain/html; index index.html; access_log /var/log/nginx/site1.your_domain.access.log; error_log /var/log/nginx/site1.your_domain.error.log; location / { try_files $uri $uri/ =404; } location ~ /\.(?!well-known) { deny all; } } ``` - `server_name` admite varios nombres separados por espacios. - `root` es el directorio publicado. - `try_files` sirve el archivo o directorio pedido o devuelve 404. - La `location ~ /\.` bloquea archivos ocultos (`.git`, `.env`) pero deja pasar `/.well-known/`, que usa Let's Encrypt. ## Paso 4: Crear el server block del segundo sitio Copia el archivo y cambia el dominio: ```bash sudo cp /etc/nginx/sites-available/site1.your_domain /etc/nginx/sites-available/site2.your_domain sudo sed -i 's/site1\.your_domain/site2.your_domain/g' /etc/nginx/sites-available/site2.your_domain grep -E 'server_name|root' /etc/nginx/sites-available/site2.your_domain ``` ```output server_name site2.your_domain www.site2.your_domain; root /var/www/site2.your_domain/html; ``` ## Paso 5: Activar los sitios y comprobarlos Nginx en Ubuntu carga todo lo que hay en `sites-enabled/`. Activa los dos sitios con enlaces simbólicos: ```bash sudo ln -s /etc/nginx/sites-available/site1.your_domain /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/site2.your_domain /etc/nginx/sites-enabled/ ``` Con varios nombres largos puedes encontrarte el error `could not build server_names_hash, you should increase server_names_hash_bucket_size`. Para evitarlo, abre `/etc/nginx/nginx.conf` y descomenta esta línea del bloque `http`: ```nginx server_names_hash_bucket_size 64; ``` Comprueba la sintaxis y recarga: ```bash sudo nginx -t sudo systemctl reload nginx ``` ```output nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` Prueba cada dominio sin esperar al DNS gracias a `--resolve`: ```bash curl --resolve site1.your_domain:80:127.0.0.1 http://site1.your_domain curl --resolve site2.your_domain:80:127.0.0.1 http://site2.your_domain ``` ```output

Sitio 1 funciona

Sitio 2 funciona

``` Para ver qué `server_name` ha cargado Nginx en total, revisa la configuración efectiva: ```bash sudo nginx -T 2>/dev/null | grep -E '^\s*server_name' ``` ```output server_name _; server_name site1.your_domain www.site1.your_domain; server_name site2.your_domain www.site2.your_domain; ``` ## Paso 6: Ejecutar PHP en un sitio con PHP-FPM Nginx no ejecuta PHP: pasa las peticiones `.php` a PHP-FPM por un socket Unix. Instálalo: ```bash sudo apt install php8.3-fpm ``` Edita el server block del sitio 2: ```bash sudo nano /etc/nginx/sites-available/site2.your_domain ``` Cambia la línea `index` y añade una `location` para PHP dentro del bloque `server`: ```nginx index index.php index.html; location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } ``` El fragmento `snippets/fastcgi-php.conf` que incluye Ubuntu define `SCRIPT_FILENAME` y comprueba que el archivo existe antes de pasarlo a PHP, lo que evita ejecutar código a través de rutas manipuladas. Recarga y prueba: ```bash sudo nginx -t sudo systemctl reload nginx echo ' /var/www/site2.your_domain/html/info.php curl --resolve site2.your_domain:80:127.0.0.1 http://site2.your_domain/info.php ``` ```output PHP 8.3.6 en site2 ``` Borra el archivo de prueba: ```bash rm /var/www/site2.your_domain/html/info.php ``` Para una aplicación con controlador frontal (WordPress, Laravel), cambia `try_files $uri $uri/ =404;` por `try_files $uri $uri/ /index.php?$args;` en la `location /`. ## Paso 7: Publicar una aplicación con un proxy inverso (opcional) Si tienes una aplicación escuchando en un puerto local (Node.js, Python, un contenedor), un server block puede publicarla en su propio dominio. Por ejemplo, para `app.your_domain` con la aplicación en el puerto 3000: ```bash sudo nano /etc/nginx/sites-available/app.your_domain ``` ```nginx server { listen 80; listen [::]:80; server_name app.your_domain; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } ``` Las cabeceras `Upgrade` y `Connection` permiten WebSockets. Actívalo como los demás: ```bash sudo ln -s /etc/nginx/sites-available/app.your_domain /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx ``` Si la aplicación no está arrancada, Nginx devolverá `502 Bad Gateway`. ## Paso 8: Activar HTTPS Instala Certbot con el plugin de Nginx: ```bash sudo apt install certbot python3-certbot-nginx ``` Solicita un certificado por sitio. Certbot encuentra el server block por `server_name`, añade `listen 443 ssl`, las rutas del certificado y un bloque que redirige HTTP a HTTPS: ```bash sudo certbot --nginx -d site1.your_domain -d www.site1.your_domain sudo certbot --nginx -d site2.your_domain -d www.site2.your_domain ``` Comprueba ambos sitios y la renovación automática: ```bash curl -I https://site1.your_domain sudo certbot renew --dry-run ``` ```output HTTP/1.1 200 OK Server: nginx/1.24.0 (Ubuntu) ``` ## Paso 9: Redirigir www al dominio principal Ahora cada sitio responde igual con y sin `www`. Para unificar las URL, separa `www` en su propio server block que solo redirige. Edita el archivo del sitio 1: ```bash sudo nano /etc/nginx/sites-available/site1.your_domain ``` En el bloque que contiene `listen 443 ssl` (el que ha modificado Certbot), deja solo el dominio principal: ```nginx server_name site1.your_domain; ``` Añade al final del archivo un bloque para `www` en HTTPS que reutiliza el mismo certificado, ya que Certbot lo emitió para ambos nombres: ```nginx server { listen 443 ssl; listen [::]:443 ssl; server_name www.site1.your_domain; ssl_certificate /etc/letsencrypt/live/site1.your_domain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/site1.your_domain/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; return 301 https://site1.your_domain$request_uri; } ``` El bloque del puerto 80 que añadió Certbot ya redirige ambos nombres a HTTPS, así que no hay que tocarlo. Comprueba y recarga: ```bash sudo nginx -t sudo systemctl reload nginx curl -I https://www.site1.your_domain/contacto ``` ```output HTTP/1.1 301 Moved Permanently Location: https://site1.your_domain/contacto ``` Repite el cambio para el sitio 2. `$request_uri` conserva la ruta y los parámetros de la URL original. ## Solución de problemas **Un dominio muestra otro sitio o la conexión se cierra**: el nombre no coincide con ningún `server_name` y ha respondido el bloque por defecto. Revisa la salida de `sudo nginx -T | grep server_name` y comprueba que el dominio aparece exactamente igual y que el enlace existe en `sites-enabled/`. **`conflicting server name "site1.your_domain" on 0.0.0.0:80, ignored`**: el mismo nombre está en dos server blocks del mismo puerto. Suele pasar al dejar una copia del archivo en `sites-enabled/`. Localízalo con `grep -r "server_name" /etc/nginx/sites-enabled/`. **`a duplicate default server for 0.0.0.0:80`**: hay dos bloques con `default_server` en el mismo puerto, normalmente porque sigue activo el sitio `default` de Ubuntu. Elimina uno de los dos enlaces. **El navegador descarga el archivo PHP**: la `location ~ \.php$` no está en el server block que responde (recuerda revisar también el bloque del puerto 443) o `php8.3-fpm` no está activo. **502 Bad Gateway**: Nginx no puede hablar con PHP-FPM o con la aplicación del proxy. Comprueba el servicio (`systemctl status php8.3-fpm`) o el puerto (`sudo ss -tlnp | grep 3000`); el log de errores del sitio indica el socket o la dirección exacta que falló. ## Conclusión Has configurado en Nginx sobre Ubuntu 24.04 un server block por defecto que rechaza nombres desconocidos, dos sitios con su propio directorio y logs, PHP-FPM, un proxy inverso, HTTPS con renovación automática y la redirección de `www`. Como siguientes pasos puedes: - Mover a un fragmento de `/etc/nginx/snippets/` las `location` que repites en todos los sitios e incluirlo con `include`. - Crear un pool de PHP-FPM por sitio para aislar aplicaciones de distintos clientes. - Añadir limitación de peticiones con `limit_req` en las rutas de login o de API.