I am having some issues with mix, and MIX_ENV=prod
with mix phoenix.server
, where it fails on starting. Running all latest (Elixir 1.0.5, Phoenix 0.14.0) except Erlang (17.x, 17.3 I think) on Linode's Ubuntu 14.04.
$ MIX_ENV=prod PORT=80 mix phoenix.server
{"Kernel pid terminated",application_controller,"{application_start_failure,elirc_site,{{shutdown,{failed_to_start_child,'Elixir.ElircSite.Endpoint',{shutdown,{failed_to_start_child,'Elixir.Phoenix.Endpoint.Server',{shutdown,{failed_to_start_child,{ranch_listener_sup,'Elixir.ElircSite.Endpoint.HTTP'},{shutdown,{failed_to_start_child,ranch_acceptors_sup,{{badmatch,{error,eacces}},[{ranch_acceptors_sup,init,1,[{file,\"src/ranch_acceptors_sup.erl\"},{line,30}]},{supervisor,init,1,[{file,\"supervisor.erl\"},{line,243}]},{gen_server,init_it,6,[{file,\"gen_server.erl\"},{line,306}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,239}]}]}}}}}}}}},{'Elixir.ElircSite',start,[normal,[]]}}}"}
Specifically I think its this part of the trace.
{{badmatch,{error,eacces}},[{ranch_acceptors_sup,init,1,[{file,\"src/ranch_acceptors_sup.erl\"},{line,30}]}
It looks like your server is attempting to bind to a restricted port (less than 1024) without root privileges. Try using a higher port, like Phoenix's default of 4000. If it needs to be on port 80, either run it as root or (better) proxy it with nginx.
As Nick Meharry pointed out you are trying to run your Phoenix server process on a port that traditionally on Unix, only root can bind to (low ports (<1024)).
Running your process as root
is not recommended because of security reasons - an attacker who would take over the process could get root access to the whole operating system.
It's more secure to work around this by running your server on a high port (for instance, 4000) and use a simple iptables rule to forward the connections from port 80 to port 4000. Note that any user on your machine can bind to port 4000 - so you lose the extra protection from the low ports.
Another solution is to allow certain programs ( mix
, elixir
) to bind to ports below 1024 using CAP_NET_BIND_SERVICE
Linux kernels capability (available since 2.6.24) which can be set using setcap
. But then still any user can use this executables unless they are available only to a certain user by using proper file access rights.
I see the following options:
I like option 4.
In order to run mix phoenix.server
and similar commands, you need to run setcap
on your BEAM binary. You can find it by briefly starting the server as root and doing ps -ef | grep beam
ps -ef | grep beam
. On my system, it's /usr/lib/erlang/erts-8.1/bin/beam.smp
, so I ran:
sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/lib/erlang/erts-8.1/bin/beam.smp
Now the server can be started on a normal port with mix commands. Next, presumably you're going to want to deploy an actual elixir release and run it as a service. The same strategy works. Use setcap
on the run_erl
binary your release created. For my app it was:
sudo setcap CAP_NET_BIND_SERVICE=+eip /home/ubuntu/myapp/_build/prod/rel/myapp/erts-8.1/bin/run_erl
Now an upstart or systemd script can launch the server, too.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.