Integrating Nextcloud + Collabora behind reverse proxy

So you have a setup where Nextcloud runs on a host with internal IP which is exposed to the public network using a reverse proxy like Nginx. Public URLs are not accessible from the internal network due to DNS resolution. Research shows that this setup seems to be quite common.

Next you want to integrate Collabora Office into Nextcloud to allow editing of office documents. First steps are to install the Nextcloud app „richdocuments“ then install the coolwsd service which provides Collabora Office. We switch off SSL in coolwsd as it is provided by the reverse proxy. Internally HTTP can be used.

Now you have 2 separate services which send requests to each other so both have to reach the other service but we can’t use public URLs as they are not reachable internally.

Next you find a quick overview how to setup this scenario:

  • There are 3 URLs in Nextcloud’s richdocuments which have to be setup using the console as 2 of them are not available in the UI. For internal communication we use HTTP so we don’t have to deal with certificates.
    • public_wopi_url is the public URL of your Nextcloud instance, e.g.
      • sudo -u www-data php ./occ config:app:set richdocuments public_wopi_url --value
    • wopi_callback_url is the internal URL of your Nextcloud instance, e.g.
      • sudo -u www-data php ./occ config:app:set richdocuments wopi_callback_url --value
    • wopi_url is the internal URL of coolwsd, e.g.
      • sudo -u www-data php ./occ config:app:set richdocuments wopi_url --value

This way both services can reach each other internally.

Integration works by including Collabora in an iframe in our Nextcloud instance. So we have to extend the Content Security Policy (CSP) of coolwsd as its directive frame-ancestors by default only includes wopi_callback_url which is not publicly reachable. We can set it in /etc/coolwsd/coolwsd.xml:

<frame_ancestors desc="OBSOLETE: Use content_security_policy. Specify who is allowed to embed the Collabora Online iframe (coolwsd and WOPI host are always allowed). Separate multiple hosts by space."> 'self'</frame_ancestors>

The hint regarding frame_ancestors being obsolete might be correct but i found that only by using frame_ancestors i got a correct CSP-policy. Using content_security_policy created 2 policies which prevent loading the iframe. I will put an issue on github.