Skip to content

feat: IPv6 dual-stack support for server bind addresses#864

Open
soheilkhan wants to merge 2 commits intoagentic-community:mainfrom
soheilkhan:feat/ipv6-dual-stack-bind
Open

feat: IPv6 dual-stack support for server bind addresses#864
soheilkhan wants to merge 2 commits intoagentic-community:mainfrom
soheilkhan:feat/ipv6-dual-stack-bind

Conversation

@soheilkhan
Copy link
Copy Markdown

@soheilkhan soheilkhan commented Apr 20, 2026

Summary

Resolves #863

All server components currently hard-code their bind address to 0.0.0.0 or default to 127.0.0.1, which prevents deployment on IPv6-only Kubernetes clusters (e.g. EKS in a hybrid VPC where pods are assigned only IPv6 addresses).

This PR makes deployment bind addresses configurable and uses :: (dual-stack) for containerized/managed deployments. On Linux, :: accepts both IPv4 and IPv6 connections by default (via IPv4-mapped IPv6 addresses), so existing IPv4-only deployments continue to work without any changes.

Changes

File What changed
registry/core/config.py Added bind_host: str = "::" setting (configurable via BIND_HOST env var)
registry/main.py Dev registry entrypoint uses settings.bind_host instead of hardcoded 127.0.0.1
docker/registry-entrypoint.sh BIND_HOST env var with :: default, passed to uvicorn
docker/auth-entrypoint.sh Same BIND_HOST pattern for the auth server
.env.example Documents BIND_HOST and the Linux dual-stack assumption
charts/mcpgw/values.yaml Adds configurable app.bindHost: "::"
charts/mcpgw/templates/deployment.yaml Reads HOST from app.bindHost instead of hardcoding it
servers/currenttime/server.py Keeps local default as 127.0.0.1; Docker/Helm/ECS can set HOST=:: explicitly
terraform/aws-ecs/* Adds bind_host variable and passes BIND_HOST/HOST to ECS services
registry/api/config_routes.py Exposes bind_host in the admin config panel

Backward compatibility

  • :: on Linux is dual-stack by default (net.ipv6.bindv6only=0 on all major distros) -- IPv4 clients continue to connect normally
  • If a host/container sets net.ipv6.bindv6only=1, IPv4 clients will not reach services bound only to ::; operators can set BIND_HOST=0.0.0.0 or HOST=0.0.0.0 for IPv4-only binding
  • All bind addresses remain overridable via environment variables (BIND_HOST, HOST) or Helm/Terraform values
  • No Kubernetes Service spec changes needed (ipFamilies/ipFamilyPolicy is handled by VPC CNI)
  • Request parsing (ipaddress.ip_address()) and IP anonymization already handle IPv6

Test plan

  • Python syntax: python3 -m py_compile registry/core/config.py registry/main.py servers/currenttime/server.py registry/api/config_routes.py
  • Shell syntax: bash -n docker/registry-entrypoint.sh docker/auth-entrypoint.sh
  • Terraform formatting for touched files: terraform fmt -check terraform/aws-ecs/variables.tf terraform/aws-ecs/main.tf terraform/aws-ecs/modules/mcp-gateway/variables.tf terraform/aws-ecs/modules/mcp-gateway/ecs-services.tf
  • Helm render: helm template mcpgw charts/mcpgw --set app.secretKey=test-secret renders HOST as ::

@aarora79
Copy link
Copy Markdown
Contributor

Thanks for the PR, @soheilkhan! Great work enabling IPv6 dual-stack support. The approach of using :: for dual-stack is solid, and all 2352 tests pass cleanly.

Requesting the following changes before merge:

1. Add BIND_HOST to .env.example

The new setting needs to be documented for operators. Please add:

# Network bind address: "::" for dual-stack IPv4+IPv6, "0.0.0.0" for IPv4 only
# On Linux, "::" accepts both IPv4 and IPv6 by default (net.ipv6.bindv6only=0)
BIND_HOST=::

2. Make Helm chart bind host configurable via values.yaml

The bind host is currently hardcoded in the template. It should be configurable so operators can override it without forking the chart.

In charts/mcpgw/values.yaml, add:

app:
  bindHost: "::"

In charts/mcpgw/templates/deployment.yaml, change:

# Before
- name: HOST
  value: "::"

# After
- name: HOST
  value: {{ .Values.app.bindHost | quote }}

3. Revert currenttime/server.py default to 127.0.0.1

The default changed from 127.0.0.1 (localhost-only) to :: (all interfaces). This loosens the security posture for local (non-Docker) development. Please keep 127.0.0.1 as the default here and rely on HOST=:: being set explicitly in Docker/Helm environments, which is already the case via the Helm template and Dockerfile.

4. Add Terraform ECS variable for BIND_HOST

Per project standards, new config params should be propagated to Terraform ECS (variables.tf + ecs.tf).

5. Add to Config API for admin visibility

The bind_host setting should be added to CONFIG_GROUPS in registry/api/config_routes.py so it's visible in the admin config panel.

6. Document net.ipv6.bindv6only assumption

The dual-stack behavior depends on the Linux default net.ipv6.bindv6only=0. If a host or container has net.ipv6.bindv6only=1, IPv4 clients will fail to connect when binding to ::. Please add a one-liner about this in the PR description or a deployment doc note.


Happy to re-review once updated.

@aarora79 aarora79 requested a review from omrishiv April 27, 2026 06:12
ssafari added 2 commits April 28, 2026 10:25
…unity#863)

Change default bind address from 0.0.0.0/127.0.0.1 to :: (dual-stack)
across all server components, enabling deployment on IPv6-only Kubernetes
clusters (e.g. EKS in hybrid VPC where pods have only IPv6 addresses).

Binding to :: on Linux accepts both IPv4 and IPv6 connections by default,
so existing IPv4-only deployments continue to work without changes.

Closes agentic-community#863

Made-with: Cursor
Document BIND_HOST, expose bind host in Helm and Terraform ECS, keep local
CurrentTime binds on localhost by default, and show bind_host in the admin
configuration panel.

Made-with: Cursor
@soheilkhan soheilkhan force-pushed the feat/ipv6-dual-stack-bind branch from 663ebfb to 189133c Compare April 28, 2026 17:28
@soheilkhan
Copy link
Copy Markdown
Author

Thanks for the review. Updated in commit 189133c8.

Checklist:

  • Added BIND_HOST to .env.example with the Linux dual-stack note.
  • Made the mcpgw Helm chart configurable via app.bindHost and changed the deployment template to use it.
  • Reverted servers/currenttime/server.py back to the local-safe 127.0.0.1 default; managed deployments now set HOST explicitly.
  • Added Terraform ECS bind_host plumbing and pass BIND_HOST / HOST into the ECS services.
  • Added bind_host to CONFIG_GROUPS for admin config visibility.
  • Updated the PR description with the net.ipv6.bindv6only=0 assumption and override guidance.

Validation run:

  • python3 -m py_compile registry/core/config.py registry/main.py servers/currenttime/server.py registry/api/config_routes.py
  • bash -n docker/registry-entrypoint.sh docker/auth-entrypoint.sh
  • terraform fmt -check on the touched Terraform files
  • helm template mcpgw charts/mcpgw --set app.secretKey=test-secret confirms HOST renders as ::

Note: terraform fmt -check terraform/aws-ecs still reports a pre-existing unrelated formatting issue in terraform/aws-ecs/keycloak-database.tf, so I limited formatting/checks to the Terraform files touched by this PR to avoid unrelated churn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IPv6 support: server bind addresses prevent deployment on IPv6-only Kubernetes clusters

2 participants