MIX_ENV = prod на сервере Phoenix сбой при запуске с PORT = 80

У меня возникают проблемы с mix и MIX_ENV=prod с mix phoenix.server, где он не работает при запуске. Запуск всех последних (Elixir 1.0.5, Phoenix 0.14.0), за исключением Erlang (17.x, 17.3, я думаю) на Linode 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,[]]}}}"}

В частности, я думаю, что эта часть трассировки.

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

Ответ 1

Похоже, ваш сервер пытается привязать к ограниченному порту (менее 1024) без привилегий root. Попробуйте использовать более высокий порт, например, по умолчанию Phoenix 4000. Если он должен быть на порту 80, запустите его как root или (лучше) прокси с помощью nginx.

Ответ 2

Как заметил Ник Мехарри, вы пытаетесь запустить процесс Phoenix-сервера на порте, который традиционно используется в Unix, только root может связываться с (low ports (< 1024)).

Выполнение вашего процесса как root не рекомендуется по соображениям безопасности - злоумышленник, который возьмет на себя этот процесс, получит доступ root ко всей операционной системе.

Более безопасно работать с этим, запустив свой сервер на высоком порту (например, 4000) и используйте простое правило iptables для пересылки соединений с порта 80 на порт 4000. Обратите внимание, что любой пользователь на вашем компьютере может связывать на порт 4000 - чтобы вы потеряли дополнительную защиту от низких портов.

Еще одно решение - разрешить определенным программам (mix, elixir) связывать с портами ниже 1024, используя CAP_NET_BIND_SERVICE Linux ядра (доступно с версии 2.6.24), которые можно установить с помощью setcap. Но тогда любой пользователь может использовать эти исполняемые файлы, если только они не доступны только определенному пользователю, используя правильные права доступа к файлам.

Ответ 3

Я вижу следующие варианты:

  • Используйте apache/nginx перед прокси-сервером для феникса, работающего на более высоком порту за ним. Создатель Elixir сказал, что обычно нет необходимости делать это в этом вопросительном потоке. Если вам уже нужен nginx для чего-то другого (например, запуска WP или обслуживания статических изображений), просто выполните это.
  • Запустите простую, но очень плохую идею с точки зрения безопасности.
  • Использовать таблицы IP - простые и эффективные, но разрывы ipv6
  • Используйте setcap, чтобы дать определенным двоичным файлам возможность открывать более низкие порты.

Мне нравится вариант 4.

Для запуска mix phoenix.server и подобных команд вам нужно запустить setcap в двоичном формате BEAM. Вы можете найти его, ненадолго запустив сервер как root и сделав ps -ef | grep beam. В моей системе это /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

Теперь сервер может быть запущен на обычном порту с командами микширования. Затем, предположительно, вам захочется развернуть фактический релиз эликсира и запустить его как службу. Та же стратегия работает. Используйте setcap в двоичной версии run_erl, созданной вашей версией. Для моего приложения это было:

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

Теперь вы можете запустить сервер upstart или systemd script.