# Actualización de configuración Nginx: Migración de listen ... http2 a http2 on; y resolución de “protocol options redefined”

- Link: https://binariocero.com/linux/actualizacion-de-configuracion-nginx-migracion-de-listen-http2-a-http2-on-y-resolucion-de-protocol-options-redefined
- Published: 2025-08-15T11:05:23+02:00
- Author: Juan José Fernández Durán

![Loading](https://binariocero.com/wp-content/plugins/page-views-count/ajax-loader-
2x.gif)

## 1. Contexto y motivo del cambio

A partir de **Nginx 1.25.1** (publicado el 4 de julio de 2023), el parámetro `http2`
ya **no se especifica** en la directiva `listen`. En su lugar, debe activarse con
la directiva independiente:

    ```wp-block-code
    http2 on;
    ```

Esto afecta a todas las configuraciones que tengan líneas como:

    ```wp-block-code
    listen 443 ssl http2;
    ```

Si no se actualiza la sintaxis, Nginx mostrará advertencias como:

    ```wp-block-code
    [warn] the "listen ... http2" directive is deprecated, use the "http2" directive instead
    ```

Además, pueden aparecer advertencias del tipo:

    ```wp-block-code
    protocol options redefined for 0.0.0.0:443
    ```

Esto sucede cuando se repiten líneas `listen` con opciones distintas para la misma
dirección:puerto dentro de un mismo bloque `server {}`.

## 2. Versiones afectadas

 * **Nginx ≤ 1.25.0**: Se permitía y era habitual `listen 443 ssl http2;`.
 * **Nginx ≥ 1.25.1**: `http2` **solo** se activa con la directiva `http2 on;` dentro
   del bloque `server {}`.
   Fuente: _CHANGES nginx-1.25.1_
   .

## 3. Ejemplo de advertencias reales

Ejemplo de log en Nginx 1.25.x:

    ```wp-block-code
    2025/08/11 21:59:01 [warn] the "listen ... http2" directive is deprecated, use the "http2" directive instead in /etc/nginx/sites-enabled/site1:27
    2025/08/11 21:59:01 [warn] protocol options redefined for 0.0.0.0:443 in /etc/nginx/sites-enabled/site2:9
    ```

## 4. Cambios de sintaxis

### **Antes (obsoleto)**

    ```wp-block-code
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name ejemplo.com;
        ssl_certificate     /etc/ssl/cert.pem;
        ssl_certificate_key /etc/ssl/key.pem;
    }
    ```

### **Después (recomendado)**

    ```wp-block-code
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        http2 on;

        server_name ejemplo.com;
        ssl_certificate     /etc/ssl/cert.pem;
        ssl_certificate_key /etc/ssl/key.pem;
    }
    ```

## 5. Procedimiento de actualización

### 5.1 Hacer copia de seguridad

    ```wp-block-code
    sudo cp -a /etc/nginx/sites-enabled /etc/nginx/sites-enabled.bak.$(date +%F)
    ```

### 5.2 Sustituir `ssl http2` por `ssl`

    ```wp-block-code
    sudo sed -i -E '
      s/(listen[[:space:]]+\[::\]:443[[:space:]]+)([^;]*)(http2)([^;]*);/\1\2\4;/g;
      s/(listen[[:space:]]+443[[:space:]]+)([^;]*)(http2)([^;]*);/\1\2\4;/g
    ' /etc/nginx/sites-enabled/*
    ```

### 5.3 Añadir `http2 on;` dentro de cada `server {}` que sirva HTTPS

Debe colocarse **solo una vez por bloque**.

## 6. Resolución de “protocol options redefined”

Para evitar el mensaje:

    ```wp-block-code
    protocol options redefined for 0.0.0.0:443
    ```

hay que asegurarse de:

 * Tener **una sola línea** `listen 443 ssl;` por IPv4 y otra `listen [::]:443 ssl;`
   por IPv6 en cada bloque.
 * No duplicar `listen 0.0.0.0:443 ...` con parámetros distintos en el mismo `server{}`.
 * Usar `default_server` **solo** en un vhost.

## 7. Ejemplo práctico: `site1.example.com`

### **Antes**

    ```wp-block-code
    server {
        server_name site1.example.com;

        location / {
            proxy_pass http://192.168.1.100:80;
            include proxy_params;
        }

        listen 443 ssl http2;
        ssl_certificate     /etc/letsencrypt/live/site1.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/site1.example.com/privkey.pem;
    }
    ```

### **Después (compatible con Nginx ≥ 1.25.1)**

    ```wp-block-code
    server {
        server_name site1.example.com;

        listen 443 ssl;
        listen [::]:443 ssl;
        http2 on;

        ssl_certificate     /etc/letsencrypt/live/site1.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/site1.example.com/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
            proxy_pass http://192.168.1.100:80;
            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 https;
        }

        access_log /var/log/nginx/access_site1.log;
    }

    server {
        listen 80;
        listen [::]:80;
        server_name site1.example.com;
        return 301 https://$host$request_uri;
    }
    ```

## 8. Comprobación y recarga

    ```wp-block-code
    sudo nginx -t
    sudo systemctl reload nginx
    ```

Si no hay advertencias, la migración ha sido correcta.

## 9. Conclusiones

 * La directiva `listen ... http2` ha quedado obsoleta en **Nginx 1.25.1 y posteriores**.
 * Es obligatorio mover la activación de HTTP/2 a `http2 on;` dentro del bloque `
   server {}`.
 * El mensaje “protocol options redefined” se evita eliminando duplicados y manteniendo
   la sintaxis consistente.
 * Es recomendable revisar todos los _vhosts_ y probar con `nginx -t` antes de recargar
   el servicio.
