24

I installed Nginx using homebrew and after completing the installation the following message was displayed:

In the interest of allowing you to run `nginx` without `sudo`, the default
port is set to localhost:8080.

If you want to host pages on your local machine to the public, you should
change that to localhost:80, and run `sudo nginx`. You'll need to turn off
any other web servers running port 80, of course.

You can start nginx automatically on login running as your user with:
  mkdir -p ~/Library/LaunchAgents
  cp #{prefix}/org.nginx.nginx.plist ~/Library/LaunchAgents/
  launchctl load -w ~/Library/LaunchAgents/org.nginx.nginx.plist

Though note that if running as your user, the launch agent will fail if you
try to use a port below 1024 (such as http's default of 80.)

But I want Nginx, on port 80, running at login and I don't want to have to open terminal and type in sudo nginx to do it. I want it to load from a plist file like Redis and PostgreSQL do.

I moved the plist to /Library/LaunchAgents/ from the user folder equivalent and changed its ownership, also tried setting the user directive in the nginx.conf file and still the same error message in Console.app:

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

(along with another message telling me that since nginx was being run without super-user privileges, the user directive was being ignored)

1
  • Be sure your plist file has "root:wheel" ownership when you move it in any of LaunchDaemons folders. otherwise launchctl won't run it beacuse of "dubious ownership".
    – risyasin
    Aug 20, 2014 at 23:29

5 Answers 5

12

I found an easier approach was to create add plist file in /Library/LaunchDaemons/

sudo vi /Library/LaunchDaemons/org.nginx.nginx.plist

Or, if you want it to launch on login, you can put it in ~/Library/LaunchAgents/, the same plist file. This will allow you to access the launchd launchctl command from your username without the need to call sudo.

and insert the following (be sure to update the path to your nginx install, and the username to your username):

<?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>
    <key>Label</key>
    <string>nginx</string>
    <key>Program</key>
    <string>/usr/local/Cellar/nginx/1.6.2/bin/nginx</string>
    <key>KeepAlive</key>
    <true/>
    <key>NetworkState</key>
    <true/>
    <key>LaunchOnlyOnce</key>
    <true/>
    <key>UserName</key>
    <string>yourusername</string>
</dict>
</plist>
5
  • This is a useful answer, but technically it starts nginx at boot, not login. If @Bryson really only wants it running after he logs into a certain GUI account, then this is not quite the right answer. But I suspect he really wants it running as soon as the machine has booted, even if the GUI is waiting at Login Window, rather than waiting until he actually logs in.
    – Spiff
    Mar 12, 2012 at 20:10
  • I added it to ~/Library/LaunchAgents/ and I get the following errors in Console: 3/30/13 9:39:24.047 AM com.apple.launchd.peruser.501[884]: (nginx) Unknown key for boolean: NetworkState 3/30/13 9:39:24.047 AM com.apple.launchd.peruser.501[884]: (nginx) Ignored this key: UserName 3/30/13 9:39:24.047 AM com.apple.launchd.peruser.501[884]: (nginx) Ignored this key: UserName. I changed Program string to /usr/local/Cellar/nginx/1.2.7/sbin/nginx if that matters.
    – hobbes3
    Mar 30, 2013 at 13:40
  • 3
    Actually I just took the original homebrew.mxcl.nginx.plist, changed UserName to root, then sudo chown root, and ran sudo launchctl load -w and it worked.
    – hobbes3
    Mar 30, 2013 at 14:14
  • Can I just check -- you have a .plist in ~/Library/LaunchAgents/ (so it's for one user only), but it starts as root? I've never seen that possibility mentioned in the documentation, and when I tried it on Mavericks it failed.
    – Pitarou
    Mar 12, 2014 at 5:02
  • @hobbes3 @rich-kroll Almost a year later but KeepAlive can either be true, or set to a dict that contains NetworkState. So the example above should say <key>KeepAlive</key><dict><key>NetworkState</key><true/></dict> (note that I replaced KeepAlive's true with the dictionary containing NetworkState). Source: developer.apple.com/library/mac/documentation/Darwin/Reference/… Jan 16, 2015 at 1:07
9

I got here because I was running into the same problem. My solution was similar to Rich's above, except I used the Homebrew nginx startup script:

sudo cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist /Library/LaunchDaemons/

For reference, here is what that homebrew.mxcl.nginx.plist looks like:

<?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>
    <key>Label</key>
    <string>homebrew.mxcl.nginx</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <false/>
    <key>UserName</key>
    <string>root</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/sbin/nginx</string>
    </array>
    <key>WorkingDirectory</key>
    <string>/usr/local</string>
  </dict>
</plist>

I have 2 aliases added to my $HOME/.profile for making it easier to start and stop nginx.

# Nginx needs to bind to port 80 so must run as /Library/LaunchDaemon with sudo
alias start-nginx='sudo launchctl load /Library/LaunchDaemons/homebrew.mxcl.nginx.plist'
alias stop-nginx='sudo launchctl unload /Library/LaunchDaemons/homebrew.mxcl.nginx.plist'

My problem was that for some reason nginx wasn't starting up properly initially. I just had to run the stop-nginx to unload it, and then re-start it again with start-nginx.

1
2

Not an exact answer to your question, but might come close enough: you can redirect port 80 to port 8080, using the packetfilter pf (tested on OS X 10.9). Add the following line to your /etc/pf.conf (it should come above the filtering rules):

rdr pass on lo0 inet proto tcp from any to any port http -> localhost port 8080

An explanation of (most of) the elements of this line can be found here.

For more information, see https://superuser.com/a/521803 and http://www.openbsd.org/faq/pf/index.html, though the latter seems to describe a newer version of pf, in which the given line would be written differently.

1

I took inspiration from the Pow server and made a plist that sets up port forwarding. It forwards port 80 to port 8080, and port 443 to port 8443. This way I can run nginx under a normal user, and all my connections transparently work.

The plist is here: https://gist.github.com/stefansundin/f0ad99195333480157ce67e97c8d28c7

0

I can think of two explanations:

  1. There are some lines like this in your .plist file:

    <key>Username</key>
    <string>some_user</string>
    

    This tells launchd to launch nginx with the privileges of the specified user, rather than root.

    If you want nginx to bind to port 80, you should set the username in nginx's user directive, rather than in the .plist. nginx will then drop the privilege for the worker processes, although the master process will still be root.

  2. You have an nginx .plist in ~/Library/LaunchAgents/ (note the leading ~) rather than /Library/LaunchAgents.

    Note that it's possible to activate and deactivate .plists, so it's possible there are two nginx .plists on your system, but only one of them is active.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .