NextCloud All-In-One Docker behind router and reverse proxy, cannot talk to https://nextcloud.mydomain.com/hosting/capabilities or Collabora Office

Support intro

Sorry to hear you’re facing problems :slightly_frowning_face:

help.nextcloud.com is for home/non-enterprise users. If you’re running a business, paid support can be accessed via portal.nextcloud.com where we can ensure your business keeps running smoothly.

In order to help you as quickly as possible, before clicking Create Topic please provide as much of the below as you can. Feel free to use a pastebin service for logs, otherwise either indent short log examples with four spaces:

example

Or for longer, use three backticks above and below the code snippet:

longer
example
here

Some or all of the below information will be requested if it isn’t supplied; for fastest response please provide as much as you can :heart:

Nextcloud version (eg, 20.0.5): 27.1.0
Operating system and version (eg, Ubuntu 20.04): Debian GNU/Linux 12 (bookworm)
Apache or nginx version (eg, Apache 2.4.25): Apache/2.4.57 (Debian)
PHP version (eg, 7.4): 7.4.33-1+deb11u3

The issue you are facing:

According to the NextCloud AIO dashboard, the Collabora server is running:
image

However, when I try to set up NextCloud Office in the admin panel, telling it that the Collabora office suite is hosted on the same subdomain and port as NextCloud itself, I get this:

I have the NextCloud AIO docker container running behind an Apache reverse proxy, of course, which is how I’m getting it to be on a subdomain, but I took my Apache2 and docker compose configurations directly from the official example one in the reverse proxy documentation, so shouldn’t this work? Port 443 on that nextcloud subdomain is being routed to port 11000 under the hood, which then connects to the docker container.

Is this the first time you’ve seen this error? (Y/N): Y

Steps to replicate it:

  1. Install and set up nextcloud aio behind a reverse proxy using the configuration examples for apache2 and docker compose.
  2. Go through the standard setup process, try to enable NextCloud Office
  3. Profit???

The output of your Nextcloud log in Admin > Logging:

It’s just this over and over:

