React app SSL error on internal port

Deployed react app and getting this error in the console:

WebSocket connection to ‘wss://mysite.net:3000/ws’ failed: An SSL error has occurred and a secure connection to the server cannot be made.

Everything works fine, just getting the error. (Same as this post but no answers there: Express and React app: WebSockets Error).

I have a Shared v4 IP pointed to by my AWS domain in the A record. https works fine. Again, everything works great aside from this error in the console.

Here’s my Dockerfile:

# syntax = docker/dockerfile:1

# Adjust BUN_VERSION as desired
ARG BUN_VERSION=1.0.18
FROM oven/bun:${BUN_VERSION}-slim as base

LABEL fly_launch_runtime="Bun"

# Bun app lives here
WORKDIR /app

# Set production environment
ENV NODE_ENV="production"


# Throw-away build stage to reduce size of final image
FROM base as build

# Install packages needed to build node modules
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python

# Install node modules
COPY bun.lockb package-lock.json package.json ./
RUN bun install

# Copy application code
COPY ./src ./src
COPY ./public ./public

# Build application
RUN bun run build

# Remove development dependencies
RUN rm -rf node_modules && \
    bun install --ci


# Final stage for app image
FROM base

# Copy built application
COPY --from=build /app /app

# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD [ "bun", "run", "start" ]

And here’s my fly.toml:

app = "trivai-client"
primary_region = "sjc"

[build]

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1
  processes = ["app"]

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 1024

You shouldn’t use the internal port (3000), you’ll need to use the normal https port (443).

Thanks for the response but that didn’t work. I changed EXPOSE to 443 in the Dockerfile and internal_port to 443 in fly.toml and site became unreachable.

It seems to be a bug in react-scripts:

I added ENV WDS_SOCKET_PORT=0 to the Dockerfile and error is gone. (Kept internal port at 3000).

Yeah you wouldn’t make the internal port 443. That should be kept at 3000 since thats what your server broadcasts at. When you connect in a browser, you shouldn’t include that port. Fly is mapping port 3000 in your app to port 443 publicly, so port should never need to be entered to connect.

So basically:

If connecting locally → connect to ws://localhost:3000/ws
If connecting after deployment → connect to was://domain.tld/ws
Your fly.toml and docker file should expose port 3000

Just to clarify, Jerome’s suggestion was that you leave the Dockerfile and fly.toml alone, and remove :3000 from wss://mysite.net:3000/ws (or replace it with 433).

A few additional notes:

  • CRA seems to be abandoned. It hasn’t been updated for nearly two years. The nearest equivalent seems to be Vite. Or you can go for a more complete framework like Next.JS or Remix.
  • With CRA, you are expected to run your development server and production server differently. There is no need for Hot Reload in production, and therefore no websocket. See: Creating a Production Build | Create React App. Of course you can pair your CRA app with an express or fastify app, and that app can have a websocket.

Not sure we are all on the same page. I was never putting wss://mysite.net:3000/ws in my browser. That’s just what’s in the error I was getting in the console when I go to the url https://mysite.com.

I think I see what you mean about using react-scripts start and hot reloading. I think I need to change that for production.

When you go to https://mysite.com, you are going to port 443. In your fly.toml, you map that to port 3000.

You are running react-scripts in development mode, and that creates a websocket for hot module reloading. It creates a URL for that purpose, and fills in the only port it knows, which is 3000.

There may be a way to influence how react-scripts generates a URL - I’m not sure, but the right fix in this case is to not create the websocket at all and run your app in production mode.

Make sense?

Yep. I’ll be changing production to run with nginx instead of react-scripts.

Also added this to fly.toml

[[services.ports]]
  port = 443
  handlers = ["tls", "http"]

Thanks for the help!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.