Nextcloud Office can't connect to CODE behind reverse proxy: Requesting address is denied

Hello everybody,

I’m having a lot of trouble with setting up the docker image: collabora/code:latest behind my reverse proxy. My nextcloud instance (which has a similar setup and is working fine) can’t connect to the server. However inside admin settings of Nextcloud Office I get Collabora Online server is reachable. when I connect through https://code.foo.tld. The first docker log shows the error I get inside my code docker container. If I try to create/open any files with Nextcloud Office I just get the error: Document loading failed - Failed to load Nextcloud Office - please try again later.
I already did a lot of research and found multiple related topics stating exactly the same problem. Most of them however are multiple years old and I couldn’t find a solution that worked for me, which is why I am opening a new topic on this.
All relevant logs, configs and docker files should be listed below.
If you have any additional questions, feel free to let me know! I would be glad if someone could help me with this because I’ve been struggling setting it up for 2 days now!

I can reach https://code.foo.tld/hosting/discovery and https://code.foo.tld/hosting/capabilities, but https://code.foo.tld/cool or https://code.foo.tld/cool/adminws show me a blank page (it is reachable tho).
https://code.foo.tld shows me a 404 as expected.

Unnecessary/Private information in the following snippets is either left out or replaced with random words/letters.

docker log (code)

Ready to accept connections on port 9980.
dateTtime.num0Z
wsd-num1-num2 date time.num3 +0000 [ websrv_poll ] WRN  convert-to: Requesting address is denied: z.z.z.z| wsd/COOLWSD.cpp:3507
wsd-num1-num1 date time.num4 +0000 [ coolwsd ] WRN  Waking up dead poll thread [HttpSynReqPoll], started: false, finished: false| net/Socket.hpp:727

docker-compose.yml

version: "3.9"

services:
  reverse-proxy:
    image: "nginx:stable-alpine"
    container_name: "reverse-proxy"
    networks:
      frontend:
        ipv4_address: "x.x.x.x"
      backend:
        ipv4_address: "y.y.y.y"
    hostname: "reverse-proxy"
    "..."
  nextcloud-webserver:
    image: "nginx:stable-alpine"
    "..."
  nextcloud:
    image: "nextcloud:stable-fpm-alpine"
    "..."
    networks:
      frontend:
        ipv4_address: "x.x.x.x"
      backend:
        ipv4_address: "y.y.y.y"
    "..."
  nextcloud-database:
    image: "yobasystems/alpine-mariadb"
    "..."
  code-web:
    image: "nginx:stable-alpine"
    container_name: "code-web"
    networks:
      backend:
        ipv4_address: "y.y.y.y"
    hostname: "code-web"
    depends_on:
      - "code"
    "..."
  code:
    image: "collabora/code:latest"
    container_name: "code"
    networks:
      frontend:
        ipv4_address: "x.x.x.x"
      backend:
        ipv4_address: "y.y.y.y"
    hostname: "code"
    restart: "always"
    env_file:
      - "~/dock/code/code.env"

networks:
  frontend:
    internal: false
    ipam:
      config:
        - subnet: "x.x.x.x/x"
          gateway: "x.x.x.x"
  backend:
    internal: true
    ipam:
      config:
        - subnet: "y.y.y.y/y"
          gateway: "y.y.y.y"

~/dock/code/code.env

aliasgroup1="https://nextcloud.foo.tld:443"
DONT_GEN_SSL_CERT="true"
extra_params="--o:ssl.enable=false --o:ssl.termination=true"
password='password'
server_name="hostname-app"
username="username"

These are the relevant nginx configs. A lot of stuff is left out and any include statements are replaced with the files that they include.

reverse-proxy.conf

