gotify / server

A simple server for sending and receiving messages in real-time per WebSocket. (Includes a sleek web-ui)
https://gotify.net
Other
11.53k stars 641 forks source link

Can't get Apache 2.4.38 proxy with sub path to upgrade to websocket #638

Closed pcwalden closed 8 months ago

pcwalden commented 8 months ago

Have you read the documentation?

You are setting up gotify in

Describe your problem

I am have trouble getting my Apache 2.4.38 reverse proxy with sub path to work. The WebUI works, but the websocket is showing the error:

2024-03-11T20:17:47-07:00 | 400 |     2.02339ms | 207.183.232.163 | GET      "/stream?token=[masked]"
Error #01: websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header

I have read the section on apache config and the troubleshooting section.

Any errors, logs, or other information that might help us identify your problem

I am using Apache/2.4.38 (Raspbian) on a RaspberryPi with Raspbian GNU/Linux 10 (buster). So the ProxyPass upgrade to websocket will not work and a rewrite rule is needed. However, I cannot get the apache to forward the Upgrade token.

The proper modules appear to be installed:

$ sudo apache2ctl -M | grep proxy
 proxy_module (shared)
 proxy_html_module (shared)
 proxy_http_module (shared)
 proxy_wstunnel_module (shared)

The abridged conf section is below:

<IfModule mod_proxy.c>
#
# Allow remote server configuration reports, with the URL of
#  http://servername/server-info (requires that mod_info.c be loaded).
# Uncomment and change the "192.0.2.0/24" to allow access from other hosts.
#
# <Location /gotify/stream >
    # Keepalive On
    # Redirect 301 "/gotify" "/gotify/"
    # The proxy must preserve the host because gotify verifies the host with the origin
    # for WebSocket connections
    ProxyPreserveHost On
    # Proxy web socket requests to /stream
    # ProxyPass ws://127.0.0.1:8055/stream retry=0 timeout=60
    RewriteEngine on
    # RewriteCond ${HTTP:Upgrade} websocket [NC]
    RewriteCond ${HTTP:Upgrade} =websocket
    #RewriteCond ${HTTP:Connection} Upgrade [NC]
    RewriteRule /gotify/stream(.*) ws://127.0.0.1:8055/stream$1 [P,L]
# </Location>

<Location /gotify/ >
    # Proxy all other requests to /
    ProxyPreserveHost On
    ProxyPass http://127.0.0.1:8055/ retry=0 timeout=5
    ProxyPassReverse http://127.0.0.1:8055/
</Location>

In case it helps, the response header on the stream request is:

HTTP/1.1 400 Bad Request
Date: Tue, 12 Mar 2024 17:20:58 GMT
Server: Apache/2.4.38 (Raspbian)
Content-Type: text/plain; charset=utf-8
Sec-Websocket-Version: 13
X-Content-Type-Options: nosniff
Content-Length: 180
Connection: close
jmattheis commented 8 months ago

Can you provide a full apache config that can reproduce the issue. Here is a docker-compose setup which works. You can use your config and see when it breaks. https://gist.github.com/jmattheis/4666058fae13397a26da7538bfd8577d

pcwalden commented 8 months ago

The docker setup you referenced contains:

    <Location /gotify/>
        ProxyPass http://server:80/ retry=0 timeout=60
        ProxyPassReverse "http://server:80/"
    </Location>

    <Location /gotify/stream>
        ProxyPass ws://server:80/stream retry=0 timeout=60
    </Location>

My understanding is that the

ProxyPass ws://server:80/stream retry=0 timeout=60

only works for apache 2.4.47+.

I have 2.4.38 and it would be very difficult to upgrade. For pre-2.4.47 versions you need to use the rewrite rule as cited in the Troubleshooting section of the documentation. However I cannot get it to work.

My config is distributed in multiple directories and would be difficult to compile into one file. Below is the whole proxy section.


$ cat conf-enabled/04_MyProxies.conf
<IfModule mod_proxy.c>
#
# Allow remote server configuration reports, with the URL of
#  http://servername/server-info (requires that mod_info.c be loaded).
# Uncomment and change the "192.0.2.0/24" to allow access from other hosts.
#
# <Location /gotify/stream >
    # Keepalive On
    # Redirect 301 "/gotify" "/gotify/"
    # The proxy must preserve the host because gotify verifies the host with the origin
    # for WebSocket connections
    ProxyPreserveHost On
    # Proxy web socket requests to /stream
    # ProxyPass ws://127.0.0.1:8055/stream retry=0 timeout=60
    RewriteEngine on
    # RewriteCond ${HTTP:Upgrade} websocket [NC]
    RewriteCond ${HTTP:Upgrade} =websocket
    #RewriteCond ${HTTP:Connection} Upgrade [NC]
    RewriteRule /gotify/stream(.*) ws://127.0.0.1:8055/stream$1 [P,L]
