2015-06-30 9 views
10

Sto riscontrando alcuni problemi con il mix e MIX_ENV=prod con mix phoenix.server, dove non riesce all'avvio. Funzionando tutti i più recenti (Elixir 1.0.5, Phoenix 0.14.0) eccetto Erlang (17.x, 17.3 penso) su Ubuntu 14.04 di Linode.MIX_ENV = prod su un server Phoenix si blocca all'avvio con PORT = 80

$ 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,[]]}}}"} 

In particolare, penso che sia questa parte della traccia.

{{badmatch,{error,eacces}},[{ranch_acceptors_sup,init,1,[{file,\"src/ranch_acceptors_sup.erl\"},{line,30}]} 

risposta

5

Sembra che il server stia tentando di collegarsi a una porta con restrizioni (inferiore a 1024) senza privilegi di root. Prova a usare una porta più alta, come il default di Phoenix di 4000. Se deve essere sulla porta 80, eseguilo come root o (meglio) proxy con nginx.

+4

Di solito non è necessario eseguire Phoenix dietro a nginx. :) –

+0

Giusto. Questo è solo meglio se non vuoi eseguire il tuo codice a livello di applicazione come root ma assolutamente bisogno della porta 80/443 (che pensavo sarebbe potuta essere il caso qui). –

+4

Si potrebbe anche eseguire un NAT sulla porta usando iptables (o firewall di preferenza). Es: iptables -t nat -A OUTPUT -d myhostname p tcp --dport 80 -j REDIRECT --to-porte 8080 && iptables -t nat -A PREROUTING -d myhostname -p tcp --dport 80 -j REDIRECT --to-ports 8080 – diogovk

4

Come Nick Meharry ha sottolineato, si sta tentando di eseguire il processo del server Phoenix su una porta che tradizionalmente su Unix, solo root può eseguire il binding a (porte basse (< 1024)).

L'esecuzione del processo come root non è consigliata per motivi di sicurezza: un utente malintenzionato che subentrerà nel processo potrebbe ottenere l'accesso come root all'intero sistema operativo.

È più sicuro aggirare questo problema eseguendo il server su una porta alta (ad esempio, 4000) e utilizzare una semplice regola di iptables per inoltrare le connessioni dalla porta 80 alla porta 4000. Si noti che qualsiasi utente sulla macchina può legare alla porta 4000 - in modo da perdere la protezione extra dalle porte basse.

Un'altra soluzione è quella di consentire alcuni programmi (mix, elixir) per collegarsi alle porte inferiore a 1024 usando CAP_NET_BIND_SERVICE Linux funzionalità kernel (disponibile dal 2.6.24), che può essere impostato utilizzando setcap. Tuttavia, qualsiasi utente può ancora utilizzare questi file eseguibili a meno che non siano disponibili solo per un determinato utente utilizzando i diritti di accesso ai file appropriati.

4

vedo le seguenti opzioni:

  1. Usa apache/nginx davanti come proxy per Phoenix in esecuzione su una porta più alta dietro-Il creatore di Elixir, ha detto di solito c'è alcun bisogno di farlo in questo thread molto domanda. Se hai già bisogno di nginx per qualcos'altro (come l'esecuzione di WP o di immagini statiche), fallo.
  2. Esegui come root, semplice ma pessima idea dal punto di vista della sicurezza.
  3. Utilizzare le tabelle IP: semplice ed efficace, ma si interrompe ipv6
  4. Utilizzare setcap per fornire a binari specifici la possibilità di aprire porte inferiori.

mi piace l'opzione 4.

Al fine di eseguire mix phoenix.server e simili comandi, è necessario eseguire setcap sul binario BEAM. Puoi trovarlo avviando brevemente il server come root e facendo ps -ef | grep beam. Sul mio sistema, è /usr/lib/erlang/erts-8.1/bin/beam.smp, così mi sono imbattuto:

sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/lib/erlang/erts-8.1/bin/beam.smp

Ora il server può essere avviato su una porta normale con i comandi mix. Successivamente, presumibilmente vorrai distribuire una versione di elisir effettiva ed eseguirla come un servizio. La stessa strategia funziona. Utilizzare setcap nel file binario run_erl creato.Per la mia app è stata:

sudo setcap CAP_NET_BIND_SERVICE=+eip /home/ubuntu/myapp/_build/prod/rel/myapp/erts-8.1/bin/run_erl

Ora uno script di upstart o systemd può avviare il server, anche.

+1

Per me ho dovuto usare 'setcap' on/beam not /beam.smp. Questo aiuta a testare se funziona: lancia 'iex', quindi': gen_tcp.listen (80, []) '. Dovrebbe risultare qualcosa del tipo: '{: ok, #Port <0.1426>}' – Vantalk