For anyone dealing with this same issue, I was able to fix it. This setup still needs some refinement, but as it stands, everything appears to be working as expected. I’m not 100% sure the Coturn configuration is right. I did it with TLS and TCP only. I started a brand new setup on a different network using docker for everything except the apache reverse proxy running on the host. I ran into the same problems. The two sticking points here ended up being some combination of adding static host entries in the containers and running the whole setup in docker-compose. Even with the host entries and using the same docker container options, it still would not work when I had Collabora running with “docker run” and everything else running with docker-compose. Possibly some Docker inter-network issue that would not have applied to my original setup where the only Docker container was Collabora and everything else was on the host.
This is on an Ubuntu Server 18.04 virtual machine running on VMware ESXi. Docker was installed from the official packages, NOT from Ubuntu’s snap. The host is running the Apache proxy and certbot. Everything else is in Docker.
A few other notes about this setup. Certbot put Let’s Encrypt certs in my virtual hosts. I originally set up certbot before adding virtual hosts for Collabora, and so when I added it and reconfigured certbot, it added a subject alternate name for my Collabora domain. They both use the same cert. I also set up a read-only volume so the Coturn container can use the host certbot’s certificate for TLS. I have Nextcloud and MySQL both storing data in a folder on the host since I’m not quite comfortable with the idea of vital data being in a Docker container at this point. And finally, to make sure Coturn gets updated certificates, as a quick and dirty and very unprofessional fix, I set a cron job on the host to restart the Coturn container every Sunday at 4am.
My setup shows no warnings under Settings > Administration > Overview and scores an A rating on https://scan.nextcloud.com/ and A+ on https://www.ssllabs.com/ssltest/.
Here are my config files (with sensitive data replaced of course). This is my working docker-compose:
version: '3.7'
networks:
nextcloud:
services:
mariadb:
image: mariadb
container_name: nextcloud-mariadb
restart: unless-stopped
volumes:
- /var/lib/nextcloud/mariadb:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=mysqlpassword
- MYSQL_PASSWORD=mysqlpassword
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
networks:
- nextcloud
redis:
image: redis
container_name: nextcloud-redis
networks:
- nextcloud
restart: unless-stopped
nextcloud:
# image: nextcloud
build: .
image: nextcloud:smbclient
container_name: nextcloud
networks:
- nextcloud
ports:
- 127.0.0.1:8080:80
volumes:
- /var/lib/nextcloud/html:/var/www/html
extra_hosts:
- "nxc.example.com:192.168.0.10"
- "nxc-office.example.com:192.168.0.10"
depends_on:
- mariadb
- redis
environment:
- NEXTCLOUD_TRUSTED_DOMAINS='nxc.example.com'
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=mysqlpassword
- MYSQL_HOST=nextcloud-mariadb
- REDIS_HOST=nextcloud-redis
restart: unless-stopped
coturn:
image: instrumentisto/coturn
container_name: nextcloud-coturn
restart: unless-stopped
ports:
- 3478:3478/tcp
networks:
- nextcloud
volumes:
- /etc/letsencrypt:/etc/letsencrypt:ro
command: ["-n","--log-file=stdout","--external-ip=12.34.56.78","--min-port=49160","--max-port=49200","--realm=nxc.example.com","--no-udp","--use-auth-secret","--static-auth-secret=coturnsecret","--cert=/etc/letsencrypt/live/nxc.example.com/fullchain.pem","--pkey=/etc/letsencrypt/live/nxc.example.com/privkey.pem"]
collabora:
image: collabora/code
container_name: nextcloud-collabora
restart: unless-stopped
networks:
- nextcloud
ports:
- 127.0.0.1:9980:9980
extra_hosts:
- "nxc.example.com:192.168.0.10"
- "nxc-office.example.com:192.168.0.10"
environment:
- 'domain=nxc\\.example\\.com'
- 'dictionaries=en'
cap_add:
- MKNOD
tty: true
The Dockerfile I used to build Nextcloud is to add SMB external storage support. I used the example found here: https://github.com/nextcloud/docker/tree/master/.examples
Here are my virtual hosts. I started them off with the SSL vhosts using the default snakeoil cert and key and let Certbot replace them.
<VirtualHost *:80>
ServerName nxc.example.com
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
RewriteEngine On
RewriteRule ^/\.well-known/carddav http://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
RewriteRule ^/\.well-known/caldav http://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
RewriteCond %{SERVER_NAME} =nxc.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:443>
ServerName nxc.example.com
SSLEngine On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
RewriteEngine On
RewriteRule ^/\.well-known/carddav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
RewriteRule ^/\.well-known/caldav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/nxc.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/nxc.example.com/privkey.pem
</VirtualHost>
<VirtualHost *:443>
ServerName nxc-office.example.com
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
SSLHonorCipherOrder on
AllowEncodedSlashes NoDecode
SSLProxyEngine On
SSLProxyVerify None
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
ProxyPreserveHost On
ProxyPass /loleaflet https://127.0.0.1:9980/loleaflet retry=0
ProxyPassReverse /loleaflet https://127.0.0.1:9980/loleaflet
ProxyPass /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0
ProxyPassReverse /hosting/discovery https://127.0.0.1:9980/hosting/discovery
ProxyPassMatch "/lool/(.*)/ws$" wss://127.0.0.1:9980/lool/$1/ws nocanon
ProxyPass /lool/adminws wss://127.0.0.1:9980/lool/adminws
ProxyPass /lool https://127.0.0.1:9980/lool
ProxyPassReverse /lool https://127.0.0.1:9980/lool
ProxyPass /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities retry=0
ProxyPassReverse /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities
SSLCertificateFile /etc/letsencrypt/live/nxc.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/nxc.example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
<VirtualHost *:80>
ServerName nxc-office.example.com
AllowEncodedSlashes NoDecode
SSLProxyEngine On
SSLProxyVerify None
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off
ProxyPreserveHost On
ProxyPass /loleaflet https://127.0.0.1:9980/loleaflet retry=0
ProxyPassReverse /loleaflet https://127.0.0.1:9980/loleaflet
ProxyPass /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0
ProxyPassReverse /hosting/discovery https://127.0.0.1:9980/hosting/discovery
ProxyPassMatch "/lool/(.*)/ws$" wss://127.0.0.1:9980/lool/$1/ws nocanon
ProxyPass /lool/adminws wss://127.0.0.1:9980/lool/adminws
ProxyPass /lool https://127.0.0.1:9980/lool
ProxyPassReverse /lool https://127.0.0.1:9980/lool
ProxyPass /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities retry=0
ProxyPassReverse /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities
</VirtualHost>
And a list of Apache2 mods-enabled:
access_compat
alias
authn_core
authn_file
authz_core
authz_host
authz_user
auth_basic
autoindex
deflate
dir
env
filter
headers
mime
mpm_event
negotiation
proxy
proxy_http
proxy_wstunnel
reqtimeout
rewrite
setenvif
socache_shmcb
ssl
status
During the setup, I also had to set some extra variables in Nextcloud’s config due to being proxied. With it being in Docker, you do it like this:
docker exec -it -u www-data nextcloud php occ config:system:set trusted_proxies 1 --value='127.0.0.1'
docker exec -it -u www-data nextcloud php occ config:system:set overwritehost --value="nxc.example.com"
docker exec -it -u www-data nextcloud php occ config:system:set overwriteprotocol --value="https"
Hope all that helps someone.