# https://nginx.org/en/docs/ngx_core_module.html#worker_processes
worker_processes auto;
# https://nginx.org/en/docs/ngx_core_module.html#error_log
error_log /var/log/nginx/error.log;
# https://nginx.org/en/docs/ngx_core_module.html#pid
pid /run/nginx.pid;
# https://nginx.org/en/docs/ngx_core_module.html#include
include /usr/share/nginx/modules/*.conf;

# https://nginx.org/en/docs/ngx_core_module.html#events
events {
    # https://nginx.org/en/docs/ngx_core_module.html#worker_connections
    worker_connections 1024;
}

# https://nginx.org/en/docs/http/ngx_http_core_module.html#http
http {
    # https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log
    access_log /var/log/nginx/access.log combined;
    # https://nginx.org/en/docs/ngx_core_module.html#include
    include /etc/nginx/mime.types;
    # https://nginx.org/en/docs/http/ngx_http_core_module.html#default_type
    default_type application/octet-stream;
    # https://nginx.org/en/docs/http/ngx_http_core_module.html#server
    server {
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#listen
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols
        ssl_protocols TLSv1.3;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM';
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ecdh_curve
        ssl_ecdh_curve secp384r1;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers
        ssl_prefer_server_ciphers on;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam
        ssl_dhparam /etc/nginx/certs/dhparam.pem;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache
        ssl_session_cache shared:SSL:10m;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_timeout
        ssl_session_timeout 10m;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets
        ssl_session_tickets off;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling
        ssl_stapling on;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling_verify
        ssl_stapling_verify on;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_verify_client
        ssl_verify_client on;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_client_certificate
        ssl_client_certificate /etc/nginx/certs/authenticated_origin_pull_ca.pem;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_trusted_certificate
        ssl_trusted_certificate /etc/nginx/certs/origin_ca_ecc_root.pem;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate
        ssl_certificate /etc/nginx/certs/foo.tld.pem;
        # https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate_key
        ssl_certificate_key /etc/nginx/certs/foo.tld.key;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name
        server_name code.foo.tld;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location / {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version
            proxy_http_version 1.1;
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_bypass
            proxy_cache_bypass $http_upgrade;
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
            proxy_read_timeout 90;
            # https://docs.oracle.com/en-us/iaas/Content/Balance/Reference/httpheaders.htm
            proxy_set_header X-Real-IP $remote_addr;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
            proxy_set_header X-Forwarded-Proto $scheme;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $host;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host
            proxy_set_header X-Forwarded-Host $host;
            # https://docs.oracle.com/en-us/iaas/Content/Balance/Reference/httpheaders.htm
            proxy_set_header X-Forwarded-Port $server_port;
            # https://nginx.org/en/docs/http/websocket.html
            ## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade
            proxy_set_header Upgrade $http_upgrade;
            ## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
            proxy_set_header Connection 'upgrade';
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-web:80/;
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect
            proxy_redirect http://hostname-web:80 https://code.foo.tld;
        }
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
        add_header Strict-Transport-Security "max-age=15780000; includeSubDomains; preload" always;
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
        add_header X-Frame-Options SAMEORIGIN;
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
        add_header X-XSS-Protection "1; mode=block";
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
        add_header X-Content-Type-Options nosniff;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens
        server_tokens off;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip
        gzip off;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile
        sendfile on;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#tcp_nopush
        tcp_nopush on;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#tcp_nodelay
        tcp_nodelay on;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout
        keepalive_timeout 65;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#types_hash_max_size
        types_hash_max_size 4096;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size
        client_max_body_size 0;
    }
    # https://nginx.org/en/docs/http/ngx_http_core_module.html#server
    server {
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#listen
        listen 80;
        listen [::]:80;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name
        server_name _;
        # https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return
        return 301 https://$host$request_uri;
    }
}

web-server.conf

# https://nginx.org/en/docs/ngx_core_module.html#worker_processes
worker_processes auto;
# https://nginx.org/en/docs/ngx_core_module.html#error_log
error_log /var/log/nginx/error.log;
# https://nginx.org/en/docs/ngx_core_module.html#pid
pid /run/nginx.pid;
# https://nginx.org/en/docs/ngx_core_module.html#include
include /usr/share/nginx/modules/*.conf;

# https://nginx.org/en/docs/ngx_core_module.html#events
events {
    # https://nginx.org/en/docs/ngx_core_module.html#worker_connections
    worker_connections 1024;
}

# https://nginx.org/en/docs/http/ngx_http_core_module.html#http
http {
    # https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log
    access_log /var/log/nginx/access.log combined;
    # https://nginx.org/en/docs/ngx_core_module.html#include
    include /etc/nginx/mime.types;
    # https://nginx.org/en/docs/http/ngx_http_core_module.html#default_type
    default_type application/octet-stream;
    #https://sdk.collaboraonline.com/docs/installation/Proxy_settings.html#reverse-proxy-settings-in-nginx-config-ssl-termination
    ########## START collabora ##########
    # https://nginx.org/en/docs/http/ngx_http_upstream_module.html#server
    server {
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#listen
        listen 80 default_server;
        listen [::]:80 default_server;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name
        server_name sub.foo.tld;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        ## STATIC FILES ##
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location ^~ /browser {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-app:9980;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $http_host;
        }
        ## WOPI DISCOVERY URL ##
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location ^~ /hosting/discovery {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-app:9980;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $http_host;
        }
        ## CAPABILITIES ##
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location ^~ /hosting/capabilities {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-app:9980;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $http_host;
        }
        ## DOWNLOAD, PRESENTATION & IMAGE UPLOAD ##
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location ~ ^/(c|l)ool {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-app:9980;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $http_host;
        }
        ## MAIN WEBSOCKET ##
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location ~ ^/cool/(.*)/ws$ {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-app:9980;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $http_host;
            # https://nginx.org/en/docs/http/websocket.html
            ## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade
            proxy_set_header Upgrade $http_upgrade;
            ## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
            proxy_set_header Connection "Upgrade";
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
            proxy_read_timeout 36000s;
        }
        ## ADMIN CONSOLE WEBSOCKET ##
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#location
        location ^~ /cool/adminws {
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
            proxy_pass http://hostname-app:9980;
            # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host
            proxy_set_header Host $http_host;
            # https://nginx.org/en/docs/http/websocket.html
            ## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade
            proxy_set_header Upgrade $http_upgrade;
            ## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
            proxy_set_header Connection "Upgrade";
            # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
            proxy_read_timeout 36000s;
        }
    ########## END collabora ##########
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
        add_header X-Frame-Options SAMEORIGIN;
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
        add_header X-XSS-Protection "1; mode=block";
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
        add_header X-Content-Type-Options nosniff;
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
        add_header Referrer-Policy "no-referrer";
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
        add_header X-Download-Options "noopen";
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
        add_header X-Permitted-Cross-Domain-Policies none;
        # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
        add_header X-Robots-Tag none;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens
        server_tokens off;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip
        gzip on;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_vary
        gzip_vary on;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_comp_level
        gzip_comp_level 4;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_min_length
        gzip_min_length 256;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_proxied
        gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
        # https://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_types
        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;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile
        sendfile on;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#tcp_nopush
        tcp_nopush on;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#tcp_nodelay
        tcp_nodelay on;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout
        keepalive_timeout 65;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#types_hash_max_size
        types_hash_max_size 4096;
        # https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size
        client_max_body_size 512M;
        # https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_buffers
        fastcgi_buffers 64 4K;
        # https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_hide_header
        fastcgi_hide_header X-Powered-By;
    }
}

After adding regex expressions for around 10 IP addresses… I gave up. I’m really not sure how, but originally I only got the error for the host ip (when setting the server as admin), then for similar looking ips(when opening a document from here on), then for probably cloudflare ips(but not my cloudflare ips), then finally the local ip that my docker clients are connected to and then just random seeming extra ips… Therefore I can only guess that the approach with --o:net.post_allow.host[x]=z\.z\.z\.z is either flawed or just incorrect.

(this is copied from stackoverflow, for context: I looked at this and figured that using net.post_allow.host[x] would be the correct approach.

I do not use docker so I am not sure if there are any additional settings necessary there, but with the follow nginx locatons reverse proxying works in my setup:

  # static files
  location ^~ /browser {
    proxy_pass http://10.0.0.3;
    proxy_set_header Host $http_host;
  }

  # WOPI discovery URL
  location ^~ /hosting/discovery {
    proxy_pass http://10.0.0.3;
    proxy_set_header Host $http_host;
  }

  # main websocket
  location ~ ^/cool/(.*)/ws$ {
    proxy_pass http://10.0.0.3;
    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 ~ ^/cool {
    proxy_pass http://10.0.0.3;
    proxy_set_header Host $http_host;
  }

  # Admin Console websocket
  location ^~ /cool/adminws {
    proxy_pass http://10.0.0.3;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $http_host;
    proxy_read_timeout 36000s;
  }

  #capabilities check
  location ^~ /hosting/capabilities {
    proxy_pass http://10.0.0.3;
    proxy_set_header Host $http_host;
  }

I hope this helps

2 Likes

Thank you very much for the reply, I’ll try the config you have suggested and see how it goes.
It may take a few days until I can give you feedback however.