Skip to content

fix(gateway): bind to IPv6 dual-stack for Railway private networking - #227

Merged
maakle merged 1 commit into
mainfrom
fix/gateway-ipv6-bind
Jun 1, 2026
Merged

fix(gateway): bind to IPv6 dual-stack for Railway private networking#227
maakle merged 1 commit into
mainfrom
fix/gateway-ipv6-bind

Conversation

@maakle

@maakle maakle commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

After #226 (single-origin gateway) shipped, production hit ECONNREFUSED when the web service tried to proxy /mcp, /v1/*, etc. to the gateway over Railway's private network.

Root cause: Railway's private DNS (e.g. gateway.railway.internal) resolves to IPv6 addresses. @hono/node-server's default bind is 0.0.0.0 which is IPv4-only, so internal traffic was rejected even though public ingress worked.

Fix

One-line change in apps/gateway/src/main.ts — pass hostname: '::' to serve(). This binds the gateway in IPv6 dual-stack mode, which accepts BOTH IPv4 and IPv6 connections through the same socket on Linux. No other change needed.

What's unaffected

  • Public ingress (Railway edge → gateway): edge still reaches the container fine — dual-stack accepts the existing IPv4 path.
  • Docker Compose self-host: gateway:8080 inside the compose network already worked over IPv4; it now also works over IPv6 (which compose doesn't use, but harmless).
  • Local pnpm dev: loopback on ::1 and 127.0.0.1 both reach the gateway.

Test plan

  • pnpm -F @holo/gateway typecheck — clean
  • Deploy to Railway; confirm WEB_BASE_URL=https://holobase.dev pnpm verify:gateway returns 6 green checks
  • Confirm Claude Desktop tool call via https://holobase.dev/mcp round-trips (the operator gate from ADR 0009)

🤖 Generated with Claude Code

Railway's private networking (`*.railway.internal`) resolves to IPv6
addresses. The default `0.0.0.0` bind is IPv4-only and rejects internal
service-to-service connections with ECONNREFUSED — observed when the web
service proxies /mcp, /v1/*, etc. to the gateway via the single-origin
rewrites added in ADR 0009.

Binding to `::` (IPv6 unspecified) enables dual-stack mode, accepting
both IPv4 and IPv6 traffic through the same socket. Public ingress
(Railway edge → container) keeps working; docker-compose and local
`pnpm dev` are unaffected because loopback works on both stacks.
@maakle
maakle merged commit b9a8e27 into main Jun 1, 2026
5 checks passed
@maakle
maakle deleted the fix/gateway-ipv6-bind branch June 1, 2026 09:33
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.

1 participant