# </Location>

<Location /gotify/ >
    # Proxy all other requests to /
    ProxyPreserveHost On
    ProxyPass http://127.0.0.1:8055/ retry=0 timeout=5
    ProxyPassReverse http://127.0.0.1:8055/
</Location>

<Location /music/>
    ProxyPass http://walden9.local/
    ProxyPassReverse http://walden9.local/
</Location>

#<Location /music/>
    #ProxyPass http://walden3.homelinuxserver.org:8080/
    #ProxyPassReverse http://walden3.homelinuxserver.org:8080/
#</Location>
#
<Location /musicstream/>
    ProxyPass http://walden9.local:8000/
    ProxyPassReverse http://walden9.local:8000/
</Location>

#<Location /musicstream/>
    #ProxyPass http://walden4.homelinuxserver.org:8000/
    #ProxyPassReverse http://walden4.homelinuxserver.org:8000/
#</Location>
#
<Location /camnorth>
    ProxyPass http://DCS-930LB1_2832EF.local:8082
    ProxyPassReverse http://DCS-930LB1_2832EF.local:8082
</Location>

<Location /camsouthwest>
    ProxyPass http://DCS-930L_027D6F.local:8083
    ProxyPassReverse http://DCS-930L_027D6F.local:8083
</Location>

<Location /camfront>
    ProxyPass http://walden0.local:8084
    ProxyPassReverse http://walden0.local:8084
</Location>

<Location /cameast>
    ProxyPass http://waldend.local:8084
    ProxyPassReverse http://waldend.local:8084
</Location>

<Location /camnortheast>
    ProxyPass http://waldene.local:8084
    ProxyPassReverse http://waldene.local:8084
</Location>

<Location /camsouth>
    ProxyPass http://waldenf.local:8084
    ProxyPassReverse http://waldenf.local:8084
</Location>

<Location /camnorthwest>
    ProxyPass http://waldeng.local:8084
    ProxyPassReverse http://waldeng.local:8084
</Location>

<Location /ha>
    ProxyPass http://waldenb.local:8000/ha
    ProxyPassReverse http://waldenb.local:8000/ha
</Location>

</IfModule>
jmattheis commented 8 months ago

Using your version, my example still works. Please give me a working docker example. Without a full config I cannot reproduce this and I don't want to guess the possible configuration your setup has.

version: "3"
services:
  apache:
    image: httpd:2.4.38
    ports:
      - "12345:80"
    volumes:
      - ./httpd.conf:/usr/local/apache2/conf/httpd.conf
  server:
    image: gotify/server:2.4.0
    ports:
      - "8080:80"

Your apache version is 5 years old, it's not secure to use this version.

pcwalden commented 8 months ago

apache.conf.txt

Output of apache2ctl -DDUMP_CONFIG | grep -v '^ *#' >apache.conf.txt attached.

jmattheis commented 8 months ago

The link you provided is: 404 not found.

pcwalden commented 8 months ago

For some reason the add files is not working. Below is a copy paste

PidFile /var/run/apache2/apache2.pid
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
User www-data
Group www-data
HostnameLookups Off
ErrorLog /var/log/apache2/error.log
LogLevel warn
Alias /icons/ "/usr/share/apache2/icons/"
<Directory "/usr/share/apache2/icons">
  Options FollowSymlinks
  AllowOverride None
  Require all granted
</Directory>
IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* Charset=UTF-8
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip x-bzip2
AddIconByType (TXT,/icons/text.gif) text/*
AddIconByType (IMG,/icons/image2.gif) image/*
AddIconByType (SND,/icons/sound2.gif) audio/*
AddIconByType (VID,/icons/movie.gif) video/*
AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif /core
AddIcon (SND,/icons/sound2.gif) .ogg
AddIcon (VID,/icons/movie.gif) .ogm
AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^
AddIcon /icons/odf6odt-20x22.png .odt
AddIcon /icons/odf6ods-20x22.png .ods
AddIcon /icons/odf6odp-20x22.png .odp
AddIcon /icons/odf6odg-20x22.png .odg
AddIcon /icons/odf6odc-20x22.png .odc
AddIcon /icons/odf6odf-20x22.png .odf
AddIcon /icons/odf6odb-20x22.png .odb
AddIcon /icons/odf6odi-20x22.png .odi
AddIcon /icons/odf6odm-20x22.png .odm
AddIcon /icons/odf6ott-20x22.png .ott
AddIcon /icons/odf6ots-20x22.png .ots
AddIcon /icons/odf6otp-20x22.png .otp
AddIcon /icons/odf6otg-20x22.png .otg
AddIcon /icons/odf6otc-20x22.png .otc
AddIcon /icons/odf6otf-20x22.png .otf
AddIcon /icons/odf6oti-20x22.png .oti
AddIcon /icons/odf6oth-20x22.png .oth
DefaultIcon /icons/unknown.gif
ReadmeName README.html
HeaderName HEADER.html
IndexIgnore .??* *~ *# RCS CVS *,v *,t
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/xml
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
<Location /server-info>
  SetHandler server-info
  Require local
</Location>
TypesConfig /etc/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType application/x-bzip2 .bz2
AddLanguage am .amh
AddLanguage ar .ara
AddLanguage be .be
AddLanguage bg .bg
AddLanguage bn .bn
AddLanguage br .br
AddLanguage bs .bs
AddLanguage ca .ca
AddLanguage cs .cz .cs
AddLanguage cy .cy
AddLanguage da .dk
AddLanguage de .de
AddLanguage dz .dz
AddLanguage el .el
AddLanguage en .en
AddLanguage eo .eo
RemoveType es
AddLanguage es .es
AddLanguage et .et
AddLanguage eu .eu
AddLanguage fa .fa
AddLanguage fi .fi
AddLanguage fr .fr
AddLanguage ga .ga
AddLanguage gl .glg
AddLanguage gu .gu
AddLanguage he .he
AddLanguage hi .hi
AddLanguage hr .hr
AddLanguage hu .hu
AddLanguage hy .hy
AddLanguage id .id
AddLanguage is .is
AddLanguage it .it
AddLanguage ja .ja
AddLanguage ka .ka
AddLanguage kk .kk
AddLanguage km .km
AddLanguage kn .kn
AddLanguage ko .ko
AddLanguage ku .ku
AddLanguage lo .lo
AddLanguage lt .lt
AddLanguage ltz .ltz
AddLanguage lv .lv
AddLanguage mg .mg
AddLanguage mk .mk
AddLanguage ml .ml
AddLanguage mr .mr
AddLanguage ms .msa
AddLanguage nb .nob
AddLanguage ne .ne
AddLanguage nl .nl
AddLanguage nn .nn
AddLanguage no .no
AddLanguage pa .pa
AddLanguage pl .po
AddLanguage pt-BR .pt-br
AddLanguage pt .pt
AddLanguage ro .ro
AddLanguage ru .ru
AddLanguage sa .sa
AddLanguage se .se
AddLanguage si .si
AddLanguage sk .sk
AddLanguage sl .sl
AddLanguage sq .sq
AddLanguage sr .sr
AddLanguage sv .sv
AddLanguage ta .ta
AddLanguage te .te
AddLanguage th .th
AddLanguage tl .tl
RemoveType tr
AddLanguage tr .tr
AddLanguage uk .uk
AddLanguage ur .ur
AddLanguage vi .vi
AddLanguage wo .wo
AddLanguage xh .xh
AddLanguage zh-CN .zh-cn
AddLanguage zh-TW .zh-tw
AddCharset us-ascii     .ascii .us-ascii
AddCharset ISO-8859-1  .iso8859-1  .latin1
AddCharset ISO-8859-2  .iso8859-2  .latin2 .cen
AddCharset ISO-8859-3  .iso8859-3  .latin3
AddCharset ISO-8859-4  .iso8859-4  .latin4
AddCharset ISO-8859-5  .iso8859-5  .cyr .iso-ru
AddCharset ISO-8859-6  .iso8859-6  .arb .arabic
AddCharset ISO-8859-7  .iso8859-7  .grk .greek
AddCharset ISO-8859-8  .iso8859-8  .heb .hebrew
AddCharset ISO-8859-9  .iso8859-9  .latin5 .trk
AddCharset ISO-8859-10  .iso8859-10  .latin6
AddCharset ISO-8859-13  .iso8859-13
AddCharset ISO-8859-14  .iso8859-14  .latin8
AddCharset ISO-8859-15  .iso8859-15  .latin9
AddCharset ISO-8859-16  .iso8859-16  .latin10
AddCharset ISO-2022-JP .iso2022-jp .jis
AddCharset ISO-2022-KR .iso2022-kr .kis
AddCharset ISO-2022-CN .iso2022-cn .cis
AddCharset Big5         .Big5      .big5 .b5
AddCharset cn-Big5       .cn-big5
AddCharset WINDOWS-1251 .cp-1251   .win-1251
AddCharset CP866           .cp866
AddCharset KOI8   .koi8
AddCharset KOI8-E         .koi8-e
AddCharset KOI8-r         .koi8-r .koi8-ru
AddCharset KOI8-U         .koi8-u
AddCharset KOI8-ru       .koi8-uk .ua
AddCharset ISO-10646-UCS-2 .ucs2
AddCharset ISO-10646-UCS-4 .ucs4
AddCharset UTF-7           .utf7
AddCharset UTF-8           .utf8
AddCharset UTF-16         .utf16
AddCharset UTF-16BE     .utf16be
AddCharset UTF-16LE     .utf16le
AddCharset UTF-32         .utf32
AddCharset UTF-32BE     .utf32be
AddCharset UTF-32LE     .utf32le
AddCharset euc-cn         .euc-cn
AddCharset euc-gb         .euc-gb
AddCharset euc-jp         .euc-jp
AddCharset euc-kr         .euc-kr
AddCharset EUC-TW         .euc-tw
AddCharset gb2312         .gb2312 .gb
AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2
AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4
AddCharset shift_jis   .shift_jis .sjis
AddCharset BRF           .brf
AddHandler type-map var
AddType text/html .shtml
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv tr zh-CN zh-TW
ForceLanguagePriority Prefer Fallback
<FilesMatch ".+\.ph(ar|p|tml)$">
  SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch ".+\.phps$">
  SetHandler application/x-httpd-php-source
  Require all denied
</FilesMatch>
<FilesMatch "^\.ph(ar|p|ps|tml)$">
  Require all denied
</FilesMatch>
ProxyHTMLLinks a                href
ProxyHTMLLinks area             href
ProxyHTMLLinks link             href
ProxyHTMLLinks img              src longdesc usemap
ProxyHTMLLinks object           classid codebase data usemap
ProxyHTMLLinks q                cite
ProxyHTMLLinks blockquote       cite
ProxyHTMLLinks ins              cite
ProxyHTMLLinks del              cite
ProxyHTMLLinks form             action
ProxyHTMLLinks input            src usemap
ProxyHTMLLinks head             profile
ProxyHTMLLinks base             href
ProxyHTMLLinks script           src for
ProxyHTMLEvents onclick ondblclick onmousedown onmouseup                onmouseover onmousemove onmouseout onkeypress           onkeydown onkeyup onfocus onblur onload               onunload onsubmit onreset onselect onchange
RequestReadTimeout header=20-40,minrate=500
RequestReadTimeout body=10,minrate=500
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "MS FrontPage" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
BrowserMatch "^gnome-vfs/1.0" redirect-carefully
BrowserMatch "^gvfs/1" redirect-carefully
BrowserMatch "^XML Spy" redirect-carefully
BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
BrowserMatch " Konqueror/4" redirect-carefully
SSLRandomSeed startup builtin
SSLRandomSeed startup file:/dev/urandom 512
SSLRandomSeed connect builtin
SSLRandomSeed connect file:/dev/urandom 512
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl
SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase
SSLSessionCache shmcb:/var/run/apache2/ssl_scache(512000)
SSLSessionCacheTimeout 300
SSLCipherSuite HIGH:!aNULL
SSLProtocol all -SSLv3
<Location /server-status>
  SetHandler server-status
  Require local
</Location>
ExtendedStatus On
ProxyStatus On
Listen 80
Listen 443
<Directory />
  Options FollowSymLinks
  AllowOverride None
  Require all denied
</Directory>
<Directory /usr/share>
  AllowOverride None
  Require all granted
</Directory>
<Directory /var/www/>
  Options Indexes FollowSymLinks
  AllowOverride None
  Require all granted
</Directory>
AccessFileName .htaccess
<FilesMatch "^\.ht">
  Require all denied
</FilesMatch>
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
ProxyPreserveHost On
RewriteEngine on
RewriteCond ${HTTP:Upgrade} =websocket
RewriteRule /gotify/stream(.*) ws://127.0.0.1:8055/stream$1 [P,L]
<Location /gotify/ >
  ProxyPreserveHost On
  ProxyPass http://127.0.0.1:8055/ retry=0 timeout=5
  ProxyPassReverse http://127.0.0.1:8055/
</Location>
<Location /music/>
  ProxyPass http://walden9.local/
  ProxyPassReverse http://walden9.local/
</Location>
<Location /musicstream/>
  ProxyPass http://walden9.local:8000/
  ProxyPassReverse http://walden9.local:8000/
</Location>
<Location /camnorth>
  ProxyPass http://DCS-930LB1_2832EF.local:8082
  ProxyPassReverse http://DCS-930LB1_2832EF.local:8082
</Location>
<Location /camsouthwest>
  ProxyPass http://DCS-930L_027D6F.local:8083
  ProxyPassReverse http://DCS-930L_027D6F.local:8083
</Location>
<Location /camfront>
  ProxyPass http://walden0.local:8084
  ProxyPassReverse http://walden0.local:8084
</Location>
<Location /cameast>
  ProxyPass http://waldend.local:8084
  ProxyPassReverse http://waldend.local:8084
</Location>
<Location /camnortheast>
  ProxyPass http://waldene.local:8084
  ProxyPassReverse http://waldene.local:8084
</Location>
<Location /camsouth>
  ProxyPass http://waldenf.local:8084
  ProxyPassReverse http://waldenf.local:8084
</Location>
<Location /camnorthwest>
  ProxyPass http://waldeng.local:8084
  ProxyPassReverse http://waldeng.local:8084
</Location>
<Location /ha>
  ProxyPass http://waldenb.local:8000/ha
  ProxyPassReverse http://waldenb.local:8000/ha
</Location>
Alias /Photos/ "/mnt/www/Photos/"
<Directory "/mnt/www/Photos">
  Options FollowSymlinks
  AllowOverride None
  AuthType Basic
  AuthName "Restricted Content"
  AuthUserFile /etc/apache2/.htpasswd
  Require valid-user
</Directory>
Alias /testPhotos/ "/mnt/www/testPhotos/"
<Directory "/mnt/www/testPhotos">
  Options FollowSymlinks
  AllowOverride None
  AuthType Basic
  AuthName "Restricted Content"
  AuthUserFile /etc/apache2/.htpasswd
  Require valid-user
</Directory>
Alias /632LindenPhotos/ "/mnt/www/632LindenPhotos/"
<Directory "/mnt/www/632LindenPhotos">
  Options +Indexes
  AllowOverride None
  AuthType Basic
  AuthName "Restricted Content"
  AuthUserFile /etc/apache2/.htpasswd632
  Require valid-user
</Directory>
Alias /album4/ "/mnt/www/album4/"
<Directory "/mnt/www/album4">
  Options FollowSymlinks
  AllowOverride None
  Require all granted
</Directory>
Alias /miniflux/ "/home/pwalden/Downloads/miniflux.w1/"
<Directory "/home/pwalden/Downloads/miniflux.w1">
  Options FollowSymlinks
  AllowOverride None
  Require all granted
</Directory>
Alias /webcam/ "/mnt/webcam/"
<Directory "/mnt/webcam">
  Options FollowSymlinks
  AllowOverride None
  Require all granted
</Directory>
CustomLog /var/log/apache2/other_vhosts_access.log vhost_combined
ServerTokens OS
ServerSignature On
TraceEnable Off
<VirtualHost *:443>
  ServerName walden4.homelinuxserver.org
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  ErrorLog /var/log/apache2/error.log
  CustomLog /var/log/apache2/access.log combined
  SSLCertificateFile /etc/letsencrypt/live/walden4.homelinuxserver.org/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/walden4.homelinuxserver.org/privkey.pem
  SSLEngine on
  SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
  SSLHonorCipherOrder off
  SSLSessionTickets off
  SSLOptions +StrictRequire
  LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
  LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
</VirtualHost>
<VirtualHost *:80>
  ServerName walden4.homelinuxserver.org
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  ErrorLog /var/log/apache2/error.log
  CustomLog /var/log/apache2/access.log combined
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =walden4.homelinuxserver.org
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
jmattheis commented 8 months ago

you need to add

RewriteEngine on
RewriteCond ${HTTP:Upgrade} =websocket
RewriteRule /gotify/stream(.*) ws://127.0.0.1:8055/stream$1 [P,L]

into the <VirtualHost *:443> config.

pcwalden commented 8 months ago

I tried your suggestion and added the RewriteRule to the VirtualHost *:443 section, but I get the same error. It does appear to direct the gotify/stream to the gotify server stream command, but the apache proxy is not passing on the upgrade token

<VirtualHost *:443>
  ServerName xxxxx4.homelinuxserver.org
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  ErrorLog /var/log/apache2/error.log
  CustomLog /var/log/apache2/access.log combined
  SSLCertificateFile /etc/letsencrypt/live/xxxxx4.homelinuxserver.org/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/xxxxx4.homelinuxserver.org/privkey.pem
  SSLEngine on
  SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
  SSLHonorCipherOrder off
  SSLSessionTickets off
  SSLOptions +StrictRequire
  LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
  LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
  RewriteEngine on
  RewriteCond ${HTTP:Upgrade} =websocket
  RewriteRule /gotify/stream(.*) ws://127.0.0.1:8055/stream$1 [P,L]
</VirtualHost>

gotify log

2024-03-13T10:00:36-07:00 | 200 |  655.215936ms | 207.183.232.163 | POST     "/client"
2024-03-13T10:00:36-07:00 | 200 |   20.882977ms | 207.183.232.163 | GET      "/current/user"
2024-03-13T10:00:36-07:00 | 200 |    8.887682ms | 207.183.232.163 | GET      "/application"
2024-03-13T10:00:36-07:00 | 400 |    2.056099ms | 207.183.232.163 | GET      "/stream?token=[masked]"
Error #01: websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header
2024-03-13T10:00:37-07:00 | 200 |    3.187718ms | 207.183.232.163 | GET      "/message?since=0"
2024-03-13T10:00:37-07:00 | 200 |    2.889436ms | 207.183.232.163 | GET      "/current/user"
2024-03-13T10:01:07-07:00 | 400 |     2.34209ms | 207.183.232.163 | GET      "/stream?token=[masked]"
Error #01: websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header
pcwalden commented 8 months ago

The browser console also states below. Looks like the WebUI is trying to establish a wss connection because the the login is via https. However, I only have a ws port for the gotify server and the RewriteRule is directing to a ws stream.

main.f445756e.chunk.js:1:62864

Firefox can’t establish a connection to the server at wss://xxxxx4.homelinuxserver.org/gotify/stream?token=CMnaIkYZ4CXbHWo.

WebSocket connection errored 
error { target: WebSocket, isTrusted: true, srcElement: WebSocket, currentTarget: WebSocket, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
pcwalden commented 8 months ago

I get the same console error when I hit thestream. non-ssl URL. The WebUI is trying to access a ws

Firefox can’t establish a connection to the server at ws://xxxxx4.mooo.com/gotify/stream?token=CLHB8JqD6rm9DHW. 

WebSocket connection errored 
error { target: WebSocket, isTrusted: true, srcElement: WebSocket, currentTarget: WebSocket, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
jmattheis commented 8 months ago

Try add it like this:

  RewriteEngine on
  RewriteCond %{HTTP:Connection} upgrade [NC]
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteRule /gotify/stream(.*) ws://server:80/stream$1 [P,L]

instead of the old rewrite statements.

pcwalden commented 8 months ago

Yes!!!

Working now.

<VirtualHost *:443>
  ServerName xxxxx4.homelinuxserver.org
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  ErrorLog /var/log/apache2/error.log
  CustomLog /var/log/apache2/access.log combined
  SSLCertificateFile /etc/letsencrypt/live/xxxxx4.homelinuxserver.org/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/xxxxx4.homelinuxserver.org/privkey.pem
  SSLEngine on
  SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
  SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
  SSLHonorCipherOrder off
  SSLSessionTickets off
  SSLOptions +StrictRequire
  LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
  LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
  RewriteEngine on
  RewriteCond %{HTTP:Connection} upgrade [NC]
  RewriteCond %{HTTP:Upgrade} websocket [NC]
  RewriteRule /gotify/stream(.*) ws://127.0.0.1:8055/stream$1 [P,L]
</VirtualHost>
<VirtualHost *:80>
  ServerName xxxxx4.homelinuxserver.org
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/html
  ErrorLog /var/log/apache2/error.log
  CustomLog /var/log/apache2/access.log combined
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =xxxxx4.homelinuxserver.org
  RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
jmattheis commented 8 months ago

Adjusted docs in gotify/website@f325769d8b582c24f96eeb781509166927c419c1