#3470·h2o

Firefox, Websockets, HTTP/2 & connection failures

Author: toastalCreated Mar 26, 2025Updated Jun 13, 2026

I have a tunneled connection to a Rachet (PHP) socket with a relevant config of

yaml
compress: 'ON'
limit-request-body: 4294967296
ssl-offload: kernel
hosts:
  social.toastal.in.th:443:
    file.custom-handler:
      extension:
      - .php
      fastcgi.connect:
        port: /run/phpfpm/movim.sock
        type: unix
      fastcgi.document_root: /nix/store/l80hivxkdqjbw5qh12w962q4rfjab0mw-movim-0.29.2
    listen:
    - port: 443
      ssl:
        identity:
        - certificate-file: /var/lib/acme/toastal.in.th/fullchain.pem
          key-file: /var/lib/acme/toastal.in.th/key.pem
    paths:
      /:
        file.dir: /nix/store/l80hivxkdqjbw5qh12w962q4rfjab0mw-movim-0.29.2/share/php/movim/public
        file.index:
        - index.php
        - index.html
        file.send-compressed: 'ON'
        header.set:
        - 'Content-Security-Policy: default-src ''self''; img-src ''self'' aesgcm:
          data: https:; media-src ''self'' aesgcm: https:; script-src ''self'' ''unsafe-eval''
          ''unsafe-inline''; style-src ''self'' ''unsafe-inline'''
        redirect:
          internal: 'YES'
          status: 307
          url: /index.php/
      # ↓↓↓ WEBSOCKET PATH HERE ↓↓↓
      /ws/:
        proxy.preserve-host: 'ON'
        proxy.reverse.url: http://127.0.0.1:8080/
        proxy.tunnel: 'ON'

The behavior is that Chromium connects fine (101 Connection) after a bit of a connection delay, but Firefox eventually fails out with a 400 & no body.

Disabling HTTP/2 on the server via Fx’s about:config with network.http.http2.enabled or network.http.http2.enabled set to false gives the desired 101. Fiddling with the other proxy values doesn’t seem to help (or makes things worse & Chromium doesn’t connect). Disabling ad blocking + tracking protection in Fx did nothing.

Seems other projects have had or still have issues in this space:

With upstream issue:


Problematic URL in production: https://social.toastal.in.th

echo | websocat --origin "https://social.toastal.in.th" "wss://social.toastal.in.th/ws/?path=login&offset=0" seems fine.


According to the Jetty issue’s final comment, HTTP/2 for these sorts of connections for Gecko (Firefox, LibreWolf, & so on) are disabled. Mozilla forums suggest disabling HTTP/2 on websockets (meaning network.http.http2.websockets = false).

Having workarounds for possible bugs in browsers via UA detection is problematic, but so would be suggesting to users to poke around about:config. Perhaps there is an mruby solution I don’t know how to solve it (not an HTTP expert). There also aren’t ways to say selectively disable HTTP/2+ on a specific path such as

yaml
/ws/:
  maximum-http-version: 1.1
  proxy.preserve-host: 'ON'
  proxy.reverse.url: http://127.0.0.1:8080/
  proxy.tunnel: 'ON'

tho this could have a negative experience for non-Gecko-based browsers. I’m not really sure what the solution is.


I do apologize if this is my own misconfiguration issue. I did have this socket working prior on Nginx & trying to migrate. Maybe at least if it is a dumb misconfiguration, the issue can help.