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"}
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().
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],
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With