{"reqId":"81xTPaVcYmdTyhef68XD","level":3,"time":"2023-10-15T16:42:17+00:00","remoteAddr":"68.232.112.106","user":"admin","app":"richdocuments","method":"POST","url":"/apps/text/session/push","message":"Failed to fetch the Collabora capabilities endpoint: cURL error 28: Connection timed out after 45000 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://nextcloud.mydomain.com/hosting/capabilities","userAgent":"Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/118.0","version":"27.1.0.7","exception":{"Exception":"GuzzleHttp\\Exception\\ConnectException","Message":"cURL error 28: Connection timed out after 45000 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://nextcloud.mydomain.com/hosting/capabilities","Code":0,"Trace":[{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php","line":158,"function":"createRejection","class":"GuzzleHttp\\Handler\\CurlFactory","type":"::","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php","line":110,"function":"finishError","class":"GuzzleHttp\\Handler\\CurlFactory","type":"::","args":[["GuzzleHttp\\Handler\\CurlHandler"],"*** sensitive parameters replaced ***",["GuzzleHttp\\Handler\\CurlFactory"]]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Handler/CurlHandler.php","line":47,"function":"finish","class":"GuzzleHttp\\Handler\\CurlFactory","type":"::","args":[["GuzzleHttp\\Handler\\CurlHandler"],"*** sensitive parameters replaced ***",["GuzzleHttp\\Handler\\CurlFactory"]]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Middleware.php","line":137,"function":"__invoke","class":"GuzzleHttp\\Handler\\CurlHandler","type":"->","args":["*** sensitive parameters replaced ***","*** sensitive parameters replaced ***"]},{"file":"/var/www/html/lib/private/Http/Client/DnsPinMiddleware.php","line":114,"function":"GuzzleHttp\\{closure}","class":"GuzzleHttp\\Middleware","type":"::","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php","line":35,"function":"OC\\Http\\Client\\{closure}","class":"OC\\Http\\Client\\DnsPinMiddleware","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Middleware.php","line":31,"function":"__invoke","class":"GuzzleHttp\\PrepareBodyMiddleware","type":"->","args":["*** sensitive parameters replaced ***","*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/RedirectMiddleware.php","line":71,"function":"GuzzleHttp\\{closure}","class":"GuzzleHttp\\Middleware","type":"::","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Middleware.php","line":63,"function":"__invoke","class":"GuzzleHttp\\RedirectMiddleware","type":"->","args":["*** sensitive parameters replaced ***","*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/HandlerStack.php","line":75,"function":"GuzzleHttp\\{closure}","class":"GuzzleHttp\\Middleware","type":"::","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Client.php","line":331,"function":"__invoke","class":"GuzzleHttp\\HandlerStack","type":"->","args":["*** sensitive parameters replaced ***","*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Client.php","line":168,"function":"transfer","class":"GuzzleHttp\\Client","type":"->","args":["*** sensitive parameters replaced ***","*** sensitive parameters replaced ***"]},{"file":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Client.php","line":187,"function":"requestAsync","class":"GuzzleHttp\\Client","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/lib/private/Http/Client/Client.php","line":230,"function":"request","class":"GuzzleHttp\\Client","type":"->","args":["*** sensitive parameters replaced ***","https://nextcloud.mydomain.com/hosting/capabilities",["/mnt/ncdata/files_external/rootcerts.crt",45,[true],["Nextcloud Server Crawler","gzip"],true]]},{"file":"/var/www/html/custom_apps/richdocuments/lib/Service/CapabilitiesService.php","line":135,"function":"get","class":"OC\\Http\\Client\\Client","type":"->","args":["https://nextcloud.mydomain.com/hosting/capabilities",[45,[true]]]},{"file":"/var/www/html/custom_apps/richdocuments/lib/Service/CapabilitiesService.php","line":73,"function":"refetch","class":"OCA\\Richdocuments\\Service\\CapabilitiesService","type":"->","args":[]},{"file":"/var/www/html/custom_apps/richdocuments/lib/AppInfo/Application.php","line":90,"function":"getCapabilities","class":"OCA\\Richdocuments\\Service\\CapabilitiesService","type":"->","args":[]},{"file":"/var/www/html/lib/private/AppFramework/Bootstrap/FunctionInjector.php","line":66,"function":"OCA\\Richdocuments\\AppInfo\\{closure}","class":"OCA\\Richdocuments\\AppInfo\\Application","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/html/lib/private/AppFramework/Bootstrap/BootContext.php","line":50,"function":"injectFn","class":"OC\\AppFramework\\Bootstrap\\FunctionInjector","type":"->","args":[["Closure"]]},{"file":"/var/www/html/custom_apps/richdocuments/lib/AppInfo/Application.php","line":145,"function":"injectFn","class":"OC\\AppFramework\\Bootstrap\\BootContext","type":"->","args":[["Closure"]]},{"file":"/var/www/html/lib/private/AppFramework/Bootstrap/Coordinator.php","line":200,"function":"boot","class":"OCA\\Richdocuments\\AppInfo\\Application","type":"->","args":[["OC\\AppFramework\\Bootstrap\\BootContext"]]},{"file":"/var/www/html/lib/private/App/AppManager.php","line":437,"function":"bootApp","class":"OC\\AppFramework\\Bootstrap\\Coordinator","type":"->","args":["richdocuments"]},{"file":"/var/www/html/lib/private/App/AppManager.php","line":216,"function":"loadApp","class":"OC\\App\\AppManager","type":"->","args":["richdocuments"]},{"file":"/var/www/html/lib/private/legacy/OC_App.php","line":126,"function":"loadApps","class":"OC\\App\\AppManager","type":"->","args":[[]]},{"file":"/var/www/html/lib/base.php","line":1048,"function":"loadApps","class":"OC_App","type":"::","args":[]},{"file":"/var/www/html/index.php","line":36,"function":"handleRequest","class":"OC","type":"::","args":[]}],"File":"/var/www/html/3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php","Line":210,"message":"Failed to fetch the Collabora capabilities endpoint: cURL error 28: Connection timed out after 45000 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://nextcloud.mydomain.com/hosting/capabilities","exception":[],"CustomMessage":"Failed to fetch the Collabora capabilities endpoint: cURL error 28: Connection timed out after 45000 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://nextcloud.mydomain.com/hosting/capabilities"},"id":"652c1669de6bc"}

The output of your config.php file in /path/to/nextcloud (make sure you remove any identifiable information!):

