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.
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
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"
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.
# 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;
}
}
# 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;
}
}
Note: I already asked this question on the Collabora Online Forum , but I don't know if it's actually active enough or will help me in any reasonable time.
I looked at following articles:
and some more, but I'd assume that they are outdated/don't apply to my setup because nothing I've tried worked!
So I kind of found the issue and multiple fixes to it.
The problem is that the Collabora and Nextcloud-Servers are being proxied by Cloudflare. Specifying the Nextcloud-Server in aliasgroup1
therefore doesn't allow the actual requesting IP.
a1.a2.a3.a4
maps to example.com, which is listed in aliasgroup1
.
The outgoing requests from that server are coming from b1.b2.b3.b4
, which is not mapped to example.com, and is also not allowed to make WOPI requests, just like any Cloudflare IPs aren't allowed, except the one that maps to example.com.
This, especially configuring the Allow list for WOPI requests
, did solve my problem.
Just adding all Cloudflare IP-Ranges to Allow list for WOPI requests
in the Nextcloud-Web-UI fixed the problem for me. I am not sure if this is secure (at all).
@Red's answer (stackoverflow.com) is still kind of correct and would work for static IPs. And I would consider it (more) secure depending on the resulting Allow list for WOPI requests
in the Nextcloud-Web-UI.
Allow list for WOPI requests
, which can be found in the Nextcloud-Web-UI:<Docker-hostname-that-both-Nextcloud-and-Collabora-share-as-IPv4,Docker-hostname-that-both-Nextcloud-and-Collabora-share-as-IPv6>
10.1.0.1/16,fe80::.../64
You will also have to select Disable certificate verification (insecure)
. Since requests will be made locally, this shouldn't be a problem.
server {
...
ssl_stapling on;
ssl_stapling_verify on;
ssl_verify_client on;
ssl_client_certificate [...];
ssl_trusted_certificate [...];
...
}
Your Cloudflare configuration can stay the same, since requests from Nextcloud to Collabora and vice versa will be made locally
server {
listen 127.0.0.1:443 ssl;
listen [::1]:443 ssl;
listen <Docker-hostname-that-both-Nextcloud-and-Collabora-share>:443 ssl;
...
}
Other than that both the local and the public server blocks are exactly the same.
server {
listen 443 ssl;
listen [::]:443 ssl;
...
}
server {
...
listen <Docker-hostname-that-both-Nextcloud-and-Collabora-share>:443 ssl;
...
}
This also works if all the services concerned are in the same Podman pod, and you are using Podman, NOT Docker:
podman pod create
:--network-alias=collabora.example.com --network-alias=nextcloud.example.com
I also removed the extra Web-Server from my original configuration and just moved it to the reverse proxy for anyone trying to follow that.
NOTE: I did a lot of edits and hope that this is finally done and at least kind of well-structured. NOTE2: Read your edits before submitting :)