Hey folks,
I’ve been building a BLE visualization project where an ESP32 scans for Bluetooth devices and sends the data to a Node.js server hosted on Fly.io. The server then broadcasts to browser clients via Socket.IO. The browser connections work perfectly - it’s just the ESP32 → Fly.io leg that’s failing.
The Setup:
-
ESP32 (Arduino) scanning BLE devices
-
Browser visualizer connecting via Socket.IO (works great)
-
ESP32 attempting to connect via WebSocket over TLS (fails)
What I’ve tried:
- WebSocket with SSL using
WebSocketsClientlibrary:
webSocket.beginSSL("data.MYURL.com", 443, "/esp32");
Result: Silently fails, no connection, no error events fired.
- WebSocket with CA certificate:
webSocket.beginSslWithCA(host, port, path, NULL, "");
Result: Same silent failure.
- Basic HTTPS test to isolate the issue:
HTTPClient http;
http.begin("https://data.MYURL.com/esp32");
int code = http.GET();
Serial.printf("HTTPS test result: %d\n", code);
Result: Returns -1 - the ESP32 cannot establish ANY TLS connection to Fly.io.
- Verified Fly.io config has
h2_backend = falseto force HTTP/1.1:
[http_service.http_options]
h2_backend = false
- Tested WebSocket upgrade works from curl with HTTP/1.1:
curl -i -N --http1.1 \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" \
https://data.MYURL.com/esp32
Result: Returns 101 Switching Protocols - so the server-side is working correctly.
The conclusion:
The ESP32’s embedded TLS stack (mbedTLS) cannot complete a TLS handshake with Fly.io’s edge proxy. Browser clients and curl work fine because they use modern, full-featured TLS implementations. The ESP32’s lightweight embedded crypto library seems incompatible with something in Fly’s TLS configuration (cipher suites? ALPN negotiation? SNI handling?).
My workaround:
I’m implementing an HTTP POST /ingest endpoint as a fallback. The ESP32 will POST batched device data every 500ms instead of using WebSocket. Not as elegant, but it should work since even basic HTTPS fails.
Questions for the community:
-
Has anyone successfully connected an ESP32 (or similar microcontroller) directly to a Fly.io app over TLS/WSS?
-
Is there a specific TLS configuration on Fly’s edge that could be tweaked to support embedded clients?
-
Are there any Fly.io settings I’m missing that might help with mbedTLS compatibility?
Any insights appreciated. Happy to share more details about my setup if it helps debug this.
Environment:
-
ESP32 Dev Module
-
Arduino framework
-
WebSocketsClient library
-
Fly.io with Node.js 18