<?php
$CONFIG = array (
  'one-click-instance' => true,
  'one-click-instance.user-limit' => 100,
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
    ),
  ),
  'check_data_directory_permissions' => false,
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => 'nextcloud-aio-redis',
    'password' => '0e7bccfd7c50f8f5ce053f8908a1c9eef2cbe57167e085f9',
    'port' => 6379,
  ),
  'overwritehost' => 'nextcloud.mydomain.com',
  'overwriteprotocol' => 'https',
  'passwordsalt' => '5i/iyDDaXJDxk0r2F76GI6NyWaARWo',
  'secret' => '53AZP6AdQE5c9OPWSi2AVDX9hxD3rUB7NkWbAjBQG5aAgrw6',
  'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => 'nextcloud.mydomain.com',
  ),
  'datadirectory' => '/mnt/ncdata',
  'dbtype' => 'pgsql',
  'version' => '27.1.0.7',
  'overwrite.cli.url' => 'https://nextcloud.mydomain.com/',
  'dbname' => 'nextcloud_database',
  'dbhost' => 'nextcloud-aio-database',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'oc_nextcloud',
  'dbpassword' => '47937cdec5d673db1d0ad1bb3d8eb46cc9cbcaafd2f6ad4e',
  'installed' => true,
  'instanceid' => 'oc2qt853149k',
  'maintenance' => false,
  'loglevel' => '2',
  'log_type' => 'file',
  'logfile' => '/var/www/html/data/nextcloud.log',
  'log_rotate_size' => '10485760',
  'log.condition' => 
  array (
    'apps' => 
    array (
      0 => 'admin_audit',
    ),
  ),
  'preview_max_x' => '2048',
  'preview_max_y' => '2048',
  'jpeg_quality' => '60',
  'enabledPreviewProviders' => 
  array (
    1 => 'OC\\Preview\\Image',
    2 => 'OC\\Preview\\MarkDown',
    3 => 'OC\\Preview\\MP3',
    4 => 'OC\\Preview\\TXT',
    5 => 'OC\\Preview\\OpenDocument',
    6 => 'OC\\Preview\\Movie',
    7 => 'OC\\Preview\\Krita',
    0 => 'OC\\Preview\\Imaginary',
  ),
  'enable_previews' => true,
  'upgrade.disable-web' => true,
  'mail_smtpmode' => 'smtp',
  'trashbin_retention_obligation' => 'auto, 30',
  'versions_retention_obligation' => 'auto, 30',
  'activity_expire_days' => '30',
  'simpleSignUpLink.shown' => false,
  'share_folder' => '/Shared',
  'one-click-instance.link' => 'https://nextcloud.com/all-in-one/',
  'upgrade.cli-upgrade-link' => 'https://github.com/nextcloud/all-in-one/discussions/2726',
  'updatedirectory' => '/nc-updater',
  'davstorage.request_timeout' => 3600,
  'htaccess.RewriteBase' => '/',
  'dbpersistent' => true,
  'files_external_allow_create_new_local' => false,
  'trusted_proxies' => 
  array (
    0 => '127.0.0.1',
    1 => '::1',
  ),
  'allow_local_remote_servers' => true,
  'preview_imaginary_url' => 'http://nextcloud-aio-imaginary:9000',
  'mail_smtpsecure' => 'ssl',
  'mail_sendmailmode' => 'smtp',
  'mail_from_address' => 'nextcloud',
  'mail_domain' => 'mydomain.com',
  'twofactor_enforced' => 'true',
  'twofactor_enforced_groups' => 
  array (
  ),
  'twofactor_enforced_excluded_groups' => 
  array (
  ),
);

The output of your Apache/nginx/system log in /var/log/____: attempting to access /hosting/capabilities or connect to the Collabora instance doesn’t appear to produce any log output at all.

Hi, can you follow https://github.com/nextcloud/all-in-one/discussions/1358?

Already did, just forgot to post the output. Here you go:

612a0fcf2ad5:/var/www/html# curl -vvv https://$NC_DOMAIN:443/hosting/discovery
exit
* processing: https://nextcloud.mydomain.com:443/hosting/discovery
*   Trying 68.232.112.106:443...
* connect to 68.232.112.106 port 443 failed: Operation timed out
* Failed to connect to nextcloud.mydomain.com port 443 after 129451 ms: Couldn't connect to server
* Closing connection
curl: (28) Failed to connect to nextcloud.mydomain.com port 443 after 129451 ms: Couldn't connect to server
exit

It should be noted that I can absolutely visit https://nextcloud.mydomain.com in my browser and it works just fine, but when I visit the /hosting/discovery subdirectory, it doesn’t respond in my browser either.

Did you check if the collabora container is running correctly?

I checked the logs on the AIO dashboard and it’s hard to tell, but I don’t see any obvious error messages. Most of the logs are just this on repeat:

