简体   繁体   中英

nginx blocking puma from same port

I have a rails app running on puma and nginx. I launch nginx with sudo service nginx restart then puma/rails with rvmsudo rails server -p 80

This is my error:

`initialize': Address already in use - bind(2) for "localhost" port 80 (Errno::EADDRINUSE)

This error only occurs when nginx is already running.

The full error is:

 $rvmsudo rails server -p 80

=> Booting Puma
=> Rails 4.2.4 application starting in development on http://localhost:80
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Puma 2.14.0 starting...
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://localhost:80
Exiting
/home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/puma-2.14.0/lib/puma/binder.rb:233:in `initialize': Address already in use - bind(2) for "localhost" port 80 (Errno::EADDRINUSE)
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/puma-2.14.0/lib/puma/binder.rb:233:in `new'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/puma-2.14.0/lib/puma/binder.rb:233:in `add_tcp_listener'
    from (eval):2:in `add_tcp_listener'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/puma-2.14.0/lib/rack/handler/puma.rb:33:in `run'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/rack-1.6.4/lib/rack/server.rb:286:in `start'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/railties-4.2.4/lib/rails/commands/server.rb:80:in `start'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:80:in `block in server'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:75:in `tap'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:75:in `server'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /home/my-user-name/apps/my-web-app/shared/bundle/ruby/2.1.0/gems/railties-4.2.4/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'

Any help on how to get nginx to allow puma to talk to it would be very appreciated.

EDIT 1 nginx.conf

upstream puma {
  server unix:///home/my-user-name/apps/my-web-app/shared/tmp/sockets/my-web-app-puma.sock;
}

server {
  listen 80 default_server deferred;

  listen 443 ssl;

  # server_name example.com;
  ssl_certificate /etc/ssl/mysite/mysite.com.chained.crt;
  ssl_certificate_key /etc/ssl/mysite/mysite.key;

  root /home/my-user-name/apps/my-web-app/current/public;
  access_log /home/my-user-name/apps/my-web-app/current/log/nginx.access.log;
  error_log /home/my-user-name/apps/my-web-app/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_pass http://puma;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 10M;
  keepalive_timeout 10;
}

Actually, let me answer this without requesting your nginx configuration. Your setup works like this:

  • nginx listens on port 80 for incoming HTTP requests
  • based on the configuration it will forward these requests to the correct application instance.
  • this is called a reverse proxy setup.

So let's look at a generic nginx configuration that will tell us how to listen on port 80 and forward all requests to an application running on port 3000:

# our http block to handle HTTP traffic with nginx
http {
  include mime.types;
  default_type  application/octet-stream;
  sendfile on;
  keepalive_timeout  65;

  # NGinx Server Configuration
  server {

    listen 80; #listen on port 80
    server_name my.domain.com;  # which domain we are listening for.

    # Add some basic auth
    # Remove this if not needed.
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;

    # Set up the location to map all requests to the Ruby App
    location / {
      proxy_pass http://127.0.0.1:3000;
      access_log off;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
  }
}

Now you need to do 2 things:

  • restart your nginx
  • start your puma application on port 3000

Hope this explains how the 2 work together and what you need to change in your file to help them communicate.

basically: if nginx claims port 80, puma cannot claim it and needs to run on a different port, letting nginx reroute all traffic to that port and back.

In your puma.rb file you should remove the line about the port. Since you are already using a sock in the configuration, there is no reason to run puma on a tcp port too.

When you start puma with:

puma -C config/puma.rb

you should only see "Listening on unix:", not on tcp:

在此处输入图片说明

In a nutshell, you should run puma on a unix socket and not on a tcp port too. Just comment the port directive.

在此处输入图片说明

Once you do that, it should work. And by the way, you should be permissive on selinux because selinux will disable the socket and you will end up seeing the message "403 Forbidden"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM