skip to Main Content

In MacOS, I usually run my project in localhost by sudo PORT=443 HTTPS=true ./node_modules/.bin/react-scripts start. As a result, https://localhost/#/start works in a browser.

Now, to run third-party authentications in localhost, I need to run nginx. Here is my /usr/local/etc/nginx/nginx.conf:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    upstream funfun {
        server 178.62.87.72:443;
    }

    server {
        listen              443 ssl;
        server_name localhost;
        ssl_certificate /etc/ssl/localhost/localhost.crt;
        ssl_certificate_key /etc/ssl/localhost/localhost.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_session_timeout 1d;
        ssl_stapling off;
        ssl_stapling_verify off;
        add_header Strict-Transport-Security max-age=15768000;
        add_header X-Frame-Options "";
        proxy_ssl_name "www.funfun.io";
        proxy_ssl_server_name on;

        location ~ /socialLoginSuccess {
            rewrite ^ '/#/socialLoginSuccess' redirect;
        }

        location ~ /auth/(.*) {
            proxy_pass  https://funfun/10studio/auth/$1?$query_string;
            proxy_set_header Host localhost;
        }

        location / {
            proxy_set_header    Host                $host;
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto   $scheme;
            proxy_set_header    Accept-Encoding     "";
            proxy_set_header    Proxy               "";
            proxy_pass          https://localhost/;
            # These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove socketio error
            proxy_http_version 1.1;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "upgrade";
        }
    }
    include servers/*;
}

However, launching the nginx returns me the following errors:

$ sudo nginx
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:443 failed (48: Address already in use)
nginx: [emerg] still could not bind()

It seems that, nginx has conflit with the app running on 443. Does anyone know why?

Additionally, could anyone tell me what’s the purpose of the block location / { ... } in my nginx configuration file?

2

Answers


  1. Any port can be bound once to given interface. Now, if you run your react application server and it already bind port 443 on interface 0.0.0.0 which in this case is used as kind of wildcard which means "listen on port 443 on all interfaces on my computer" then any other application can’t use this port because is already taken. In your nginx configuration you can see line which says that it also want to use port 443:

    server {
        listen              443 ssl;  #<--- this is port config
        server_name localhost;
    

    You have (at least) 2 choices to fix that error:

    • change PORT=443 in your local application
    • change line with port numer in nginx configuration to any other not occupied

    Next – location / { ... } means that all request starting from / which are virtually all requests except these catched in the two previous location blocks, will be forwarded to another web server located at https://localhost/ with some additional headers. This is called reverse proxy.

    Login or Signup to reply.
  2. Only one application can bind/listen on a given port at a time.

    You started your app running on port 443:
    sudo PORT=443 HTTPS=true ./node_modules/.bin/react-scripts start

    Then when you tried to start nginx also on port 443 it fails because your app is already using 443.

    To fix this:

    • stop nginx
    • stop your app and restart it running on a different port (e.g. 3000):
      • sudo PORT=3000 HTTPS=true ./node_modules/.bin/react-scripts start
    • edit your nginx config to tell nginx that your app ("upstream") is running on port 3000 now.
      • proxy_pass https://localhost:3000;
    • start nginx

    Additionally, I would suggest that you do SSL (https) termination on nginx and let nginx connect to your app on localhost insecurely to reduce other problems. Currently it looks like you are doing ssl termination on nginx and then another ssl connection/termination to your app/upstream. This really isn’t necessary when connecting on localhost or over a secure/private network (e.g. within AWS VPC).

    • stop nginx
    • stop your app and restart it running on a different port (e.g. 3000):
      • remove HTTPS=true from sudo PORT=3000 HTTPS=true ./node_modules/.bin/react-scripts start
      • …and any other changes needed in your react app to disable ssl/https.
    • edit your nginx config to tell nginx that your app ("upstream") is running on port 3000 now and insecure (change https to http).
      • proxy_pass http://localhost:3000;
    • start nginx

    For production you should really always run nginx in front of your apps. This allows you to easily do ssl termination, load balancing (multiple apps/upstreams) as well as serving static files (jpg, css, etc) without running through nodejs or other application server. It will scale better. Right tool for the right job.

    For local development purposes you can just work against the local insecure http://localhost:3000. If you really hate using port 3000 for some reason then you can of course change that using NODE_ENV in tandem with dotenv or similar in order to switch the port your app uses when in development mode vs production. There really isn’t any reason you need to use https/443 on localhost during development. You won’t be able to get a trusted SSL cert for localhost so there really isn’t any point…it just makes your life more difficult.

    I have no issues testing oauth login flows against http://localhost:3000 with google for instance.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search