wsd-00007-00007 2023-10-15 13:25:17.415221 -0400 [ coolwsd ] INF  Waiting for a new child for a max of 20000ms| wsd/COOLWSD.cpp:5714
wsd-00007-00018 2023-10-15 13:25:17.896988 -0400 [ prisoner_poll ] TRC  Poll completed with 0 live polls max (5000000us)(timedout)| net/Socket.cpp:360
wsd-00007-00018 2023-10-15 13:25:17.897064 -0400 [ prisoner_poll ] TRC  #7: Handling events of wakeup pipe: 0x0| net/Socket.cpp:364
wsd-00007-00018 2023-10-15 13:25:17.897086 -0400 [ prisoner_poll ] TRC  #16: Handling poll events of prisoner_poll at index 0 (of 1): 0x0| net/Socket.cpp:457
wsd-00007-00018 2023-10-15 13:25:17.897108 -0400 [ prisoner_poll ] TRC  Executing SocketDisposition of #16: Type::CONTINUE| net/Socket.cpp:689
wsd-00007-00018 2023-10-15 13:25:17.897130 -0400 [ prisoner_poll ] TRC  #16: setupPollFds getPollEvents: 0x1| net/Socket.hpp:845
wsd-00007-00018 2023-10-15 13:25:17.897149 -0400 [ prisoner_poll ] TRC  ppoll start, timeoutMicroS: 5000000 size 1| net/Socket.cpp:341
wsd-00007-00018 2023-10-15 13:25:22.902380 -0400 [ prisoner_poll ] TRC  Poll completed with 0 live polls max (5000000us)(timedout)| net/Socket.cpp:360
wsd-00007-00018 2023-10-15 13:25:22.902460 -0400 [ prisoner_poll ] TRC  #7: Handling events of wakeup pipe: 0x0| net/Socket.cpp:364
wsd-00007-00018 2023-10-15 13:25:22.902484 -0400 [ prisoner_poll ] TRC  #16: Handling poll events of prisoner_poll at index 0 (of 1): 0x0| net/Socket.cpp:457
wsd-00007-00018 2023-10-15 13:25:22.902507 -0400 [ prisoner_poll ] TRC  Executing SocketDisposition of #16: Type::CONTINUE| net/Socket.cpp:689
wsd-00007-00018 2023-10-15 13:25:22.902532 -0400 [ prisoner_poll ] TRC  #16: setupPollFds getPollEvents: 0x1| net/Socket.hpp:845
wsd-00007-00018 2023-10-15 13:25:22.902553 -0400 [ prisoner_poll ] TRC  ppoll start, timeoutMicroS: 5000000 size 1| net/Socket.cpp:341
wsd-00007-00018 2023-10-15 13:25:27.907839 -0400 [ prisoner_poll ] TRC  Poll completed with 0 live polls max (5000000us)(timedout)| net/Socket.cpp:360
wsd-00007-00018 2023-10-15 13:25:27.907918 -0400 [ prisoner_poll ] TRC  #7: Handling events of wakeup pipe: 0x0| net/Socket.cpp:364
wsd-00007-00018 2023-10-15 13:25:27.907942 -0400 [ prisoner_poll ] TRC  #16: Handling poll events of prisoner_poll at index 0 (of 1): 0x0| net/Socket.cpp:457
wsd-00007-00018 2023-10-15 13:25:27.907966 -0400 [ prisoner_poll ] TRC  Executing SocketDisposition of #16: Type::CONTINUE| net/Socket.cpp:689
wsd-00007-00018 2023-10-15 13:25:27.907989 -0400 [ prisoner_poll ] TRC  #16: setupPollFds getPollEvents: 0x1| net/Socket.hpp:845
wsd-00007-00018 2023-10-15 13:25:27.908011 -0400 [ prisoner_poll ] TRC  ppoll start, timeoutMicroS: 5000000 size 1| net/Socket.cpp:341

Update: I’m not sure what I changed, but I can now access https://nextcloud.mydomain.com/hosting/discovery from a browser and get a big ol’ XML file, but I still can’t curl that URL from within the nextcloud-aio-nextcloud docker container, it just times out. Which is why, I think, it can’t talk to itself to set up the Collabora server in the settings page. Does anyone know why a docker container might not be able to access its own public URL?

Okay, the problem seems to go even deeper. My server can’t ping or curl its own domain name or its own public IP.

1 Like

I was able to fix this on my server by just adding the domain name to my /etc/hosts file, so I added it to the extra_hosts for the master container, but that still doesn’t actually fix the problem within the actual nextcloud-aio-nextcloud container, so either I need to fix this with a different solution on my server or figure out a way to edit the /etc/hosts on the nextcloud sub-containers. Does anyone know anything about this?

