Could not establish connection with FQDN as URL, working with container_name (docker compose)

Hi there! I’m trying to setup a VPS with Nextcloud and Collabora in docker-compose behind a nginx reverse proxy (jwilder’s + let’s encrypt companion, not modified). I spent the day at it (learning a lot…).

At this point, in the Nextcloud interface, in the Collabora Online settings, I can connect to collabora via https and using the container name: https://nextcloud-collabora:9980. However, when I open a .ods or .odt document in my nextcloud files, I get no response for:

https://nextcloud-collabora:9980/loleaflet/46545ce/loleaflet.html?WOPISrc=https%3A%2F%2Fdrive.domain.tld%2Findex.php%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F141183_ocksbm4b6wf3&title=documentName%20-%20Copy.ods&lang=en&closebutton=1&revisionhistory=1

With Brave Browser showing the sad face sheet of paper: nextcloud-collabora ’s server IP address could not be found.

To fix this, I am trying to instead put my FQDN to my Collabora server in the URL textbox (https://office.domain.tld:9980). However, I then get: Could not establish connection to the Collabora Online server.

I am at a loss here, I don’t know why my nextcloud instance won’t talk to my Collabora instance over the reverse proxy. Also, when I try to reach https://office.domain.tld, I get “OK” displayed in the top left, which I think is normal. But when I try to reach https://office.domain.tld/loleaflet/dist/admin/admin.html, I get a prompt that never lets me log in. The docker-compose log says:

nextcloud-collabora | wsd-00008-00046 2021-01-09 07:12:31.739516 [ websrv_poll ] WRN  client - server version mismatch, disabling browser cache. Expected: 46545ce| wsd/FileServer.cpp:285
nextcloud-collabora | wsd-00008-00046 2021-01-09 07:12:31.739665 [ websrv_poll ] ERR  FileServerRequestHandler::NotAuthenticated: No authentication information found| wsd/FileServer.cpp:476

nslookup office.domain.tls returns the external (WAN) IP from DNS Server 8.8.8.8

The VPS runs a Ubuntu 20.04 server with NExtcloud 20.0.2, Collabora Online app 3.7.11, Collabora server 6.4.3.1 (latest).

Here is my docker-compose.yml:
version: ‘3.8’

volumes:
  nextcloud:
  nextcloud-db:

services:
  nextcloud-db:
    image: postgres:13.1
    container_name: "nextcloud-db"
    restart: always
    volumes:
      - "./nextcloud-db:/var/lib/postgresql/data"
    environment:
      - POSTGRES_ROOT_PASSWORD=${ROOT_PASSWORD}
      - POSTGRES_PASSWORD=${APP_PASSWORD}
      - POSTGRES_DB=nextcloud
      - POSTGRES_USER=${USERNAME}

  nextcloud:
    image: nextcloud:20.0.2-fpm
    container_name: "nextcloud"
    links:
      - nextcloud-db
    volumes:
      - "./nextcloud:/var/www/html"
    restart: always
    environment:
      - POSTGRES_HOST=nextcloud-db
      - POSTGRES_PASSWORD=${APP_PASSWORD}
      - POSTGRES_DB=nextcloud
      - POSTGRES_USER=${USERNAME}

  web:
    build: ./web
    container_name: "nextcloud-web"
    restart: always
    volumes:
      - "./nextcloud:/var/www/html:ro"
      - "../reverse-proxy/certs/office.${DOMAIN}:/etc/nginx/certs:ro"
    environment:
      - VIRTUAL_HOST=drive.${DOMAIN}
      - LETSENCRYPT_HOST=drive.${DOMAIN}
      - LETSENCRYPT_EMAIL=${USERNAME}@${DOMAIN}
    depends_on:
      - nextcloud
    networks:
      - network-proxy
      - default

  collabora:
    image: collabora/code
    container_name: "nextcloud-collabora"
    networks:
      - default
      - network-proxy
    ports:
      - 9980:9980
    depends_on:
      - web
    cap_add:
     - MKNOD
    environment:
      - username=admin
      - password=${APP_PASSWORD}
      # Domain the service should be accessed from:
      - domain=drive\.${DOMAIN}
      - DONT_GEN_SSL_CERT="True"
      #
      - VIRTUAL_PROTO=https
      - VIRTUAL_PORT=443
      - VIRTUAL_HOST=office.${DOMAIN}
      - LETSENCRYPT_HOST=office.${DOMAIN}
      #
      # Extra parameters to Collabora, see also
      # https://www.collaboraoffice.com/code/nginx-reverse-proxy/:
      # SSL terminates at the proxy
      - extra_params=--o:ssl.enable=true
      - TZ=America/Toronto
    volumes:
      - "/etc/timezone:/etc/timezone"
      - "/etc/localtime:/etc/localtime"
      - "../reverse-proxy/certs/office.${DOMAIN}/key.pem:/etc/loolwsd/key.pem:ro"
      - "../reverse-proxy/certs/office.${DOMAIN}/cert.pem:/etc/loolwsd/cert.pem:ro"
      - "../reverse-proxy/certs/office.${DOMAIN}/chain.pem:/etc/loolwsd/ca-chain.cert.pem:ro"

  coturn:
    image: instrumentisto/coturn
    container_name: nextcloud-coturn
    restart: unless-stopped
    ports:
      - "3478:3478/tcp"
      - "3478:3478/udp"
    command:
      - -n
      - --log-file=stdout
      - --min-port=49160
      - --max-port=49200
      - --realm=drive.${DOMAIN}
      - --use-auth-secret
      - --static-auth-secret=${APP_PASSWORD}


networks:
  network-proxy:
    external: true

Here is nginx.conf, used by the web service. It has a 2nd server block for Collabora, which I’m not sure is needed, taken from here: https://www.collaboraoffice.com/code/nginx-reverse-proxy/. I use a script to copy/paste the config, that’s why there is a “\” before every “$”
worker_processes auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '\$remote_addr - \$remote_user [\$time_local] "\$request" '
                      '\$status \$body_bytes_sent "\$http_referer" '
                      '"\$http_user_agent" "\$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    set_real_ip_from  10.0.0.0/8;
    set_real_ip_from  172.16.0.0/12;
    set_real_ip_from  192.168.0.0/16;
    real_ip_header    X-Real-IP;

    #gzip  on;

    upstream php-handler {
        server nextcloud:9000;
    }

    server {
        listen 80;

        # Add headers to serve security related headers
        # Before enabling Strict-Transport-Security headers please read into this
        # topic first.
        #add_header Strict-Transport-Security "max-age=15768000; includeSubDOMAINs; preload;" always;
        #
        # WARNING: Only add the preload option once you read about
        # the consequences in https://hstspreload.org/. This option
        # will add the DOMAIN to a hardcoded list that is shipped
        # in all major browsers and getting removed from this list
        # could take several months.
        add_header Referrer-Policy "no-referrer" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Download-Options "noopen" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Permitted-Cross-DOMAIN-Policies "none" always;
        add_header X-Robots-Tag "none" always;
        add_header X-XSS-Protection "1; mode=block" always;

        # Remove X-Powered-By, which is an information leak
        fastcgi_hide_header X-Powered-By;

        # Path to the root of your installation
        root /var/www/html;

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        # The following 2 rules are only needed for the user_webfinger app.
        # Uncomment it if you're planning to use this app.
        #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
        #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;

        # The following rule is only needed for the Social app.
        # Uncomment it if you're planning to use this app.
        #rewrite ^/.well-known/webfinger /public.php?service=webfinger last;

        location = /.well-known/carddav {
            return 301 \$scheme://\$host:\$server_port/remote.php/dav;
        }

        location = /.well-known/caldav {
            return 301 \$scheme://\$host:\$server_port/remote.php/dav;
        }

        # set max upload size
        client_max_body_size 10G;
        fastcgi_buffers 64 4K;

        # Enable gzip but do not remove ETag headers
        gzip on;
        gzip_vary on;
        gzip_comp_level 4;
        gzip_min_length 256;
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-DOMAIN-policy;

        # Uncomment if your server is build with the ngx_pagespeed module
        # This module is currently not supported.
        #pagespeed off;

        location / {
            rewrite ^ /index.php;
        }

        location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
            deny all;
        }
        location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
            deny all;
        }

        location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy)\.php(?:\$|\/) {
            fastcgi_split_path_info ^(.+?\.php)(\/.*|)\$;
            set \$path_info \$fastcgi_path_info;
            try_files \$fastcgi_script_name =404;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
            fastcgi_param PATH_INFO \$path_info;
            # fastcgi_param HTTPS on;

            # Avoid sending the security headers twice
            fastcgi_param modHeadersAvailable true;

            # Enable pretty urls
            fastcgi_param front_controller_active true;
            fastcgi_pass php-handler;
            fastcgi_intercept_errors on;
            fastcgi_request_buffering off;
        }
		
        location ^~ /hosting/capabilities {
            proxy_pass https://127.0.0.1:9980;
            proxy_set_header Host \$http_host;
        }

        location ~ ^\/(?:updater|oc[ms]-provider)(?:\$|\/) {
            try_files \$uri/ =404;
            index index.php;
        }

        # Adding the cache control header for js, css and map files
        # Make sure it is BELOW the PHP block
        location ~ \.(?:css|js|woff2?|svg|gif|map)\$ {
            try_files \$uri /index.php\$request_uri;
            add_header Cache-Control "public, max-age=15778463";
            # Add headers to serve security related headers (It is intended to
            # have those duplicated to the ones above)
            # Before enabling Strict-Transport-Security headers please read into
            # this topic first.
            #add_header Strict-Transport-Security "max-age=15768000; includeSubDOMAINs; preload;" always;
            #
            # WARNING: Only add the preload option once you read about
            # the consequences in https://hstspreload.org/. This option
            # will add the DOMAIN to a hardcoded list that is shipped
            # in all major browsers and getting removed from this list
            # could take several months.
            add_header Referrer-Policy "no-referrer" always;
            add_header X-Content-Type-Options "nosniff" always;
            add_header X-Download-Options "noopen" always;
            add_header X-Frame-Options "SAMEORIGIN" always;
            add_header X-Permitted-Cross-DOMAIN-Policies "none" always;
            add_header X-Robots-Tag "none" always;
            add_header X-XSS-Protection "1; mode=block" always;

            # Optional: Don't log access to assets
            access_log off;
        }

        location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)\$ {
            try_files \$uri /index.php\$request_uri;
            # Optional: Don't log access to other assets
            access_log off;
        }
    }
	
	
	
    server {
        listen       443 ssl;
        server_name  office.${DOMAIN};

        ssl_certificate /etc/nginx/certs/cert.pem;
        ssl_certificate_key /etc/nginx/certs/key.pem;

        # static files
        location ^~ /loleaflet {
            proxy_pass https://localhost:9980;
            proxy_set_header Host \$http_host;
        }

        # WOPI discovery URL
        location ^~ /hosting/discovery {
            proxy_pass https://localhost:9980;
            proxy_set_header Host \$http_host;
        }

        # Capabilities
        location ^~ /hosting/capabilities {
            proxy_pass https://localhost:9980;
            proxy_set_header Host \$http_host;
        }

        # main websocket
        location ~ ^/lool/(.*)/ws\$ {
            proxy_pass https://localhost:9980;
            proxy_set_header Upgrade \$http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host \$http_host;
            proxy_read_timeout 36000s;
        }

        # download, presentation and image upload
        location ~ ^/lool {
            proxy_pass https://localhost:9980;
            proxy_set_header Host \$http_host;
        }

        # Admin Console websocket
        location ^~ /lool/adminws {
            proxy_pass https://localhost:9980;
            proxy_set_header Upgrade \$http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host \$http_host;
            proxy_read_timeout 36000s;
        }
    }
}

