Realtime WYSIWYG behind reverse proxy

Hello,

what are the required configuration changes that need to be done when using the Realtime WYSIWYG editor while using an reverse proxy like nginx?

I have set up an new test server with the 15.9 tomcat9 debian package. When accessing a page with 8080 (directly to tomcat) Realtime editing works.
When accessing the page normally (port 80) to the nginx reverse proxy, realtime editing doesn’t work and an info box is shown.
Connecting to the collaborative session. Please wait…
image

The nginx is set up absolutely minimally only with port 80 based on this: Tomcat Installation (XWiki.org)

I understand that the Realtime WYSIWYG Editor is still in experimental state.
But I assume that configuration changes for the reverse proxy will still be needed still required.

Does somebody already had success in using Realtime Editing in combination with an reverse proxy and can tell, what needs to be configured?

Edit: Just as expected same behaviour with 15.10.

Hi,

The Realtime WYSIWYG editor performs content sync through WebSocket connections. This means the reverse proxy needs to forward not only http:// and https:// requests but also ws:// and wss:// (WebSocket and WebSocket Secure requests).

I know very little about nginx configuration, but this doesn’t look good to me:

location ^~ /xwiki {
  # If path starts with /xwiki - then redirect to backend: XWiki application in Tomcat
  # Read more about proxy_pass: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
  proxy_pass http://localhost:8080;

My understanding is that with this configuration any request that has its URL path prefixed with /xwiki is forwarded with http:// scheme. Doesn’t this mean that any ws:// (WebSocket) request received by the reverse proxy will be forwarded locally to Tomcat as http://? Which is obviously not good.

I would expect the reverse proxy to forward wss://mydomain.com/xwiki/... to ws://localhost:8080/xwiki/..., i.e. forward the received secure (encrypted) WebSocket request (on port 80) to localhost (Tomcat) unencrypted on port 8080.

Hope this helps,
Marius

1 Like

Hi! I had no time to test something similar with XWiki, but I’m dealing with what I think could be the same issue while setting up Cockpit on an Alma Linux 9.3 server.

Perhaps you can find some clues in the following cockpit.conf file. It is working for Cockpit:

upstream cockpit {
 server 127.0.0.1:9090 weight=100 max_fails=5 fail_timeout=5;
 }

 server {
 server_name cockpit.igfae.usc.es;

 location / {
 proxy_set_header X-Forwarded-Host $host;
 proxy_set_header X-Forwarded-Server $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_pass http://cockpit/;

 # By rjr from https://github.com/cockpit-project/cockpit/wiki/Proxying-Cockpit-over-NGINX
 # Required for web sockets to function
 proxy_http_version 1.1;
 proxy_buffering off;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";

 # Pass ETag header from Cockpit to clients.
 # See: https://github.com/cockpit-project/cockpit/issues/5239
 gzip off;
 }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/cockpit.igfae.usc.es/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/cockpit.igfae.usc.es/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}



 server {
    if ($host = cockpit.igfae.usc.es) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


 listen 80;
 server_name cockpit.igfae.usc.es;
    return 404; # managed by Certbot


}

I will try it ASAP!

1 Like

Ok simply wow. After searching the internet a lot. there is so much contradictory information but the solution for XWiki to bring Realtime WYSIWYG alive over nginx seems top be way to easy.

Some nginx documentation and configuration snipets tells that Websockets need to run on another port, but as you stated the websockets runs on the same port.
When running both on the same port however some documentation then tells that websockets needs to run on another path than the http stuff (examples http stuff on servername.domain.com:8080/xwiki/ and web socket stuff on servername.domain.com:8080/websocketstuff/) to switch the proxy forwarding. Which is not something that brought me closer to a solution.

For Apache on the other hand it seems to be more easy to understand as it can be defined for ws:// and wss:// seperated form http:// and http://

However for Nginx with xwiki + Realtime Editing I found the super simple solution here by coincidence: How to use Nginx as a Reverse proxy for HTTPS and WSS - Self Signed Certificates and Trusted Certificates (linkedin.com)

Put these few lines for additional headers below the proxy forwarding headers and then websocket is also handled successfully…

# WebSocket support
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";

I am quite new to nginx and tomcat and hosting Xwiki so take this all with not only a grain of salt but rather a spoon of salt. But for me this 3 lines made it work.

So the complete simple port 80 (without SSL) configuration to run XWIKI with Realtime WYSIWYG on nginx is that:

server {
    listen       80;
    # REPLACE THIS WITH YOUR SERVERNAME AND DOMAIN AND TLD
    server_name  servername.domain.com,

    # Normally root should not be accessed, however, root should not serve files that might compromise the security of your server.
    root /var/www/html;

    # Configuration to avoid Request Entity too large error 413
    client_max_body_size 0;

    location / {
        # All "root" requests will have /xwiki appended AND redirected to mydomain.com
        rewrite ^ $scheme://$server_name/xwiki$request_uri? permanent;
    }

    location ^~ /xwiki {
       # If path starts with /xwiki - then redirect to backend: XWiki application in Tomcat
       # Read more about proxy_pass: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
       proxy_pass http://localhost:8080;
       proxy_set_header        X-Real-IP $remote_addr;
       proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header        Host $http_host;
       proxy_set_header        X-Forwarded-Proto $scheme;

       # WebSocket support
       proxy_http_version 1.1;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
   }
}

I’ll configure SSL later and give an update if the simple fix still applies, but right now I don’t have any doubts about it.

Nice, just while I was writing about the solution you posted that - your config includes the same websocket lines that are necessary.

Also your websocket config seems to disable buffering - maybe I should include that also?
Realtime WYSIWYG works without that line, so I have no clue.

No idea either! I will update this thread when I got an explanation for that line.

Ok I rejoiced to soon: When enabling SSL the issue occurs again.

Also running without SSL (normal http) on an other port than 80, the issue is the same. So as example running the the reverse proxy port listening on 8888 the issue occurs.

Ok so now after hitting a wall with SSL I thought lets see how Confluence handles it which his very interesting:
Running Confluence behind NGINX with SSL | Confluence Data Center and Server 8.6 | Atlassian Documentation

Their nginx configuration is nearly the same with the proxy headers for http 1.1 and connection upgrade.
However Confluence cleanly seperate their Realtime Colaborative Editing engine (Synchrony) into another port aswell as another location so that reverse proxys can handle things without too difficult configurations.

@mflorea could you possibly provide an configuration example for an reverse proxy with XWiki WYSIWYG and SSL enabled - like Apache or anything you are familiar something? That would be super helpfull.
Im not really settled to nginx, I simply want things to work and right now I can’t find any configuration Documentation to get the the Realtime WYSIWYG Editor running with SSL.

NEVERMIND:
When Enabling SSL you HAVE TO edit the xwiki.cfg and tell XWiki that it is running on SSL as well as the server name, otherwise the Websockets are still sent on http (port 80) from XWiki. Actually this makes quite sense.

xwiki.home=https://yourservername.yourdomain.yourTLD/

xwiki.url.protocol=https

I will later on post an full baseline https nginx configuration so that other people don’t run into the same issue as I did.

As promised here is our minimalistic running configuration with SSL and Realtime WYSIWYG working behind nginx. We are running XWiki 15.10 on Debian 11 with the tomcat9 .DEB Package.

The default nginx configuration still aplies and includes the tomcat9.conf file.

Content of file: /etc/nginx/conf.d/tomcat9.conf (replace the capslock stuff):

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    rewrite     ^   https://YOURWIKISERVER.YOURDOMAIN.YORTLD$request_uri? permanent;
}

server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    gzip off;

    server_name  YOURWIKISERVER.YOURDOMAIN.YORTLD;

    # Normally root should not be accessed, however, root should not serve files that might compromise the security of your server.
    root /var/www/html;

    # Configuration to avoid Request Entity too large error 413
    client_max_body_size 0;

    #ssl on;
    ssl_certificate YOUR-CERTIFICATE-FILE.crt;
    ssl_certificate_key YOUR-CERTIFICATE-KEY.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers DEFINE CHIPHERS HERE;


    location / {
        # All "root" requests will have /xwiki appended AND redirected to mydomain.com
        rewrite ^ $scheme://$server_name/xwiki$request_uri? permanent;
    }

    location ^~ /xwiki {
       # If path starts with /xwiki - then redirect to backend: XWiki application in Tomcat
       # Read more about proxy_pass: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
       proxy_pass              http://127.0.0.1:8080;
       proxy_set_header        X-Real-IP $remote_addr;
       proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header        Host $server_name;
       proxy_set_header        X-Forwarded-Proto $scheme;

       # WebSocket support is required for Realtime WYSIWYG, also it's neccessary to set home URL and URL protocol in the xwiki.cfg
       proxy_http_version 1.1;
       proxy_buffering off;
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "Upgrade";
    }
}

the xwiki configuration file under /etc/xwiki/xwiki.cfg needs to be modified:

xwiki.home=https://YOURWIKISERVER.YOURDOMAIN.YORTLD/
xwiki.url.protocol=https

Please note, that this is an quite minimal configuration so you should take it with an grain of salt. My knowledge about nginx and xwiki are currently still quite limited. This configuration should help as a baseline.
If you have tips on how to improve / secure the configuration I would be very glad to hear them!

1 Like