Edit:

I used vi to edit the /etc/hosts file in nextcloud-aio-nextcloud and tried the curl command again, but no dice:

*   Trying 127.0.0.1:443...
* connect to 127.0.0.1 port 443 failed: Connection refused
* Failed to connect to nextcloud.mydomain.com port 443 after 0 ms: Couldn't connect to server
* Closing connection
curl: (7) Failed to connect to nextcloud.mydomain,com port 443 after 0 ms: Couldn't connect to server

Keep in mind that the exact same command, with the exact same lines in /etc/hosts, works on my server, and the same command, without any modifications to the hosts file, also works on every other computer I have.

Update: editing nextcloud.mydomain.com into /etc/hosts as localhost doesn’t work because that refers to the current container, not the server. So I’m back to the original problem of needing to figure out why the server and the docker containers can’t talk to their domain or public IP.

1 Like

Background

Okay, I figured it out. So, servers can’t talk to themselves by taking a round trip via the public IP or public domain name/URL of your server if you don’t have your router correctly configured (with hairpin NAT). In my case, I’m using a router provided by an ISP, so I need a workaround, because this means, putting in the actual URL of your nextcloud all in one instance into the “URL (and Port) of Collabora Online-server” text field actually will not work, because when you put that URL in, that’s the URL the nextcloud-aio-nextcloud docker container will use to talk to the nextcloud-aio-collabora docker container, which is on the same machine, so it’ll be one docker container trying to use a domain name that resolves to the public IP of the server it is running on to talk to another docker container running on the same server, which runs into that server-talking-to-itself problem.

Solution

What you have to do instead is find out the internal virtual IP address of your nextcloud-aio-collabora docker container using this command:

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nextcloud-aio-collabora

And then test it by running this command:

docker exec -it nextcloud-aio-nextcloud  curl -kvvv http://192.168.0.3:9980/hosting/discovery

If that works, then you’ve got the right IP address. So plug that into the URL field of the Nextcloud Office tab in the Administration settings, like so:

And that should work! Or at least, it seems to attempt to load the Collabora suite when I open relevant files now, it just times out, which I believe is for independent reasons.

Alternative Solution (important if you want to use HTTPS, since you need to use a reverse proxy to get it)

Alternatively, if you want to be able to use your server’s domain name in the text field and let your server’s reverse proxy (if it has one, as mine does) route connections to the appropriate subdomain to the appropriate port, you can get the internal virtual IP address for docker of your host machine using this command:

ip addr | grep docker0

pull out the IP address (will usually be 172.17.0.1), put it in the /etc/hosts file of your nextcloud-aio-nextcloud docker container with the following command:

docker exec -it nextcloud-aio-nextcloud echo "172.17.0.1        nextcloud.mydomain.com" >> /etc/hosts

and then enter your domain into the text field as above, now that your nextcloud container knows to talk to your server (and thus its reverse proxy) via its virtual IP address when given the domain name.

@szaimen maybe this should be noted somewhere, because this seems like it would effect anyone that tries to use nextcloud AIO with collabora enabled?

To add on to this, the next problem I faced was that nextcloud-aio-collabora wasn’t able to get anything, including files and json stuff, from nextcloud-aio-nextcloud. All I had to do to fix this was:

docker exec -u 0 -it nextcloud-aio-collabora echo "172.17.0.1 nextcloud.mydomain.com" >> /etc/hosts

and it worked! I have collabora running!

Hi, just wanted to point out that your solution is incorrect. Servers actually can talk to itself via the public ip-address if the network is correctly configured. Most likely your Router simply does not support Hairpin NAT.

Ah okay, thank you, my bad. I’ll edit my solution in a bit.

Hi. I had a similar problem and I solved it a different way. I hope this will add to the conversation.

I have a URL, nextcloud.example.com which maps to my public IP and Nextcloud is available externally. Internally at home, I am running Unbound DNS locally for name resolution. I’ve overridden the URL nextcloud.example.com so that it points to my local server’s private IP address. Seems to work well.

3 Likes

Yup that aligns conceptually with what I did, nice!

1 Like

Actually regarding this we have the following docs: GitHub - nextcloud/all-in-one: Nextcloud AIO stands for Nextcloud All-in-One and provides easy deployment and maintenance with most features included in this one Nextcloud instance.

1 Like

And that’s how it should be done! :slight_smile:

Btw. the concept is called: Split-horizon DNS, also known as split-view DNS, split-brain DNS, or just split DNS :slight_smile:

1 Like