[英]MIX_ENV=prod on a Phoenix server crashes on starting with PORT=80
I am having some issues with mix, and MIX_ENV=prod
with mix phoenix.server
, where it fails on starting. 我有一些混合问题, MIX_ENV=prod
with mix phoenix.server
,它在启动时失败。 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. 在Linode的Ubuntu 14.04上运行所有最新的(Elixir 1.0.5,Phoenix 0.14.0),除了Erlang(17.x,17.3我认为)。
$ 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. 看起来您的服务器正在尝试绑定到没有root权限的受限端口(小于1024)。 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. 尝试使用更高端口,例如Phoenix的默认值4000.如果它需要在端口80上,要么以root身份运行,要么(更好)使用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)). 正如Nick Meharry指出你试图在传统上在Unix上的端口上运行Phoenix服务器进程,只有root可以绑定到(低端口(<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. 由于安全原因,不建议以root
身份运行您的进程 - 接管该进程的攻击者可以获得对整个操作系统的root访问权限。
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. 通过在高端口(例如,4000)上运行服务器并使用简单的iptables规则将连接从端口80转发到端口4000来解决此问题更安全。请注意,计算机上的任何用户都可以绑定到端口4000 - 所以你失去了低端口的额外保护。
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
. 另一个解决方案是允许某些程序( mix
, elixir
)使用CAP_NET_BIND_SERVICE
Linux内核功能(自2.6.24开始提供)绑定到1024以下的端口,该功能可以使用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. 我喜欢选项4。
In order to run mix phoenix.server
and similar commands, you need to run setcap
on your BEAM binary. 要运行mix phoenix.server
和类似命令,需要在BEAM二进制文件上运行setcap
。 You can find it by briefly starting the server as root and doing ps -ef | grep beam
你可以通过简单地以root身份启动服务器并执行ps -ef | grep beam
来找到它 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: 在我的系统上,它是/usr/lib/erlang/erts-8.1/bin/beam.smp
,所以我运行:
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. 现在可以使用mix命令在普通端口上启动服务器。 Next, presumably you're going to want to deploy an actual elixir release and run it as a service. 接下来,大概你会想要部署一个实际的elixir版本并将其作为服务运行。 The same strategy works. 同样的策略也有效。 Use setcap
on the run_erl
binary your release created. 在您的发布版本创建的run_erl
二进制文件上使用setcap
。 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. 现在,一个upstart或systemd脚本也可以启动服务器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.