Skip to content

refactor: Standardise listener IPv6 support across endpoints #13112

@twellck

Description

@twellck

Description

Description

APISIX handles listener configuration inconsistently across its endpoints. node_listen and ssl.listen support flexible object/list-based definitions and automatically generate proper dual-stack (IPv4 + IPv6) listen directives when enable_ipv6 is true. Other endpoints do not:

Listener Config Key IPv6 support Multi-port Uses listen_table_insert
HTTP proxy apisix.node_listen Yes Yes Yes
HTTPS/SSL apisix.ssl.listen Yes Yes Yes
PROXY Protocol apisix.proxy_protocol Global only (added in #12859) No No
Admin API deployment.admin.admin_listen No No No
Control API apisix.control No No No
Status API apisix.status No No No
Prometheus plugin_attr.prometheus.export_addr No No No

The problem in practice

In IPv6 environments like Kubernetes, deployers currently work around this by either setting the listener IP directly to [::] (relying on OS-level dual-stack behavior, which isn't guaranteed) or injecting raw Nginx configuration snippets. For example, a Helm values workaround to get IPv6 working on admin, status, and proxy_protocol:

admin:
  ip: '"[::]"'
status:
  ip: '"[::]"'
nginx:
  configurationSnippet:
    httpSrv: |
      listen [::]:9182 ssl default_server proxy_protocol;

This should be unnecessary, setting enable_ipv6: true should be enough for all endpoints to generate proper dual-stack listen directives, just as it already does for node_listen and ssl.listen.

Proposed Change

Route all listener processing through listen_table_insert in ops.lua, which already handles IPv4/IPv6 expansion, IP validation, and duplicate detection. This would:

  1. For proxy_protocol: Add full alignment with node_listen/ssl.listen, list-based listen_http/listen_https keys with IP binding and multi-port support (backward compatible with listen_http_port/listen_https_port).
  2. For admin, control, status, prometheus: Process through listen_table_insert to gain automatic IPv6 support via enable_ipv6. No multi-port support needed, these remain single-endpoint listeners.

The result is one code path for all listeners instead of the current 4-5 different patterns, and enable_ipv6: true works consistently everywhere.

Implementation approach

The bulk of the work involves making listen_table_insert generic enough to handle all listener types (it currently assumes HTTP/HTTPS proxy semantics). The template changes in ngx_tpl.lua are minimal, iterating over processed listener lists instead of raw config values. Most of the diff will likely be in tests, updating them to validate IPv6 generation and the new schema for proxy_protocol. The core logic change is small since the patterns already exist in node_listen/ssl.listen processing.

Context

This was originally part of #12859, which was simplified per reviewer feedback to only add IPv6 support for PROXY Protocol. A reference implementation for the proxy_protocol portion exists on branch refactor/proxy-protocol-listener-standardization.


Note: AI helped format this Issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    📋 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions