DEV Community

Maddy
Maddy

Posted on

Fixing WebSocket Failures in Production on SiteGround: A Practical Guide

Why WebSocket Fails in Production on SiteGround

If your WebSocket connection fails in production on SiteGround, you’re not alone. The error you’re seeing—WebSocket is closed before the connection is established—typically means the WebSocket handshake is failing, often due to SSL, port, or server configuration issues. SiteGround’s shared hosting environment is not optimized for raw WebSocket traffic by default, but that doesn’t mean it’s impossible. Let’s walk through the root causes and how to fix them.

Root Cause #1: Missing SSL Certificates in the Expected Path

Your code assumes that /etc/ssl/privkey.pem and /etc/ssl/fullchain.pem exist on SiteGround. In reality, SiteGround Shared and Cloud hosting customers don’t have direct access to /etc/ssl. Those paths are internal to server management and not exposed to your application. This is why fs.readFileSync() fails—it can’t find the files.

Instead, SiteGround uses Let’s Encrypt for SSL certificates, but they’re stored in a managed location that you cannot read directly from your Node.js app. Even if you use SSH to browse the filesystem, you won’t see them in a standard user-accessible path.

Root Cause #2: WebSocket Ports Are Blocked by Default

SiteGround blocks most high ports (like 6001, 7001, 8080, etc.) in shared hosting environments to prevent abuse. WebSocket traffic typically runs on non-standard ports, and these are often closed unless explicitly opened via support tickets or custom server configurations.

When you try to connect to mydomain.com:6001, the connection is rejected by the firewall before it even reaches your app.

Root Cause #3: WebSocket Transport Not Properly Negotiated

Even if the port is open and SSL is configured, the WebSocket upgrade request may fail if:

  • The server is not sending the correct Upgrade: websocket header.

  • The client is forcing WebSocket transport, but the server is falling back to polling.

  • CORS policies block the WebSocket connection.

Your client-side code specifies transports: ["websocket"], which forces WebSocket. If the server can’t upgrade the connection, the fallback to polling may also fail if CORS isn’t correctly configured.

Solution: Host WebSocket on Port 443 with HTTPS Forwarding

Since SiteGround blocks non-standard ports and manages SSL certificates centrally, the best workaround is to use port 443 (HTTPS default) for WebSocket traffic. This avoids firewall issues and leverages SiteGround’s managed SSL certificates automatically.

Step 1: Use HTTPS with Port 443 for WebSocket

Modify your server code to listen on port 443 and route WebSocket traffic through it. Socket.IO supports running over standard HTTPS/443 ports.

Update your server code:

import { createServer } from "https";
import { Server } from "socket.io";
import { readFileSync } from "fs";

// No need to manually load SSL files—SiteGround handles it
const server = createServer({
// Let SiteGround's internal SSL handler take care of the certificate
});

// Note: We don't pass key/cert directly anymore
// SiteGround uses SNI-based SSL termination at the proxy level

const io = new Server(server, {
cors: {
origin: ["https://mydomain.com", "https://www.mydomain.com"],
credentials: true,
},
transports: ["websocket"], // Keep forcing websocket for efficiency
});

io.on("connection", (socket) => {
console.log("✅ Client connected:", socket.id);
});

// Listen on port 443 (requires root privileges; use port 8443 if on Shared hosting)
const PORT = process.env.NODE_ENV === "production" ? 8443 : 443;
server.listen(PORT, () => {
console.log(⚡ Socket.IO server running on port ${PORT});
});


**Important:** On SiteGround Shared hosting, you cannot bind to port 443 directly unless youre on a Cloud or dedicated plan with root access. For shared hosting, use **port 8443**a common alternative that SiteGround allows for SSL traffic.

Update your client connection accordingly:

const socket = io("https://mydomain.com:8443", {
  withCredentials: true,
  auth: payload,
  transports: ["websocket"],
});

Enter fullscreen mode Exit fullscreen mode

Step 2: Update CORS to Use HTTPS Origins

Make sure your CORS configuration includes the correct HTTPS origin. SiteGround enforces HTTPS on all sites via Let’s Encrypt, so the origin must be https://mydomain.com, not http://.

Change:

