Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Phoenix to listen on IPv6?

I'm struggling to find information about getting Phoenix (and Cowboy and Ranch for that matter) to listen on both IPv4 and IPv6.

I'm running on a VPS with Ubuntu 16.04. It has both an IPv4 and IPv6 address. When running netstat -tulpn it shows that beam is only listening on IPv4, with the ports specified in Phoenix config. Whereas other processes, like epmd, are able to listen on both IPv4 and IPv6.

I've tried specifying a port like "::4000" in my config.exs, but it crashes due to failure to parse as an integer.

Can someone point me in the right direction? Do I need to add a custom Cowboy listener somehow?

I'd rather not have to run Nginx in front to listen to IPv6 traffic.

Config I tried:

config :my_app, MyApp.Endpoint,
  http: [port: "[::]:4000"]

Stack trace (looks like Phoenix only expects an integer port):

** (Mix) Could not start application my_app: MyApp.start(:normal, []) returned an error: shutdown: failed to start child: MyApp.Endpoint
    ** (EXIT) shutdown: failed to start child: Phoenix.Endpoint.Server
        ** (EXIT) an exception was raised:
            ** (ArgumentError) argument error
                :erlang.binary_to_integer("[::]:4000")
                (phoenix) lib/phoenix/endpoint/server.ex:32: Phoenix.Endpoint.Server.to_port/1
                (phoenix) lib/phoenix/endpoint/server.ex:28: Phoenix.Endpoint.Server.default/3
                (phoenix) lib/phoenix/endpoint/server.ex:17: anonymous fn/5 in Phoenix.Endpoint.Server.init/1
                (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
                (phoenix) lib/phoenix/endpoint/server.ex:15: Phoenix.Endpoint.Server.init/1
                (stdlib) supervisor.erl:294: :supervisor.init/1
                (stdlib) gen_server.erl:328: :gen_server.init_it/6
                (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Also this is Phoenix {:phoenix, "~> 1.2.0"} and Cowboy {:cowboy, "~> 1.0"}

like image 892
TalkLittle Avatar asked Jan 06 '23 08:01

TalkLittle


2 Answers

config :my_app, MyApp.Endpoint,
  http: [port: 4000, ip: {0, 0, 0, 0, 0, 0, 0, 0}]

This tells Phoenix to listen on all IPv6 addresses. It also listens on IPv4.

I originally thought this was IPv6-only, since netstat -tulpn shows beam as only tcp6 and not tcp. But after testing, it's clear that it is also listening on IPv4 as an "IPv4-mapped IPv6 address."

The IP tuple format is Erlang type inet:ip6_address().

like image 156
TalkLittle Avatar answered Jan 16 '23 05:01

TalkLittle


According to https://hexdocs.pm/phoenix/endpoint.html you can also use just :inet6. This works for me:

config :my_app, MyApp.Endpoint,
  http: [:inet6, port: 4000],
like image 41
phunehehe Avatar answered Jan 16 '23 03:01

phunehehe