[Solved] Collabra w/ NextCloud Office via Apache2 reverse proxy: "Document loading failed. Failed to load Nextcloud Office - please try again later."

Hello,

I am testing out the NextCloud v27.1.1.0 TurnKey appliance behind my Apache reverse proxy.

I have installed the NextCloud and Collabra apps to run self-hosted online office.

This is my first Apache reverse proxy configuration attempt. I have used what little information I found in chapter 5.13 of the manual, ‘Reverse Proxy’.

As per chapter 5.13.1, I have added ‘trusted_proxies’ and (as per chapter 5.13.2) ‘overwrites’ to my NextCloud config.php file:

public.domain.co.uk is the public-facing FQDN for the Apache2 VPS running the reverse proxy, while my.internal.domain.co.uk is the local LAN DNS resolution for the NextCloud VM. As you will see, I use the internal FQDN to connect to NextCloud from the Apache reverse proxy.

<?php
$CONFIG = array (
  'passwordsalt' => '*********************************',
  'secret' => '*********************************************************************',
  'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => 'public.domain.co.uk',
    2 => 'my.internal.domain.co.uk'
  ),
  'datadirectory' => '/var/www/nextcloud-data',
  'dbtype' => 'mysql',
  'version' => '27.1.1.0',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => '****************************',
  'installed' => true,
  'instanceid' => '*************',
  'memcache.local' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'timeout' => 0.0,
  ),
  'filelocking.enabled' => true,
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'log_type' => 'file',
  'logfile' => '/var/www/nextcloud-data/nextcloud.log',
  'loglevel' => 3,
  'enforce_theme' => '',
  'default_locale' => 'en_GB',
  'default_phone_region' => 'UK',
  'maintenance' => false,

  'trusted_proxies'   => ['192.168.42.9'],
  'overwritehost'     => 'public.domain.co.uk',
  'overwriteprotocol' => 'https',
  'overwritewebroot'  => '/',
  'overwritecondaddr' => '^192\.168\.42\.9$',
  'overwrite.cli.url' => 'https://public.domain.co.uk/',

  'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'),
);

(I gather there should be no closing php tag?)

Apache2.4 vhost reverse proxy configuration. As per 5.13.3 I added the Apache 2 rewrite rules for caldav and carddav and extra header directives as per some forum posts I found discussing reverse proxy issues with Collabra:

<VirtualHost *:80>
        ServerName public.domain.co.uk
        ServerAlias www.public.domain.co.uk

        RewriteEngine on
        RewriteCond %{SERVER_NAME} =public.domain.co.uk
        RewriteCond %{SERVER_NAME} =www.public.domain.co.uk
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
        ServerName public.domain.co.uk
        ServerAlias www.public.domain.co.uk

        RewriteEngine on
        RewriteRule ^/\.well-known/carddav https://my.internal.domain.co.uk/remote.php/dav/ [R=301,L]
        RewriteRule ^/\.well-known/caldav https://my.internal.domain.co.uk/remote.php/dav/ [R=301,L]

        SSLProxyEngine on
        SSLProxyVerify none
        SSLProxyCheckPeerCN off
        SSLProxyCheckPeerName off

        ProxyPass / https://my.internal.domain.co.uk/ nocanon
        ProxyPassReverse / https://my.internal.domain.co.uk/

        Header always set Strict-Transport-Security "max-age=15768000; preload"

        RequestHeader set X-Forwarded-SSL "1"
        RequestHeader set X-Forwarded-Proto "https" env=HTTPS

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/public.domain.co.uk/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/public.domain.co.uk/privkey.pem
</VirtualHost>

(I just noticed an incumbent 'overwrite.cli.url' => 'http://localhost', entry as I pasted my NextCloud config.php. - I have removed that line and nothing has changed (I don’t think it was causing an issue as it is overridden later in the array.)

I can create a new document fine, but when it comes to editing it, I just get the circular loading spinner.

Previously, I managed to correct all the internal domain names that were being sent to the clientbut it seems to be sending my.internal.domain.co.uk instead of public.domain.co.uk in this instance, resulting in the following errors in my FireFox v124.0.1 client. As I said I can’t find anywhere to fix this:

404 | GET  | public.domain.co.uk      | workspace?path=/EXTANT+DIRECTORY | xhr | json | ...
404 | GET  | public.domain.co.uk      | preview?fileId=nnnn&c=hexhexhexhexhexhexhexhexhex&x=200&y=200&forceIcon=0&a=1 | merged-index.js:6634 (img) | json | ...
404 | GET  | public.domain.co.uk      | closedoc.svg | img | ...
404 | POST | my.internal.domain.co.uk | https://my.internal.domain.co.uk/apps/richdocumentscode/proxy.php?req=/cool/https%3A%2F%2Fpublic.domain.co.uk%2Findex.php%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F4324_144e733f82229%3Faccess_token%3DerXk20dLs2MXjfEYkHamGbviQS615B6q%26access_token_ttl%3D0/ws?WOPISrc=https%3A%2F%2Fpublic.domain.co.uk%2Findex.php%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F4324_144e733f82229&compat=/ws/open/open/0 |  | ...

That past POST looks suspect and I think that’s what’s causing the failure, but I can’t find out where this particular URL is coming from, since every other URL error has been rectified (I got lots until I sorted the NextCloud domains and some Apache2 vhost SSL settings.

I tried to glean as much information from the documentation on NextCloud as I could but ultimately found it to be missing important details and context and I do see other potential advocates having troubles relying solely on the instruction manual for instructions.

How would one go about making submissions or recommendations to the documentation team?

I am not seeing any errors from the proxy or the NextCloud Apache2 web service, just client errors - which is a monumental improvement on initial installation lol

So, I guess my questions are:

  1. Do my configs look OK or is something glaringly obviously broken?
  2. How would I remedy that leaked, rogue, internal domain name?

If there’s anything I’ve missed, please ask.

I hope this post is clearly put. If not, just ask and I’ll augment and clarify.

Many thanks.

(Apologies for any spelling mistakes or layout problems.)

please follow Collabora integration and report details…

in general there is no good way to access the the system using different hostnames… you better follow a splitbraindns approach - having same public dns resolved to differnt IP internally and externally

1 Like

Sorry, I didn’t mention my DNS config. I have a split DNS setup. public.domain.co.uk resolves to a WAN IP on WAN-side and a LAN IP on LAN-side, both connecting to the reverse proxy.

It spits out the my.internal.domain.co.uk hostname, just the once, which resolves to the private IP and should only be used by the Apache reverse proxy.

Your comment about the XML config file sounds promising:

I shall check the XML file out to see if the internal DNS name is in there somehow.

Everything else is working inside and out so far and I don’t want to take steps backwards just yet.

Many thanks for the lightening fast response. <3

I get a 404 from [...]/hosting/capabilities and [...]/hosting/discovery.

I can’t find these on the filesystem or in the Apache2 configs.

However, I went back through my terminal to a wget I did earlier and I saw that the URLs were all https://my.internal.domain.co.uk[...].

I did notice that when I try to manually set the Collabra server to ‘Use your own server’ with ‘https://public.domain.co.uk/apps/richdocumentscode/proxy.php?req=’ and save, it resets to ‘Use the built-in CODE[…]’ afterwards.

Here’s my [...]proxy.php?req=capabilities output:

{
  "convert-to": {
    "available": true,
    "endpoint": "/cool/convert-to"
  },
  "hasMobileSupport": true,
  "hasProxyPrefix": true,
  "hasTemplateSaveAs": false,
  "hasTemplateSource": true,
  "hasWASMSupport": false,
  "hasZoteroSupport": true,
  "productName": "Collabora Online Development Edition",
  "productVersion": "23.05.10.1",
  "productVersionHash": "baa6eef",
  "serverId": "********"
}

The [...]/status.php page looks fine:

{
  "installed": true,
  "maintenance": false,
  "needsDbUpgrade": false,
  "version": "27.1.1.0",
  "versionstring": "27.1.1",
  "edition": "",
  "productname": "Nextcloud",
  "extendedSupport": false
}

I am thinking that this stuck option is enforcing an incorrect hostname in responses.

No idea why the […]/capabilities response is empty in my browser, though.

Update: Just found out that if I append “/hosting/[...]” to the end of “https://public.domain.co.uk/apps/richdocumentscode/proxy.php?req=” I do get a response. Although, fetching [...]/hosting/capabilities returns 0-length data to my browser but no server-side errors. I can also wget the discovery XML fine this way.

I could use Apache to rewrite this, but I’m not sure if this is expected behaviour for CODE.

Thanks again for your time.

Best regards.

this happens because built-in CODE runs on this address (basically the server proxies requests to built-in CODE). the option “own server” is used when CODE runs outside of Nextcloud.

Sounds you are using collabora-built-in so all CODE URLs should live at “https://public.domain.co.uk/apps/richdocumentscode/proxy.php?req=” e.g. “https://public.domain.co.uk/apps/richdocumentscode/proxy.php?req=/hosting/discovery” and “https://public.domain.co.uk/apps/richdocumentscode/proxy.php?req=/hosting/capabilities”, reverseproxy should forward host headers (X-FORWARDED-*) and Nextcloud system must access “https://public.domain.co.uk/*” through your reverse proxy (using internal IP from splitbraindns is OK)

1 Like

Thank you very much for your assistance, I think I’ve fixed it.

I added two directives to the reverse proxy config which I hadn’t before:

AllowEncodedSlashes NoDecode
ProxyPreserveHost On

I didn’t add PreserveHost because I thought it would confuse the nextcloud server. I was wrong.

Enabled modules on the reverse proxy:

~ $ >a2query -m | grep proxy
proxy_html (enabled by site administrator)
proxy_http (enabled by site administrator)
proxy (enabled by site administrator)

I just did a test and I didn’t see any internal name requests:

My reverse proxy vhost config for Apache2:

AllowEncodedSlashes NoDecode
ProxyPreserveHost On

<VirtualHost *:80>
        ServerName public.domain.co.uk
        ServerAlias www.public.domain.co.uk

        RewriteEngine on
        RewriteCond %{SERVER_NAME} =public.domain.co.uk
        RewriteCond %{SERVER_NAME} =www.public.domain.co.uk
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
        ServerName public.domain.co.uk
        ServerAlias www.public.domain.co.uk

        RewriteEngine on
        RewriteRule ^/\.well-known/carddav https://public.domain.co.uk/remote.php/dav/ [R=301,L]
        RewriteRule ^/\.well-known/caldav https://public.domain.co.uk/remote.php/dav/ [R=301,L]

        SSLProxyEngine on
        SSLProxyVerify none
        SSLProxyCheckPeerCN off
        SSLProxyCheckPeerName off

        ProxyPass / https://my.internal.domain.co.uk/ nocanon
        ProxyPassReverse / https://my.internal.domain.co.uk/

        Header always set Strict-Transport-Security "max-age=15768000; preload"

        RequestHeader set X-Forwarded-SSL "1"
        RequestHeader set X-Forwarded-Proto "https" env=HTTPS

        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateFile /etc/letsencrypt/live/public.domain.co.uk/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/public.domain.co.uk/privkey.pem
</VirtualHost>

My NextCloud config.php:

<?php
$CONFIG = array (
  'passwordsalt' => '*********************************',
  'secret' => '*********************************************************************',
  'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => 'public.domain.co.uk',
    2 => 'my.internal.domain.co.uk'
  ),
  'datadirectory' => '/var/www/nextcloud-data',
  'dbtype' => 'mysql',
  'version' => '27.1.1.0',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'nextcloud',
  'dbpassword' => '****************************',
  'installed' => true,
  'instanceid' => '*************',
  'memcache.local' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
    'timeout' => 0.0,
  ),
  'filelocking.enabled' => true,
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'log_type' => 'file',
  'logfile' => '/var/www/nextcloud-data/nextcloud.log',
  'loglevel' => 3,
  'enforce_theme' => '',
  'default_locale' => 'en_GB',
  'default_phone_region' => 'UK',
  'maintenance' => false,

  'trusted_proxies'   => ['192.168.42.9'],
  'overwritehost'     => 'public.domain.co.uk',
  'overwriteprotocol' => 'https',
  'overwritewebroot'  => '/',
  'overwritecondaddr' => '^192\.168\.42\.9$',
  'overwrite.cli.url' => 'https://public.domain.co.uk/',

  'forwarded_for_headers' => array('HTTP_X_FORWARDED_FOR'),
);

The reverse proxy now preserves the public host header. Simples.

So, you can have two names for the same host and it shouldn’t be a problem so long as the public name is passed through and everything else is configured correctly.

I feel so stupid.

Thanks again for your help :slight_smile: <3

1 Like