Configuración de Server Blocks en Nginx: Guía Completa
Introducción
Los server blocks en Nginx son el equivalente a los virtual hosts de Apache, permitiendo que una sola instalación de Nginx aloje múltiples sitios web, aplicaciones y servicios en un servidor físico. Esta poderosa característica te permite servir diferente contenido basado en el nombre de dominio solicitado por el cliente, haciendo posible ejecutar sitios web ilimitados en una sola dirección IP de manera eficiente.
A diferencia del sistema de virtual hosts de Apache, Nginx utiliza server blocks con una sintaxis de configuración más optimizada. La arquitectura orientada a eventos de Nginx combinada con server blocks bien configurados puede manejar miles de conexiones concurrentes mientras sirve múltiples sitios web simultáneamente con una sobrecarga mínima de recursos.
Esta guía integral cubre todo lo que necesitas saber sobre configurar server blocks en Nginx. Aprenderás cómo configurar server blocks basados en nombre e IP, configurar SSL/TLS para HTTPS, implementar reglas de enrutamiento avanzadas, optimizar rendimiento, asegurar tus configuraciones y solucionar problemas comunes. Ya sea que estés alojando un blog simple o gestionando una infraestructura multi-sitio compleja, dominar los server blocks es esencial para una administración efectiva de Nginx.
Prerrequisitos
Antes de configurar server blocks, asegúrate de tener:
- Nginx instalado y ejecutándose en Ubuntu/Debian o CentOS/Rocky Linux
- Acceso root o sudo a tu servidor
- Comprensión básica de la sintaxis de configuración de Nginx
- Nombres de dominio con DNS configurado para apuntar a la IP de tu servidor
- Familiaridad con permisos de archivos Linux y estructura de directorios
- Conocimiento de editor de texto (nano, vim u otro)
- Comprensión de conceptos básicos de redes y HTTP
- Certificados SSL/TLS (si configuras server blocks HTTPS)
Entendiendo Server Blocks
Server Blocks Basados en Nombre
Los server blocks basados en nombre permiten múltiples dominios en una sola dirección IP:
Flujo de Petición del Cliente:
1. Cliente solicita http://example.com/page.html
2. Navegador envía petición HTTP con cabecera "Host: example.com"
3. Nginx recibe petición en dirección IP 192.168.1.100:80
4. Nginx compara cabecera Host contra directivas server_name configuradas
5. Nginx sirve contenido del server block coincidente
6. Si no encuentra coincidencia, sirve desde server block por defecto
Ejemplo básico:
# Ambos server blocks comparten la misma IP
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
}
server {
listen 80;
server_name another.com www.another.com;
root /var/www/another.com;
}
Server Blocks Basados en IP
Los server blocks basados en IP asignan a cada sitio una dirección IP única:
# Cada server block tiene una IP diferente
server {
listen 192.168.1.100:80;
server_name example.com;
root /var/www/example.com;
}
server {
listen 192.168.1.101:80;
server_name another.com;
root /var/www/another.com;
}
Server Block Por Defecto
El server block por defecto maneja peticiones que no coinciden con ningún server_name configurado:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444; # Cerrar conexión sin respuesta
}
Estructura de Directorios de Server Blocks
Ubuntu y Debian
Nginx en Ubuntu/Debian usa estructura sites-available/sites-enabled:
/etc/nginx/
├── nginx.conf # Configuración principal
├── sites-available/ # Todas las configs de server blocks
│ ├── default # Server block por defecto
│ ├── example.com # Server block personalizado
│ └── another.com # Otro server block
├── sites-enabled/ # Server blocks habilitados (symlinks)
│ ├── default -> ../sites-available/default
│ └── example.com -> ../sites-available/example.com
└── snippets/ # Snippets de configuración reutilizables
Flujo de trabajo:
- Crear configuración en
sites-available/ - Habilitar con symlink a
sites-enabled/ - Probar y recargar Nginx
CentOS, Rocky Linux y AlmaLinux
Los sistemas basados en Red Hat usan un enfoque más simple:
/etc/nginx/
├── nginx.conf # Configuración principal
└── conf.d/ # Todos los archivos *.conf se cargan
├── default.conf
├── example.com.conf
└── another.com.conf
Flujo de trabajo:
- Crear archivo .conf en
conf.d/ - Probar y recargar Nginx
Creando Tu Primer Server Block
Paso 1: Crear Directorio Document Root
Crear la estructura de directorios para tu sitio web:
# Ubuntu/Debian
sudo mkdir -p /var/www/example.com/html
sudo mkdir -p /var/www/example.com/logs
# CentOS/Rocky/AlmaLinux
sudo mkdir -p /usr/share/nginx/example.com/html
sudo mkdir -p /var/log/nginx/example.com
Paso 2: Establecer Permisos Apropiados
Configurar propiedad y permisos:
# Ubuntu/Debian
sudo chown -R www-data:www-data /var/www/example.com
sudo chmod -R 755 /var/www/example.com
# CentOS/Rocky/AlmaLinux
sudo chown -R nginx:nginx /usr/share/nginx/example.com
sudo chmod -R 755 /usr/share/nginx/example.com
En sistemas con SELinux habilitado (CentOS/Rocky/AlmaLinux):
# Establecer contexto SELinux correcto
sudo chcon -R -t httpd_sys_content_t /usr/share/nginx/example.com/html
# Hacerlo permanente
sudo semanage fcontext -a -t httpd_sys_content_t "/usr/share/nginx/example.com/html(/.*)?"
sudo restorecon -Rv /usr/share/nginx/example.com
Paso 3: Crear Contenido de Prueba
Crear un archivo index.html simple:
# Ubuntu/Debian
sudo nano /var/www/example.com/html/index.html
# CentOS/Rocky/AlmaLinux
sudo nano /usr/share/nginx/example.com/html/index.html
Agregar el siguiente contenido:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to Example.com</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
padding: 60px 40px;
border-radius: 12px;
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
max-width: 600px;
text-align: center;
}
h1 {
color: #009639;
font-size: 2.5em;
margin-bottom: 20px;
}
.info {
background: #f0f8ff;
padding: 20px;
border-left: 4px solid #009639;
margin: 30px 0;
text-align: left;
}
.info strong {
color: #009639;
}
p {
color: #666;
line-height: 1.6;
margin: 15px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>Welcome to Example.com</h1>
<p>Your Nginx server block is configured correctly!</p>
<div class="info">
<strong>Server Information:</strong><br>
Server Block: example.com<br>
Document Root: /var/www/example.com/html<br>
Status: Active and Running<br>
Powered by: Nginx
</div>
<p>You can now upload your website content to this directory.</p>
</div>
</body>
</html>
Paso 4: Crear Configuración de Server Block
Configuración Ubuntu/Debian
Crear el archivo de configuración del server block:
sudo nano /etc/nginx/sites-available/example.com
Agregar la configuración básica:
server {
# Escuchar en IPv4 e IPv6
listen 80;
listen [::]:80;
# Nombre del servidor
server_name example.com www.example.com;
# Document root
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
# Logging
access_log /var/www/example.com/logs/access.log;
error_log /var/www/example.com/logs/error.log;
# Bloque location principal
location / {
try_files $uri $uri/ =404;
}
# Denegar acceso a archivos ocultos
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
Habilitar el server block:
# Crear symlink
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# Probar configuración
sudo nginx -t
# Recargar Nginx
sudo systemctl reload nginx
Configuración CentOS/Rocky/AlmaLinux
Crear el archivo de configuración:
sudo nano /etc/nginx/conf.d/example.com.conf
Agregar la configuración:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /usr/share/nginx/example.com/html;
index index.html index.htm;
access_log /var/log/nginx/example.com/access.log;
error_log /var/log/nginx/example.com/error.log;
location / {
try_files $uri $uri/ =404;
}
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
Probar y recargar:
# Probar configuración
sudo nginx -t
# Recargar Nginx
sudo systemctl reload nginx
Configuración Avanzada de Server Blocks
Múltiples Nombres de Dominio
Alojar múltiples dominios apuntando al mismo contenido:
server {
listen 80;
listen [::]:80;
# Múltiples nombres de servidor
server_name example.com www.example.com example.net www.example.net example.org;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
# Registrar qué dominio fue accedido
access_log /var/log/nginx/example-access.log combined;
}
Nombres de Servidor con Comodín
Coincidir todos los subdominios:
server {
listen 80;
server_name *.example.com .example.com;
root /var/www/example.com/html;
# Registrar subdominio en logs de acceso
log_format subdomains '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/subdomains-access.log subdomains;
location / {
try_files $uri $uri/ =404;
}
}
Server Blocks de Subdominios
Crear server blocks separados para diferentes subdominios:
# Dominio principal
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# Subdominio de blog
server {
listen 80;
server_name blog.example.com;
root /var/www/example.com/blog;
index index.html index.php;
access_log /var/log/nginx/blog.example-access.log;
error_log /var/log/nginx/blog.example-error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# Subdominio de API
server {
listen 80;
server_name api.example.com;
root /var/www/example.com/api;
access_log /var/log/nginx/api.example-access.log;
error_log /var/log/nginx/api.example-error.log;
# Cabeceras CORS para API
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
location / {
try_files $uri $uri/ =404;
}
}
Enrutamiento Dinámico de Subdominios
Enrutar subdominios dinámicamente basados en estructura de directorios:
server {
listen 80;
server_name ~^(?<subdomain>.+)\.example\.com$;
root /var/www/subdomains/$subdomain;
index index.html;
# Si el directorio no existe, mostrar error
if (!-d /var/www/subdomains/$subdomain) {
return 404;
}
location / {
try_files $uri $uri/ =404;
}
}
Redirección de URL
Redirigir www a no-www (o viceversa):
# Redirigir www a no-www
server {
listen 80;
listen [::]:80;
server_name www.example.com;
return 301 http://example.com$request_uri;
}
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Alternativa usando declaración if (menos preferido):
server {
listen 80;
server_name example.com www.example.com;
# Redirigir www a no-www
if ($host = www.example.com) {
return 301 http://example.com$request_uri;
}
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Páginas de Error Personalizadas
Configurar páginas de error personalizadas por server block:
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
index index.html;
# Páginas de error personalizadas
error_page 400 /errors/400.html;
error_page 401 /errors/401.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 500 502 503 504 /errors/50x.html;
location / {
try_files $uri $uri/ =404;
}
# Ubicación para páginas de error
location ^~ /errors/ {
internal;
root /var/www/example.com/html;
}
}
Crear páginas de error personalizadas:
sudo mkdir -p /var/www/example.com/html/errors
sudo nano /var/www/example.com/html/errors/404.html
Ejemplo de página 404:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Page Not Found</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
margin: 0;
padding: 20px;
}
.error-container {
text-align: center;
color: white;
}
h1 {
font-size: 120px;
margin: 0;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
h2 {
font-size: 36px;
margin: 20px 0;
}
p {
font-size: 18px;
margin: 20px 0;
}
a {
display: inline-block;
padding: 15px 30px;
background: white;
color: #667eea;
text-decoration: none;
border-radius: 30px;
font-weight: bold;
margin-top: 20px;
transition: transform 0.3s;
}
a:hover {
transform: scale(1.05);
}
</style>
</head>
<body>
<div class="error-container">
<h1>404</h1>
<h2>Page Not Found</h2>
<p>The page you're looking for doesn't exist or has been moved.</p>
<a href="/">Return to Homepage</a>
</div>
</body>
</html>
Server Blocks SSL/TLS
Configurar server blocks HTTPS:
Server Block HTTPS Básico
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
# Certificados SSL
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# Protocolos y cifrados SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Caché de sesión SSL
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Cabecera HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/example-ssl-access.log;
error_log /var/log/nginx/example-ssl-error.log;
}
# Redirección HTTP a HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Configuración Let's Encrypt
Después de obtener certificados Let's Encrypt:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
# Certificados Let's Encrypt
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Configuración SSL fuerte
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Configuración de sesión SSL
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Cabeceras de seguridad
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
location / {
try_files $uri $uri/ =404;
}
# Desafío ACME de Let's Encrypt
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/example.com/html;
}
}
# Redirección HTTP a HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# Permitir desafíos Let's Encrypt
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/example.com/html;
}
# Redirigir todo lo demás a HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
Snippet de Configuración SSL
Crear configuración SSL reutilizable:
sudo nano /etc/nginx/snippets/ssl-params.conf
Agregar:
# Protocolos SSL
ssl_protocols TLSv1.2 TLSv1.3;
# Cifrados SSL
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# Sesión SSL
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Cabeceras de seguridad
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
Usar en server block:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# Incluir parámetros SSL
include snippets/ssl-params.conf;
root /var/www/example.com/html;
location / {
try_files $uri $uri/ =404;
}
}
Optimización de Rendimiento
Habilitar Compresión
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
# Compresión Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
gzip_disable "msie6";
location / {
try_files $uri $uri/ =404;
}
}
Caché de Navegador
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
# Cachear archivos estáticos
location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
expires 365d;
add_header Cache-Control "public, no-transform, immutable";
access_log off;
}
location ~* \.(css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
location ~* \.(woff|woff2|ttf|eot)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
location / {
try_files $uri $uri/ =404;
}
}
Caché FastCGI para PHP
# Definir zona de caché FastCGI
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2
keys_zone=PHPCACHE:100m
inactive=60m
max_size=1g;
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
index index.php index.html;
# Omitir caché para ciertas condiciones
set $skip_cache 0;
# Peticiones POST y URLs con query strings
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
# No cachear páginas de admin
if ($request_uri ~* "/wp-admin/|/admin/") {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Caché FastCGI
fastcgi_cache PHPCACHE;
fastcgi_cache_valid 200 60m;
fastcgi_cache_valid 404 10m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# Agregar cabecera de estado de caché
add_header X-Cache-Status $upstream_cache_status;
}
location / {
try_files $uri $uri/ /index.php?$args;
}
}
Configuración de Seguridad
Limitación de Tasa
# Definir zona de límite de tasa
limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=10r/s;
limit_req_status 429;
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
location / {
# Aplicar límite de tasa
limit_req zone=limitbyaddr burst=20 nodelay;
try_files $uri $uri/ =404;
}
# Límite diferente para API
location /api/ {
limit_req zone=limitbyaddr burst=10 nodelay;
try_files $uri $uri/ =404;
}
}
Limitación de Conexiones
# Definir zona de límite de conexiones
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
# Limitar conexiones concurrentes
limit_conn connlimit 10;
location /download/ {
# Más restrictivo para descargas
limit_conn connlimit 2;
limit_rate 500k; # Límite de ancho de banda por conexión
}
location / {
try_files $uri $uri/ =404;
}
}
Control de Acceso Basado en IP
server {
listen 80;
server_name admin.example.com;
root /var/www/example.com/admin;
# Permitir solo IPs específicas
allow 192.168.1.0/24;
allow 10.0.0.100;
allow 203.0.113.50;
deny all;
location / {
try_files $uri $uri/ =404;
}
}
Autenticación Básica
server {
listen 80;
server_name secure.example.com;
root /var/www/example.com/secure;
# Autenticación básica
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
try_files $uri $uri/ =404;
}
# Deshabilitar auth para ubicación específica
location /public/ {
auth_basic off;
}
}
Crear archivo de contraseñas:
# Instalar utilidad htpasswd
sudo apt install apache2-utils # Ubuntu/Debian
sudo yum install httpd-tools # CentOS/Rocky
# Crear archivo de contraseñas
sudo htpasswd -c /etc/nginx/.htpasswd username
Cabeceras de Seguridad
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
# Cabeceras de seguridad
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always;
# Eliminar firma del servidor
server_tokens off;
location / {
try_files $uri $uri/ =404;
}
}
Server Block de Reverse Proxy
Configurar Nginx como reverse proxy:
upstream backend {
least_conn;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 80;
server_name app.example.com;
access_log /var/log/nginx/app-access.log;
error_log /var/log/nginx/app-error.log;
location / {
proxy_pass http://backend;
# Cabeceras de proxy
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}
# Archivos estáticos servidos por Nginx
location /static/ {
alias /var/www/example.com/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
}
Configuración de Logging
Formatos de Log Personalizados
# Definir formatos de log personalizados
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
log_format json escape=json '{'
'"time": "$time_local",'
'"remote_addr": "$remote_addr",'
'"request": "$request",'
'"status": $status,'
'"body_bytes_sent": $body_bytes_sent,'
'"http_referer": "$http_referer",'
'"http_user_agent": "$http_user_agent"'
'}';
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
# Usar formato de log personalizado
access_log /var/log/nginx/example-access.log detailed;
error_log /var/log/nginx/example-error.log warn;
location / {
try_files $uri $uri/ =404;
}
}
Logging Condicional
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
# Map para determinar si se debe registrar
map $request_uri $loggable {
~*\.(gif|jpg|jpeg|png|css|js|ico|svg)$ 0;
default 1;
}
# No registrar health checks
map $http_user_agent $log_ua {
~*pingdom|uptime 0;
default 1;
}
# Combinar condiciones
set $log 0;
if ($loggable) {
set $log 1;
}
if ($log_ua = 0) {
set $log 0;
}
access_log /var/log/nginx/example-access.log combined if=$log;
location / {
try_files $uri $uri/ =404;
}
}
Solución de Problemas
Probar Configuración
Siempre probar configuración antes de recargar:
sudo nginx -t
Salida esperada:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Verificar Configuración de Server Block
# Ver todos los server blocks y sus configuraciones
sudo nginx -T
# Verificar coincidencias específicas de server_name
sudo nginx -T | grep -A 10 "server_name example.com"
Problemas Comunes
Problema: "conflicting server name"
# Verificar directivas server_name duplicadas
sudo nginx -T | grep "server_name" | sort | uniq -d
# Solución: Asegurar server_name único o usar default_server
Problema: Server block incorrecto servido
# Verificar orden de server blocks y default_server
sudo nginx -T | grep -A 5 "listen.*default_server"
# Probar con curl
curl -H "Host: example.com" http://your_ip/
Problema: Errores de permiso denegado
# Verificar permisos de archivos
ls -la /var/www/example.com/
# Corregir permisos
sudo chown -R www-data:www-data /var/www/example.com # Ubuntu/Debian
sudo chown -R nginx:nginx /usr/share/nginx/example.com # CentOS/Rocky
# Verificar SELinux (CentOS/Rocky/AlmaLinux)
sudo getenforce
sudo chcon -R -t httpd_sys_content_t /usr/share/nginx/example.com/html
Problema: Errores de certificado SSL
# Verificar que existen archivos de certificado
sudo ls -la /etc/letsencrypt/live/example.com/
# Probar configuración SSL
sudo nginx -t
# Verificar validez del certificado
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout
Mejores Prácticas
Configuración Organizada
Mantener archivos de server blocks organizados:
# Convención de nombres Ubuntu/Debian
/etc/nginx/sites-available/
├── default # Catch-all por defecto
├── example.com # Dominio principal
├── blog.example.com # Subdominio
└── api.example.com # Subdominio API
Usar Include para Configuraciones Comunes
# /etc/nginx/snippets/common-locations.conf
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location = /robots.txt {
access_log off;
log_not_found off;
}
# Usar en server block
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
include snippets/common-locations.conf;
location / {
try_files $uri $uri/ =404;
}
}
Documentación
Documentar cada server block:
#
# Server Block: example.com
# Created: 2024-01-15
# Modified: 2024-01-20
# Purpose: Main company website
# Contact: [email protected]
#
server {
listen 80;
server_name example.com www.example.com;
# ...
}
Respaldos Regulares
Respaldar configuraciones de server blocks:
# Ubuntu/Debian
sudo tar -czf nginx-sites-backup-$(date +%F).tar.gz /etc/nginx/sites-available/
# CentOS/Rocky/AlmaLinux
sudo tar -czf nginx-conf-backup-$(date +%F).tar.gz /etc/nginx/conf.d/
Monitoreo
Monitorear acceso y errores de server blocks:
# Log de acceso en tiempo real
sudo tail -f /var/log/nginx/example-access.log
# Log de errores en tiempo real
sudo tail -f /var/log/nginx/example-error.log
# Contar peticiones por código de estado
sudo awk '{print $9}' /var/log/nginx/example-access.log | sort | uniq -c | sort -nr
Conclusión
Los server blocks son la base del alojamiento multi-sitio de Nginx, permitiendo gestión eficiente de múltiples sitios web en un solo servidor. Esta guía ha cubierto todo desde server blocks básicos basados en nombre hasta configuraciones SSL/TLS avanzadas, hardening de seguridad, optimización de rendimiento y solución de problemas.
Conclusiones clave:
- Los server blocks basados en nombre permiten sitios web ilimitados en una dirección IP con sobrecarga mínima de recursos
- La estructura de directorios y permisos apropiados son críticos para seguridad y funcionalidad
- Los server blocks SSL/TLS con HTTP/2 proporcionan alojamiento web moderno y seguro
- La optimización de rendimiento a través de caché y compresión mejora la experiencia del usuario
- Las características de seguridad como limitación de tasa, control de acceso y cabeceras de seguridad protegen tus sitios
- Las pruebas regulares, monitoreo y respaldos aseguran operación confiable
Domina la configuración de server blocks para alojar eficientemente múltiples sitios web, implementar patrones de enrutamiento avanzados y construir infraestructuras web escalables. Continúa explorando temas avanzados como server blocks dinámicos con Lua, integración con balanceo de carga, estrategias avanzadas de caché y gestión automatizada de certificados SSL con Certbot.


