Websocket connection to admin console (adminws) is failing

I enabled the Admin console and open it at https://$MYSERVER/loleaflet/dist/admin/admin.html. I get the error message “Der Server wurde heruntergefahren, bitte laden Sie die Seite neu.” (“Server has been shut down; please reload the page.”).

In the browser console (Chromium, Debian Testing) I see:

WebSocket connection to 'wss://$MYSERVER/lool/adminws/' failed

I also tried incognito mode and Firefox.

I installed the CODE Debian packages, loolwsd has version 6.4.10-4. The Apache config is exactly as described for Apache (terminating):
https://sdk.collaboraonline.com/docs/installation/Proxy_settings.html#reverse-proxy-settings-in-apache2-config-ssl-termination

The Apache access log shows a 400 HTTP error:

"GET /lool/adminws/ HTTP/1.1" 400 717 "-"

loolwsl.xml (stripped and redacted):

<ssl>
  <enable>false</enable>
  <termination>true</termination>
  <cert_file_path relative="false">/etc/loolwsd/cert.pem</cert_file_path>
  <key_file_path relative="false">/etc/loolwsd/key.pem</key_file_path>
  <ca_file_path relative="false">/etc/loolwsd/ca-chain.cert.pem</ca_file_path>
  <cipher_list />
  <hpkp enable="false" report_only="false">
    <max_age enable="true">1000</max_age>
    <report_uri enable="false"/>
    <pins>
      <pin/>
    </pins>
  </hpkp>
</ssl>
<admin_console>
  <enable>true</enable>
  <enable_pam>false</enable_pam>
  <username>REDACTED</username>
  <password />
  <secure_password>REDACTED</secure_password>
</admin_console>

This is shown in the loolwsd logs when the websocket request comes in:

[ websrv_poll ] INF #30: Client HTTP Request: GET /lool/adminws/ HTTP/1.1 / Host: $MYHOST/REDACTED / Pragma: no-cache / Cache-Control: no-cache / User-Agent: REDACTED / Origin: $MYHOST/REDACTED / Sec-WebSocket-Version: 13 / Accept-Encoding: gzip, deflate, br / Accept-Language: de,en-US;q=0.9,en;q=0.8,ro;q=0.7 / Sec-WebSocket-Key: REDACTED / Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits / X-Forwarded-For: REDACTED / X-Forwarded-Host: REDACTED / X-Forwarded-Server: REDACTED / Connection: Keep-Alive| net/Socket.cpp:903
[ websrv_poll ] INF Handling request: /lool/adminws/| wsd/LOOLWSD.cpp:2557
[ websrv_poll ] INF Admin request: /lool/adminws/| wsd/LOOLWSD.cpp:2596
[ websrv_poll ] INF Admin::handleInitialRequest bad request| wsd/Admin.cpp:378

So this if condition in wsd/Admin.cpp#L364 is not true:

if (request.find("Upgrade") != request.end() && Util::iequal(request["Upgrade"], "websocket"))

However I double checked in the Browser console that the request sends the Upgrade header (with uppercase ‘U’) with value “websocket”. I even changed the Apache config to explicitly set the Upgrade header in case it gets lost:

  <Location "/lool/adminws">
    ProxyPass ws://127.0.0.1:9980/lool/adminws
    RequestHeader set Upgrade websocket
  </Location>

The websocket requests to /lool/(.*)/ws/lool/(.*)/ws work.

Duplicate issue report in this forum:

I opened a GitHub issue: