# Troubleshoot WebSocket Connection Issues

The Bindplane console uses a persistent WebSocket (WSS) connection to stream live telemetry data, agent status updates, and configuration rollout progress. If your corporate network, proxy, or load balancer blocks or drops WebSocket connections, the UI will appear to load but live data will not update.

{% hint style="warning" %}
Bindplane requires WebSocket support. There is no HTTP long-poll or SSE fallback. If WebSocket connections cannot be permitted, the console cannot function correctly.
{% endhint %}

### Symptoms

* The browser console shows WebSocket connection errors such as `WebSocket connection to 'wss://...' failed` or `Error during WebSocket handshake`
* The Bindplane UI loads the page shell but displays a persistent spinner or "disconnected" banner
* Agent status, live preview, and rollout progress do not update
* Refreshing the page temporarily shows data, but it stops updating within seconds
* The same problem occurs in multiple browsers (Chrome, Firefox, Safari) on the same machine or network

### Root Causes

| Root cause                                        | Description                                                                                             |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Corporate proxy/firewall drops WebSocket upgrades | The proxy intercepts the HTTP `Upgrade` request and returns an error instead of forwarding it           |
| Load balancer not configured for WebSocket        | The LB strips the `Connection: Upgrade` and `Upgrade: websocket` headers before reaching the server     |
| Proxy/LB idle timeout too short                   | WebSocket connections are long-lived; a short idle timeout causes the proxy to terminate the connection |
| HTTP/2 protocol on AWS ALB                        | WebSocket requires HTTP/1.1; using HTTP/2 on the listener prevents the protocol upgrade                 |

### Diagnosis

#### Step 1: Check browser DevTools

1. Open your browser's developer tools (F12 or Cmd+Option+I).
2. Go to the **Network** tab and filter by **WS** (WebSocket).
3. Reload the Bindplane console.
4. Look for a WebSocket connection attempt to your Bindplane host (the URL will end in `/v1/ws` or similar).

Interpret the status column:

| Status                          | Meaning                                                                   |
| ------------------------------- | ------------------------------------------------------------------------- |
| **101 Switching Protocols**     | Connection succeeded — the problem is elsewhere                           |
| **502 Bad Gateway**             | The proxy or load balancer is refusing to forward the WebSocket upgrade   |
| **503 Service Unavailable**     | The upstream server is unreachable or the LB has no healthy targets       |
| **Connection failed / blocked** | The firewall or proxy is dropping the connection before any HTTP response |

#### Step 2: Test the WebSocket upgrade with curl

Run this command from a machine on the same network as the browser, replacing `<bindplane-host>` with your Bindplane server hostname:

```bash
curl -i -N \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Version: 13" \
  https://<bindplane-host>/v1/ws
```

**Expected output** — the server accepts the upgrade:

```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ...
```

**Problem output** — a proxy or LB is rejecting the upgrade:

```
HTTP/1.1 502 Bad Gateway
...
```

#### Step 3: Isolate client network vs. server

Run the same `curl` command from:

1. A machine **on the corporate network** (the network the browser is on)
2. A machine **outside the corporate network** (for example, a cloud shell or a personal hotspot)

| Scenario                                            | Likely location of the problem                                                       |
| --------------------------------------------------- | ------------------------------------------------------------------------------------ |
| Fails from corporate network, succeeds from outside | Corporate proxy, firewall, or VPN is blocking WebSocket                              |
| Fails from both locations                           | Load balancer or server-side misconfiguration                                        |
| Succeeds from both locations                        | Problem is browser-specific — check browser extensions or per-browser proxy settings |

### Resolutions

#### Configure nginx to pass WebSocket headers

If nginx is acting as a reverse proxy in front of Bindplane, add the following to the `location` block that proxies to Bindplane:

```nginx
location / {
    proxy_pass          http://bindplane_backend;
    proxy_http_version  1.1;

    # Required for WebSocket upgrade
    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;

    # Allow long-lived WebSocket connections (1 hour)
    proxy_read_timeout  3600s;
    proxy_send_timeout  3600s;
}
```

