Friday, 30 April 2021

Deploying React/Node.js Application: SSL_PROTOCOL_ERROR

I'm trying to deploy a full-stack React/Node.js web app with Letsencrypt to production on an Ubuntu 20.04 LTS server. I've built the client and the web page is rendering over https with no problem. The issue arises when I try to make a POST request to the backend.

The React client is running on example.com:3000.
The Node.js server is running on example.com:9000.

When I trigger a call to the backend, e.g. example.com:9000/signIn to get the user's credentials and sign them in, I get 2 errors in my browser console:

POST https://example.com:9000/signIn net::ERR_SSL_PROTOCOL_ERROR coming from one of my React components as well as this error: Uncaught (in promise) TypeError: Failed to fetch.

When I tail the nginx logs, all I see are GET requests loading my front end files/content. Also when I run my node.js server, all I see are logs I left in the application to show that the database is connected successfully. I'm expecting to see some logs indicating whether the user was authenticated or not.

Nginx configuration in /etc/nginx/sites-enabled/example.com:

server {
         root /home/ubuntu/apps/mysite/client/build;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name example.com www.example.com;

        location / {
                try_files $uri /index.html;
        }

         location /server {
            proxy_pass https://localhost:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        listen [::]:80;

        server_name example.com www.example.com;
    return 404; # managed by Certbot
}

package.json in /server:

{
  "name": "server",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "bcrypt": "^4.0.1",
    "bcryptjs": "^2.4.3",
    "constantinople": "^4.0.1",
    "cookie-parser": "~1.4.4",
    "cookie-session": "^1.4.0",
    "cors": "^2.8.5",
    "debug": "~2.6.9",
    "dotenv": "^8.2.0",
    "express": "~4.16.1",
    "express-session": "^1.17.1",
    "http-errors": "~1.6.3",
    "jade": "~1.11.0",
    "morgan": "~1.9.1",
    "mysql": "^2.18.1",
    "nodemailer": "^6.4.17",
    "passport": "^0.4.1",
    "passport-http-bearer": "^1.0.1",
    "passport-local": "^1.0.0"
  }
}

package.json in /client:

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "bootstrap": "^4.4.1",
    "chart.js": "^2.9.3",
    "cors": "^2.8.5",
    "d3": "^6.2.0",
    "moment": "^2.29.1",
    "morris.js.so": "^0.5.1",
    "node-sass": "^4.14.1",
    "perm": "^1.0.0",
    "react": "^16.13.1",
    "react-bootstrap": "^1.0.1",
    "react-chartkick": "^0.4.1",
    "react-dom": "^16.13.1",
    "react-facebook-login": "^4.1.1",
    "react-feather": "^2.0.4",
    "react-google-login": "^5.1.10",
    "react-router-dom": "^5.2.0",
    "react-scripts": "^3.4.3",
    "react-timeline-range-slider": "^1.1.2",
    "recharts": "^1.8.5",
    "universal-cookie": "^4.0.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "build-localhost": "PUBLIC_URL=/ react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "homepage": "https://example.com",
  "proxy": "https://example.com:9000",
  "devDependencies": {
    "dotenv-webpack": "^7.0.2",
    "morris.js": "^0.5.0",
    "raphael": "^2.3.0"
  }
}

Confirming that node.js is in fact listening on port 9000:
bin/www in /server:

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '9000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

I should note the entire web app is working locally with no issue. I've gone through a number of video tutorials and Stack Overflow answers several times and I've confirmed ufw is configured to allow the necessary ports/traffic and at this point I am out of ideas. Any suggestions on what I'm doing wrong highly appreciated.



from Deploying React/Node.js Application: SSL_PROTOCOL_ERROR

No comments:

Post a Comment