OSX Mavericks: Como posso iniciar um servidor web na inicialização e ouvir a porta 80 sem executar o servidor da Web como root?

1

De acordo com a documentação launchd da Apple :

[launchd] Eliminates the primary reason for running daemons as root. Because launchd runs as root, it can create low-numbered TCP/IP listen sockets and hand them off to the daemon.

Isso é bom ... mas como?

Eu quero fazer o seguinte:

  • inicie o servidor web Nginx no momento da inicialização
  • escuta a porta 80
  • execute como _www user

qual é exatamente o cenário que a documentação acima está falando. Mas eu não encontrei uma maneira de fazer isso que não me desse uma mensagem de erro bind() to 0.0.0.0:80 failed (13: Permission denied) .

Aqui está o arquivo .plist que eu tenho em /Systems/Library/LaunchDemons/homebrew.mxcl.nginx.plist :

<!--
Adapted from the .plist file provided as part of
the Mac Homebrew distribution of nginx.
-->

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>


<!-- 
Here's the problem!!

    <key>Username</key>
    <string>_www</string>

-->

<!--
I thought that Sock(et) declarations would be
the way to tell launchd to hand off a port to the
daemon. So I added these lines, but they don't
appear to make any difference at all.
-->

    <key>SockServiceName</key>
    <string>http</string>

    <key>SockType</key>
    <string>stream</string>

    <key>SockFamily</key>
    <string>IP4</string>

    <key>Label</key>
    <string>homebrew.mxcl.nginx</string>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <false/>

    <key>StandardOutputPath</key>
    <string>/var/log/nginx.log</string>

    <key>StandardErrorPath</key>
    <string>/var/log/nginx.log</string>

    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/opt/nginx/bin/nginx</string>
    </array>

    <key>WorkingDirectory</key>
    <string>/usr/local</string>

  </dict>
</plist>

Como você pode ver, o Username: _www está comentado. Então, quando eu executo o launchd como root, o nginx roda como root, e tudo funciona bem. Mas quando incluo a declaração Username: _www , o nginx falha e deixa esta mensagem de erro no arquivo de log:

nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)

O que estou perdendo?

    
por Pitarou 10.03.2014 / 06:15

1 resposta

2

Um daemon precisa "receber" o soquete vinculado por launchd (por exemplo, launch_data_get_fd ) - ele precisa estar ciente do launchd e implementar alguma lógica internamente. AFAIK que não é o caso do nginx, então sugiro uma das seguintes opções:

  • Ajuste a porta nginx para > 1024, configure seu firewall para redirecionar o tráfego de / para a porta 80 de / para a porta nginx;
  • Deixe o launchd executar o nginx como root e faça o nginx perder seus privilégios depois alterando a diretiva user em seu arquivo de configuração;
por 10.03.2014 / 07:19