Nginx con múltiples sitios + ssl

Gestiona múltiples sitios con Nginx y Docker

El servidor web Nginx es potente y versátil. Una de sus características más destacables es su capacidad para manejar múltiples dominios y subdominios desde una única instancia. Pero, ¿cómo organizamos de manera efectiva todas estas configuraciones? Aquí es donde entra en juego el sistema de archivos de configuración divididos.

¿Por qué dividir las configuraciones?

Algunos de los beneficios de adoptar esta estrategia son:

  • Organización: Separa las configuraciones por dominio o función, facilitando la búsqueda y edición de configuraciones específicas.
  • Mantenibilidad: Las actualizaciones o cambios en un dominio en particular no afectan ni interrumpen a los demás.
  • Evita duplicaciones: Al mantener todo separado, evitas la posibilidad de tener configuraciones repetidas o contradictorias.

Configuración básica con Docker y Nginx

Si estás utilizando Docker para tus servicios, esta estructura y estrategia encaja perfectamente. En este post, detallaremos cómo configurar Nginx con Docker para administrar múltiples sitios web.

Estructura de archivos de Nginx:

Dado que estamos utilizando Docker, asumamos que ya tienes una estructura de directorios relacionada con tu configuración de Docker. Dentro de esta estructura, nuestra configuración de Nginx podría verse así:
infrastructure/

├── config_nginx/
│ ├── nginx.conf
│ │
│ └── sites-enabled/
│ ├── web1.com.conf
│ └── web2.es.conf


Configuraciones de archivos

nginx.conf
Este es el archivo de configuración principal que en comparación a los anteriores que hemos visto en otros post, únicamente añadiremos la ruta de los sitios enabled donde estarán los archivos de conf de cada sitio/dominio.

# Indica nª de procesos de worker que se deben iniciar. Normalmente se configura al número de cores de la CPU.
worker_processes 1;

# Máximo número de conexiones simultáneas que puede manejar cada proceso worker.
events {
    worker_connections 1024;
}


http {
    # Este archivo contiene los tipos MIME que Nginx usará.
    include /etc/nginx/mime.types;
    
    # Tipo MIME por defecto.
    default_type application/octet-stream;
    
        # Oculta la versión de NGINX en las respuestas HTTP.
    server_tokens off;

    # Cabeceras de seguridad:
    add_header X-Frame-Options SAMEORIGIN;  # Protege contra clickjacking
    add_header X-Content-Type-Options nosniff;  # Protege contra ataques MIME
    add_header X-XSS-Protection "1; mode=block";  # Protección contra cross-site scripting
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; # Configuración de HSTS

    # Limitación de tasa para prevenir fuerza bruta o ataques DDoS (por ejemplo, para limitar a 5 solicitudes por minuto).
    limit_req_zone $binary_remote_addr zone=one:10m rate=5r/m;
    
    # Limitar número de conexiones simultáneas por IP (por ejemplo, a 10 conexiones por IP).
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn addr 10;

    # Permite envío de archivos directamente desde el sistema de archivos al socket de red.
    sendfile on;
    
    # Incluir configuraciones para cada sitio.
    include /etc/nginx/sites-enabled/*;

}

Ejemplo web1.com.conf:
Como se puede observar en el ejemplo anterior se añaden las configuraciones de nginx en el archivo y únicamente del dominio / subdominio que queramos. Además dejo el ejemplo de la configuración ssl que además ya lo tenemos en post anteriores.

### WEB1 ###
server {
    # Esta sección es para redirigir todas las conexiones no seguras (HTTP, puerto 80) a HTTPS (puerto 443).
    listen 80;
        server_name web1.com;

    # Necesario para el certbot !!!
    ## Recordatorio si es la primera vez de usar el cerbot añadir:
    ## docker-compose run --rm --entrypoint "certbot certonly --webroot -w /etc/letsencrypt --email tu@email.es --agree-tos --no-eff-email -d dominio.com" certbot
    
    
    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root /etc/letsencrypt;
        allow all;
        try_files $uri =404;
    }

    location ~ {
        return 301 https://$host$request_uri;
    
    }
    # Carpeta de registros
    access_log /var/log/nginx/access_web1.log;  
    error_log /var/log/nginx/error_web1.log;
}

server {
    listen 443 ssl;
    server_name web1.com;

    ssl_certificate /etc/letsencrypt/live/web1.com/fullchain.pem; # Especifica la ubicación de tu certificado
    ssl_certificate_key /etc/letsencrypt/live/web1.com/privkey.pem; # Especifica la ubicación de tu clave privada
    
    location / {
        # Se usa con uwsgi
        include uwsgi_params;
        # Aquí especificas directamente tu servidor UWSGI
        uwsgi_pass python_web1:4441;

        # Establece el encabezado Host para el proxy.
        proxy_set_header Host $host;
        # Establece el encabezado X-Real-IP para el proxy.
        proxy_set_header X-Real-IP $remote_addr;
        # Establece el encabezado X-Forwarded-For para el proxy.
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # Establece el encabezado Content-Type para el proxy.
        proxy_set_header Content-Type $http_content_type;
        # Establece el encabezado Content-Length para el proxy
        proxy_set_header Content-Length $http_content_length;
        # Define la versión de HTTP para el proxy.
        proxy_http_version 1.1;
        # Se usa para Websockets.
        proxy_set_header Upgrade $http_upgrade;
        # Se usa para Websockets.
        proxy_set_header Connection "Upgrade";


        # Control de manejo del tamaño de archivo recibido
        client_max_body_size 50M; 
        
        # Encabezados Cors, permite que el navegador realice las solicitudes
        # Si deseas restringir el acceso solo a orígenes específicos, reemplazar el * con el origen permitido.
        # Por ejemplo, add_header Access-Control-Allow-Origin http://ip_publica:20222;

        # Permitir el acceso: a todos.
        # add_header Access-Control-Allow-Origin *; ## A todos
        add_header Access-Control-Allow-Origin "web1.com"; ## A tu misma web
        # Establece los métodos HTTP permitidos para las solicitudes desde un origen externo.
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        # Establece los encabezados personalizados permitidos en las solicitudes CORS. Los encabezados mencionados en la directiva, 
        #  como DNT, User-Agent, X-Requested-With, etc.
        add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,x-access-token';
        # Define qué encabezados pueden ser expuestos en la respuesta a una solicitud CORS. En este caso, se exponen los encabezados Content-Length 
        #  y Content-Range. Esto significa que el cliente que realice la solicitud CORS puede acceder a los valores de estos encabezados en la respuesta.
        add_header Access-Control-Expose-Headers 'Content-Length,Content-Range';
    }
    # Carpeta de registros
    access_log /var/log/nginx/access_web1.log;  
    error_log /var/log/nginx/error_web1.log;
}

Ya con esta configuración de web1 se puede duplicar e ir añadiendo más dominios/subdominios.

Espero que esta configuración os sirva de ayuda.

Salu2!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *