Local access for Collabora

Thank you for writing this up.

I think it makes sense if the Nextcloud and Collabora servers are running on a single host within a single docker network and https://cloud.mydomain points to a reverse proxy on a different host. We don’t want Nextcloud and Collabora to communicate over the internet unnecessarily or mess with DNS.

For example, this is my configuration for Nextcloud AIO with a Reverse Proxy on VPS doing SSL termination. The Nextcloud AIO host is behind a CGNAT, so I connect to it using Tailscale for a VPN.

graph LR
    Client -->|HTTPS cloud.mydomain| ReverseProxy

    subgraph Tailnet
        subgraph "VPS"
            ReverseProxy
        end

        subgraph "Nextcloud AIO Host"
            subgraph nextcloud-aio [nextcloud-aio dockernet]
                AIO_Apache["nextcloud-aio-apache"]
                Nextcloud["nextcloud-aio-nextcloud"]
                Collabora["nextcloud-aio-collabora"]
            end
        end

        ReverseProxy -->|HTTP AIO Tailnet IP:11000| AIO_Apache
        AIO_Apache --> Nextcloud
        AIO_Apache --> Collabora
        Nextcloud --> Collabora
        Collabora --> Nextcloud
    end
Configured WOPI URL: http://nextcloud-aio-collabora:9980
Configured public WOPI URL: https://cloud.mydomain
Configured callback URL: http://nextcloud-aio-apache:11000

I had to apply a change to AIO for the internal communication to work which I hope to upstream.

I hope this helps others!

Or, even without Docker and Tailscale, if everything, including the web server/reverse proxy, is running on the same host.

To be honest, though, I’m not a big fan of the WOPI protocol, as it’s far too complicated. I’m sure there are reasons why it’s so complicated; one of them is probably that it was invented by Microsoft. :wink: However, it would be so much nicer if Collabora could just offer a simple web socket with a JWT authentication token, like e.g. the Whiteboard backend does.

1 Like

And here the actual reasons why it’s so complicated (warning: this is extremely oversimplified):

Collabora exposes what feels like a hundred endpoints and relies on WOPI (a protocol originally designed to make Microsoft Office available in the browser) because, at its core, it is not a true web application but essentially a desktop application (LibreOffice in this case) that is serevd through a web server.

The server does most of the heavy lifting, the browser displays the rendered output and the user’s input is sent back. In return, you theoretically get the full feature set of a desktop suite in your browser. In practice, however, some features are still missing, probably due to performance constraints.

Native web apps like Google Docs, OnlyOffice, or Excalidraw (the Nextcloud Whiteboard app) take a very different approach, as most of the application logic is loaded directly into the browser itself, so that only the document data needs to sync with the server.

In short: WOPI-based apps behave more like remote desktop solutions than modern web applications. :wink:

1 Like

I’m sorry I strongly disagree - different URLs make troubleshooting much harder as for testing and logs one has to consider the right perspective - not only in the outgoing direction but also on the incoming side the admin must take into account where the request comes from - additional program code complexity and potential bugs included.

Using same URL everywhere simplifies code, config and troubleshooting. The demand of avoiding internet loop with with low latency ā€œlocalā€ connections is described in detail in Probably DNS help with NC Docker + Collabora + Wireguard tunnel - #4 by wwe - at the end it is a variant of splitbraindns 101: Split-Brain DNS (split-horizon) - connection to/though local reverse proxy are quick and utilize same URL, TLS certs and (from application point of view) follow same network path - easy to understand, same way to troubleshoot independent from the source of request.

FYI @szaimen

yes but the reason to expose as many endpoints is simple - in opposite to other applications you mentioned CODE/COOL is not a ā€œsingle purposeā€ application but office suite which handles many different formats (mime types) - and must assign each supported format to another ā€œsub-applicationā€ → simply check ../hosting/discovery document and you get the reason.

3 Likes

Thank you for your reply. I appreciate the feedback. I tried the Split-Brain DNS approach and unfortunately it doesn’t work for my use-case because it assumes that the VPS can port forward to a Reverse Proxy on the on the docker host. In my case, the reverse proxy on the VPS is a frontend for multiple services – cloud.example.com goes to the docker host and jellyfin.example.com goes to a different server – so I can’t simply forward port 443 to the docker host.

I tried chaining an additional reverse proxy on the Nextcloud and Collabora host using the same SSL certs from the VPS reverse proxy, but never quite got it working and would be a pain to maintain those certs long-term anyway.

I agree that having all the requests go through a single point makes things a little easier to debug because you can look at the logs of the reverse proxy and see all of the requests. So, I modified my PR so all the requests always go through the AIO apache server.

graph LR
    Client -->|cloud.mydomain| ReverseProxy

    subgraph Tailnet
        subgraph "VPS Host"
            ReverseProxy
        end

        subgraph "Nextcloud AIO Host"
            subgraph nextcloud-aio [nextcloud-aio dockernet]
                AIO_Apache["AIO Apache"]
                Nextcloud
                Collabora
            end
        end

        ReverseProxy -->|HTTP| AIO_Apache
        AIO_Apache --> Nextcloud
        Nextcloud --> AIO_Apache
        AIO_Apache --> Collabora
        Collabora --> AIO_Apache
    end
Configured WOPI URL: http://nextcloud-aio-apache:11000
Configured public WOPI URL: https://cloud.mydomain
Configured callback URL: http://nextcloud-aio-apache:11000

Does this make sense? Am I missing anything?

Your new approach looks more structured now as traffic flow is same after Apache.. but you still use different URLs which requires different config (IMO CODE heavily relies on reverse proxy headers like x_forwarded.. this might need attention)

Best approach depends on your network topology. If the VPS is kind of local you and not ā€œremoteā€ somewhere in the cloud you can still use it as an entry point (not using docker config but tailnet DNS or hosts records). Otherwise the best approach would be to enable https on AIO Apache and use the front reverse proxy as relay.

But this discussion is not related to CODE and my knowledge on tailscale and AiO is too limited to recommend the way to implement. I split this discussion to a separate topic to focus on additional details and keep the guide lean.

OnlyOffice can handle many different file formats as well, but you can connect to it through a single endpoint, without needing a complicated reverse proxy configuration.

The main reason for this is that OnlyOffice (and other web-native apps, such as Excalidraw) are designed as native web applications from the ground up. Collabora Online, on the other hand, is essentially a headless LibreOffice instance and therefore relies on the more complex WOPI protocol to serve the application as a web app.

That said, I still prefer Collabora to OnlyOffice for other reasons. However, it is definitely more complicated to set up than modern web applications need to be or should be. Also, it is more resource-intensive on the server side.

Hi @bb77,

It’s this warning that keeps me from going too deeply into your claims.

  • Collabora Online can be set up just as easily standalone, without a reverse proxy, and used with TLS.
  • OnlyOffice, on the other hand, also supports WOPI and can be placed behind a reverse proxy.

Your gut-feeling comments and comparisons are - as you said - ā€œextremely oversimplifiedā€ and can therefore - with due respect - not be taken serious.

:wink:


ernolf

Yeah maybe. But I see it from my perspective as a hobby admin, and from that perspective I see…

SetEnvIf Host "^(.*)$" THE_HOST=$1
RequestHeader setifempty X-Forwarded-Proto https
RequestHeader setifempty X-Forwarded-Host %{THE_HOST}e
ProxyAddHeaders Off

ProxyPassMatch (.*)(\/websocket)$ "ws://127.0.0.1:9981/$1$2"
ProxyPass / "http://127.0.0.1:9981/"
ProxyPassReverse / "http://127.0.0.1:9981/"

vs.

# Encoded slashes need to be allowed
AllowEncodedSlashes NoDecode

# Container uses a unique non-signed certificate
SSLProxyEngine On
SSLProxyVerify None
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off

# keep the host
ProxyPreserveHost On

# static html, js, images, etc. served from coolwsd
# browser is the client part of LibreOffice Online
ProxyPass           /browser https://127.0.0.1:9980/browser retry=0
ProxyPassReverse    /browser https://127.0.0.1:9980/browser

# WOPI discovery URL
ProxyPass           /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0
ProxyPassReverse    /hosting/discovery https://127.0.0.1:9980/hosting/discovery

# Main websocket
ProxyPassMatch "/cool/(.*)/ws$" wss://127.0.0.1:9980/cool/$1/ws nocanon

# Admin Console websocket
ProxyPass   /cool/adminws wss://127.0.0.1:9980/cool/adminws

# Download as, Fullscreen presentation and Image upload operations
ProxyPass           /cool https://127.0.0.1:9980/cool
ProxyPassReverse    /cool https://127.0.0.1:9980/cool

# Endpoint with information about availability of various features
ProxyPass           /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities retry=0
ProxyPassReverse    /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities

and a JWT token vs servername internal external, aliasgroups 1 2 3 etc.

And I haven’t even mentioned the XML configuration file, which is a pain to use. Fortunately, I use the Docker container with an .env file, which makes it possible to configure Collabora in a ā€œhuman-readableā€ way, if you can find the right environment variables in the documentation.

:wink:

Yes! I agree!

I’m working on a Python-based project to significantly simplify configuration file handling with simple override rules.

It already works for me, but I’d like to improve it a bit.

This makes configuring CoolWSD a breeze!

I’ll be happy to show you the result as soon as it’s ready to be published.


ernolf

1 Like