Docker Compose for Nextcloud + Collabora + Traefik?

I have such setup running 1,5y and survived 2 major updates and hardware move without issues, the setup is stable. maybe this is the least problematic advanced feature of NC… (works much more stable than talk+coturn).

as I don’t use Collabora often first start takes multiple seconds but then it works good on old i3 desktop…

The only big problem I experienced was Collabora outage for multiple weeks caused by Collabora until I discovered the solution in Collabora forums (Collabora+SNI). The problem was identified much earlier but nobody made the link between Collabora and Nextcloud forums until I decided to dig into the issue… I described the problem here in detail.

see my config below, there is nothing special, maybe little hard to fit all the parts together… maybe the most important hint - as you can see from the examples all configurations use fqdn so each system: the client must reach both Nextcloud and Collabora by FQDN (with TLS) and both system must reach each other using fqdn as well. This is requirement is based on how WOPI works - once the user start editing a document, the originating system - here Nextcloud forwards the client to includes a frame from the WOPI system with an URL pointing back to itself like https://collabora.mydomain.tld/open_the_dcument_N0_32342_on_my_Nextcloud (not really) which makes Collabora to fire it’s engine and connect to the Nextcloud and access the document 32342 on the Nextcloud (and auto-magically gain access to it). This communication systems might be an issue in some situation e.g. Fritzbox blocks access to local systems using public URLs - see “DNS Rebind Protection”, IPv6 could become an issue as well as modern system tend to prefer it (and it doesn’t work well for dynamic DNS pointing to self-hosted system)… I’m using local PiHole running as Docker container to point public URLs to local IPs…

traefik

  traefik:
    image: traefik:v2.5
    container_name: traefik
    restart: unless-stopped
    command:
      - "--api=true"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      #- "--log.level=DEBUG"
      - "--log.filePath=/etc/traefik/traefik.log"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=traefik_proxy"
      - "--providers.file.filename=/etc/traefik/config/tls.yaml"
      - "--providers.file.watch=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web-secure.address=:443"
      # Let's Encrypt
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencryptresolver.acme.email=youremail@forle.tld"
      - "--certificatesresolvers.letsencryptresolver.acme.storage=/etc/traefik/acme.json"
      # Logging options, what to log
      - "--accesslog=true"
      - "--accesslog.format=json"
      - "--accessLog.filters.statusCodes=400-499"      
    volumes:
      - ./traefik:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
    - traefik_proxy

traefik dynamic config

tls.yaml is nothing special (some security related settings and headers):

tls:
  options:
    TLSv13:
      minVersion: VersionTLS13
      cipherSuites:
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true
        
    default:
      minVersion: VersionTLS12
      cipherSuites:
      - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
      - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
      - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
      - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true

http:
  middlewares:
    secHeaders:
      headers:
        browserXssFilter: true
        contentTypeNosniff: true
        frameDeny: true
        sslRedirect: true
        #HSTS Configuration
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 15768000
    secHeaders2:
      headers:
        browserXssFilter: true
        contentTypeNosniff: true
        frameDeny: true
        customFrameOptionsValue: SAMEORIGIN
        referrerPolicy: same-origin
        sslRedirect: true
        #HSTS Configuration
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 15768000
        forceSTSHeader: true
        sslForceHost: true
        browserXssFilter: true
        customResponseHeaders:
          server: "" # removes "Server" header
          X-Powered-By: "" # Removes X-Powered-By
          X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex"
          #https://securityheaders.com/ is camera+mic enough?
          Permissions-Policy:	camera=('self'), microphone=('self'), autoplay=('self'), payment=(), screen-wake-lock=('self'), geolocation=()
          Feature-Policy:	"camera 'self'; microphone 'self'; payment 'none'; screen-wake-lock 'self'; geolocation 'none'; usb 'none'; vr 'none';"

collabora

  nextcloud-collabora:
    image: collabora/code
    container_name: collabora
    restart: unless-stopped
    networks:
      - traefik_proxy
    ports:
      - 9980:9980
    expose:
      - "9980"      
    environment:
      #should work as "domain=cloud1\.nextcloud\.com|cloud2\.nextcloud\.com"
      - domain=${COLLABORA_DOMAINS}
      - 'dictionaries=en_US,de_DE'
      - VIRTUAL_PROTO=http
      - VIRTUAL_PORT=9980
      - VIRTUAL_HOST=${COLLABORA_FQDN}
      - "extra_params=--o:ssl.enable=false  --o:ssl.termination=true"
    cap_add:
      - MKNOD
    tty: true
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik_proxy"
      - "traefik.http.routers.collabora.rule=Host(`${COLLABORA_FQDN}`)"
      - "traefik.http.routers.collabora.entrypoints=web"
      - "traefik.http.middlewares.collabora-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.collabora.middlewares=collabora-https-redirect"
      - "traefik.http.routers.collabora-secure.entrypoints=web-secure"
      - "traefik.http.routers.collabora-secure.rule=Host(`${COLLABORA_FQDN}`)"
      - "traefik.http.routers.collabora-secure.tls=true"
      - "traefik.http.routers.collabora-secure.tls.certresolver=letsencryptresolver"

I fill variable with .env file:

# fqdn of Collaboa conatainer
COLLABORA_FQDN=collabora.mydomain.tld
COLLABORA_DOMAINS=nc1.mydomain.tld|nc2.mydomain.tld # share one Collabora installation with two NC instances

you can check your Collabora instance itself works fine by visiting https://${COLLABORA_FQDN}/hosting/discovery in your browser/curl/whatever - XML describing service capabilities should appear…

nextcloud

I don’t remember something special - use working traefik example - I’m too lazy to pull out my personal data from my config :wink: just choose the right option and enter the host in Settings > Admin > Collabora Online… (https://nc2.mydomain.tld/settings/admin/richdocuments) :

image

1 Like