origin: isLocal ? ["http://localhost:5173"] : ["mydomain.com"]

To:

origin: isLocal ? ["http://localhost:5173"] : ["https://mydomain.com", "https://www.mydomain.com"]

Step 3: Ensure Your DNS Points to SiteGround Correctly

Confirm that your domain’s A records point to SiteGround’s server IP (found in SiteGround’s Customer Area > Site > Site Information). Misconfigured DNS can cause SSL handshake failures even with correct WebSocket setup.

Step 4: Handle Reverse Proxy Properly

SiteGround runs behind a reverse proxy (Nginx or Apache). To allow WebSocket traffic through, you may need to configure a custom Nginx rule. Since you don’t control the web server directly on shared hosting, file a support ticket with SiteGround:

  • Request: "Enable WebSocket support for port 8443 with upgrade headers."

  • Include: Your domain and application purpose.

  • Note: SiteGround support can add a custom Nginx snippet like:

location /socket.io/ {
proxy_pass http://localhost:8443;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

This ensures WebSocket upgrade headers are passed correctly.

Testing and Debugging Tips

Test Locally First

Run your server locally with NODE_ENV=production to catch syntax errors or missing dependencies:

Local HTTPS test

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
node server.js




Then connect from your client (e.g., `https://localhost:443`) to verify the WebSocket path works.

### Use Browser DevTools

Open Developer Tools > Network tab and check the `Socket.IO` connection. Look for:

- Status code: Should be `101 Switching Protocols` after upgrade.

- Headers: Ensure `Upgrade: websocket` and `Connection: Upgrade` are present.

- WebSocket URL: Should be `wss://mydomain.com:8443/socket.io/?EIO=4&transport=websocket`

### Check Firewall Logs (via Support)

Ask SiteGround support to check if port 8443 is open and if any outgoing WebSocket traffic is being blocked. On shared hosting, you rely entirely on their configuration.

## Alternative: Use a Reverse Proxy with Standard Ports

If port 8443 is still problematic, consider using SiteGround’s Apache server to proxy WebSocket traffic internally. Use a standard path like `/ws` that maps to your Node.js app on another port (e.g., 3000).

Example Apache config (SiteGround can add this):

`<Location /ws>
  ProxyPass http://localhost:3000/socket.io/
  ProxyPassReverse http://localhost:3000/socket.io/
  RewriteEngine on
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteCond %{HTTP:Connection} upgrade [NC]
  RewriteRule ^/?(.*) "ws://localhost:3000/socket.io/$1" [P,L]
</Location>
`

Then connect your client to:

`const socket = io("https://mydomain.com/ws", {
  transports: ["websocket"],
});
`

This leverages standard HTTPS and avoids port restrictions entirely.

## Final Checklist

-  WebSocket server runs on port 8443 (or via reverse proxy).

-  CORS origin uses `https://`, not `http://`.

-  DNS is correct and SSL is active (check via `https://sslshopper.com`).

-  SiteGround support confirmed WebSocket support and Nginx proxy rules.

-  Client connects to `wss://mydomain.com:8443` (not `ws://`).

## FAQ

  ### Can I use WebSocket on SiteGround Shared Hosting?



      Yes, but with limitations. You cannot bind directly to port 443 without root access, and non-standard ports like 6001 are blocked by default. The recommended approach is to use port 8443 with SSL and request WebSocket support via SiteGround support. Alternatively, proxy WebSocket traffic through Apache/Nginx on standard paths like `/ws`.




  ### Why does my WebSocket connection fail with `Error during WebSocket handshake`?



      This usually means the server did not return a `101 Switching Protocols` response. On SiteGround, this happens when:



        - The port is blocked by firewall.

        - The reverse proxy (Nginx/Apache) lacks `Upgrade` header handling.

        - SSL is misconfigured or missing.



      Fix by using port 8443 with support-approved Nginx rules and HTTPS origins.




  ### Do I need to manually manage SSL certificates on SiteGround?



      No. SiteGround automatically provisions and renews Let’s Encrypt certificates for your domain. You should never manually read `privkey.pem` or `fullchain.pem` in your app. Instead, configure your HTTPS server to use the managed certificate via SiteGround’s internal proxy, and bind to port 8443.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)