After editing, reload nginx:

```bash
sudo nginx -t && sudo systemctl reload nginx
```

#### Configure HAProxy to pass WebSocket headers

Add a `use_backend` rule and a dedicated backend for the Bindplane host:

```haproxy
frontend bindplane_front
    bind *:443 ssl crt /etc/haproxy/certs/bindplane.pem
    default_backend bindplane_back

backend bindplane_back
    option http-server-close
    option forwardfor

    # Enable WebSocket tunneling
    timeout tunnel  3600s

    server bindplane1 bindplane.internal:3001 check
```

{% hint style="info" %}
`timeout tunnel` controls how long HAProxy keeps an established WebSocket connection alive. Set it to at least `3600s` (1 hour) to prevent premature disconnects.
{% endhint %}

#### Increase the proxy idle timeout

WebSocket connections between the Bindplane console and server are long-lived — a connection can stay open for the entire browser session. If your proxy or load balancer has a short idle timeout (for example, 60 seconds), it will terminate the connection and the UI will appear to freeze or disconnect.

Set the idle or tunnel timeout to at least **3600 seconds (1 hour)** on whichever proxy layer sits between the browser and Bindplane.

#### If WebSocket cannot be unblocked

Some organizations cannot permit WebSocket traffic through their network security controls. In that case:

* Work with your network or security team to add an exception for the Bindplane console hostname on port 443 (WSS).
* Allowlist the specific upgrade path: requests with the `Upgrade: websocket` header destined for `<bindplane-host>`.

{% hint style="warning" %}
There is no HTTP long-poll or fallback transport in Bindplane. If WSS traffic is permanently blocked, the console cannot deliver live updates and certain features (live preview, rollout progress) will not function.
{% endhint %}

### Cloud-Specific Notes

#### AWS Application Load Balancer (ALB)

AWS ALB supports WebSocket, but it requires **HTTP/1.1** on the listener protocol. HTTP/2 does not support the WebSocket upgrade mechanism.

1. In the AWS Console, navigate to **EC2 → Load Balancers → \[your ALB] → Listeners**.
2. Confirm the listener protocol is **HTTP** or **HTTPS** (not HTTP/2 or gRPC).
3. Check that the target group's **Protocol** is **HTTP** or **HTTPS** (not HTTP/2).
4. Verify the listener rules route traffic to the correct target group.

AWS ALB automatically handles the `Connection: Upgrade` / `Upgrade: websocket` headers — no additional header configuration is required once HTTP/1.1 is confirmed.

#### GCP Cloud Load Balancing

GCP HTTP(S) load balancers support WebSocket by default on backend services. No additional configuration is required for the WebSocket upgrade itself.

Ensure the backend service's **timeout** is long enough to keep WebSocket connections alive:

1. In the Google Cloud Console, navigate to **Network services → Load balancing → \[your load balancer] → Backend services**.
2. Set **Timeout** to at least `3600` seconds.

#### Azure Application Gateway

Azure Application Gateway requires WebSocket to be explicitly enabled:

1. In the Azure Portal, navigate to your **Application Gateway**.
2. Select **Settings → HTTP settings** (or the relevant backend HTTP setting).
3. Enable **WebSocket** (the toggle is labeled "WebSocket enabled").
4. Set the **Request timeout** to at least `3600` seconds to prevent idle disconnections.

{% hint style="info" %}
Azure Front Door and Azure API Management have their own WebSocket settings. Refer to your Azure documentation if you are using those services in front of Bindplane.
{% endhint %}

### Getting Help

If you have worked through the steps above and WebSocket connections are still failing, contact [Bindplane Support](https://support.bindplane.com) and include:

* The output of the `curl` WebSocket upgrade test from both inside and outside the corporate network
* Your proxy or load balancer type and version
* The HTTP status code and response headers from the failed WebSocket handshake (from browser DevTools)
* A description of the network path between the browser and the Bindplane server (VPN, corporate proxy, cloud LB, etc.)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bindplane.com/how-to-guides/infrastructure-and-operations/troubleshoot-websocket-connection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