And here is Nextcloud’s config.php:

<?php
$CONFIG = array (
  '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,
    ),
  ),
  'instanceid' => 'asdasdasdasd',
  'passwordsalt' => 'asdasdasdasdasd',
  'secret' => 'asdasdasdasdasd',
  'trusted_domains' =>
  array (
    0 => 'drive.domain.tld',
  ),
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'pgsql',
  'version' => '20.0.2.2',
  'overwrite.cli.url' => 'http://drive.domain.tld',
  'dbname' => 'nextcloud',
  'dbhost' => 'nextcloud-db',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'dbuser' => 'oc_admin',
  'dbpassword' => 'asdasdasdasd',
  'installed' => true,
  'overwritehost' => 'drive.domain.tld',
  'overwriteprotocol' => 'https',
  'maintenance' => false,
);

I have not added anything to my hosts file. I think that covers the information I have.

Update: I am now at the step where I get an error message in Nextcloud when I try to open a document: Failed to read document from storage. Please contact your storage server administrator.. The docker logs show the following when the file fails to load:

nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.541747 [ docbroker_001 ] ERR  Cannot get file info from WOPI storage uri [https://drive.domain.tld/index.php/apps/richdocuments/wopi/files/139139_ockeqm4b6wf3?access_token=eudg5J5J3Eqwx0rJy7CLKRtPdnewuY&access_token_ttl=0]. Error: Timeout: connect timed out: 123.456.789.012:443| wsd/Storage.cpp:632
nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.541836 [ docbroker_001 ] ERR  loading document exception: Timeout| wsd/DocumentBroker.cpp:1427
nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.541858 [ docbroker_001 ] ERR  Failed to add session to [/index.php/apps/richdocuments/wopi/files/139139_ocwebm4b6wf3] with URI [https://drive.domain.tld/index.php/apps/richdocuments/wopi/files/139139_ocksbasb6wf3?access_token=eudg5J5J3asdwa0rJy7CLKRtPdnwEEuY&access_token_ttl=0]: Timeout| wsd/DocumentBroker.cpp:1389
nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.541884 [ docbroker_001 ] ERR  Error while loading : Timeout| wsd/LOOLWSD.cpp:3419
nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.542037 [ docbroker_001 ] ERR  No DocBroker found, or DocBroker marked to be destroyed. Terminating session ToClient-009| wsd/ClientSession.cpp:331
nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.542387 [ docbroker_001 ] ERR  No DocBroker found, or DocBroker marked to be destroyed. Terminating session ToClient-009| wsd/ClientSession.cpp:331
nextcloud-collabora | wsd-00008-00034 2021-01-09 18:40:19.579066 [ docbroker_001 ] ERR  Invalid or unknown session [009] to remove.| wsd/DocumentBroker.cpp:1466
nextcloud-collabora | sh: 1: /usr/bin/loolmount: Operation not permitted
nextcloud-collabora | frk-00027-00027 2021-01-09 18:40:22.225782 [ forkit ] ERR  Failed to unmount [/opt/lool/child-roots/o9QachUfvXwXbesQ/tmp].| common/JailUtil.cpp:68
nextcloud-collabora | sh: 1: /usr/bin/loolmount: Operation not permitted
nextcloud-collabora | frk-00027-00027 2021-01-09 18:40:22.248603 [ forkit ] ERR  Failed to unmount [/opt/lool/child-roots/o9QachUfvXwXbesQ/lo].| common/JailUtil.cpp:68
nextcloud-collabora | sh: 1: /usr/bin/loolmount: Operation not permitted
nextcloud-collabora | frk-00027-00027 2021-01-09 18:40:22.274010 [ forkit ] ERR  Failed to unmount [/opt/lool/child-roots/o9QachUfvXwXbesQ].| common/JailUtil.cpp:68

Not there yet, but getting there.
I am now using https://office.domain.tld:9980 with certificate verification to connect to the server successfully. I also just noticed that I get the following when entering the URL and clicking the “save” button:

[ websrv_poll ] WRN  convert-to: Requesting address is denied: ::ffff:172.28.0.1| wsd/LOOLWSD.cpp:2300

What I did:

  1. Remove the 2nd server block in nginx.conf. I realised this was supposed to be used for the reverse proxy, not with the reverse proxy. Since I use jwilder’s nginx reverse proxy for other containers as well, I don’t need this.

I updated the docker-compose.yml:

  collabora:
    image: collabora/code
    container_name: "nextcloud-collabora"
	restart: unless-stopped
    networks:
      - default
      - network-proxy
    ports:
      - 9980:9980
    depends_on:
      - web
    cap_add:
     - MKNOD
    environment:
      - username=admin
      - password=${APP_PASSWORD}
      # Domain the service should be accessed from:
      - domain=drive\.${DOMAIN}
      - DONT_GEN_SSL_CERT="True"
      #
      - VIRTUAL_PROTO=https
      - VIRTUAL_PORT=443
      - VIRTUAL_HOST=office.${DOMAIN}
      - LETSENCRYPT_HOST=office.${DOMAIN}
      #
      - TZ=America/Toronto
    volumes:
      - "/etc/timezone:/etc/timezone"
      - "/etc/localtime:/etc/localtime"
      - "../reverse-proxy/certs/office.${DOMAIN}/key.pem:/etc/loolwsd/key.pem:ro"
      - "../reverse-proxy/certs/office.${DOMAIN}/cert.pem:/etc/loolwsd/cert.pem:ro"
      - "../reverse-proxy/certs/office.${DOMAIN}/chain.pem:/etc/loolwsd/ca-chain.cert.pem:ro"

I still get the “OK” message at https://drive.domain.tld, but the admin page at https://drive.domain.tld/loleaflet/dist/admin/admin.html still does nothing. Logs say the same thing.

I removed ‘overwritehost’ => ‘drive.domain.tld’, from my nextcloud config.php and it does not seem to change anything.

After two full days trying to get this to work, I am giving up and switching to OnlyOffice, which took about 2 minutes to set up and get to work with partners. It also comes with a connected desktop app, which is a big plus for me. I’m a little sad to go back to .xlsx files, though.

I managed to get a little further (a.k.a. changing the error type) by increasing the timeout value in NextCloud’s lib/http/client/Client.php, and the connection timeout value in Collabora’s /etc/loolwsd/loolwsd.xml, but made no progress on the result.

what do you expect here? localhost:9980 isn’t the hosts port 9980. it the container ones. you ask your nginx to connect inside it’s container to port 9980. each container and the host has it’s own localhost/127.0.0.1.

it should be:

        location ^~ /hosting/capabilities {
            proxy_pass https://nextcloud-collabora:9980;
            proxy_set_header Host \$http_host;

OnlyOffice won’t be reachable on localhost either. :wink:

in case you are looking for a kind of reference installation:

Thanks for taking the time to look at this. I understand a bit better what’s going on now. I tried your suggestion and updated, but I still got the same error message: Timeout.

I also managed to access the admin interface by removing special characters from my password.

I also tried using expose instead of ports in my docker-compose.yml file, in conjunction with the settings from Setting up Nginx reverse proxy - Collabora Office and Collabora Online (the one for ssl.enable=true) in nginx reverse proxy’s vhost.d/office.domain.tld, but I can’t contact the server anymore that way, with or without the port specified. The admin interface works if I replace localhost with nextcloud-collabora in that file.

I read the definitions for ports and expose, and think I understand them, but I don’t get why expose doesn’t work, especially with - VIRTUAL_PORT=9980.

As for OnlyOfice, I installed the document server and the desktop app, and the two connected right away, and I tested simultaneous modifications with a partner: no problem. People say there are data loss issues with the document server app, so I will transfer to the full server in the future, probably with OO Community Server as it offers integrated features (mail, CRM, projects) that should simplify things significantly for me. It doesn’t seem to have as much support, though, so things better run out of the box :wink:

For what it’s work I get OP’s error with Brave but not Firefox.

I’m interested in finding a solution.

I have been using this template docker-compose file to host my Nextcloud + Collabora Office:

It is part of this pull request that got not/never accepted: