Onlyoffice not working behind caddy

Hello,

I’ve moved from bare metal nginx to dockerized caddy, and managed to redirect seafile correctly with caddy.
However, the onlyoffice Integration is somehow broken, clicking on an office file results in a blank tab.
Has anyone managed to setup seafile with onlyoffice behind caddy?
And would be willing to share his Caddyfile (without domain names)?
Thanks a lot,
Ruediger

I’ve given up on caddy, I was unable to get onlyoffice working in seafile with caddy.
So I moved back to nginx, but with nginx running in Docker using this image here:
https://hub.docker.com/r/jonasal/nginx-certbot

This will take care of automatic certbot updates, you only need to provide the conf files for nginx. Quite nice!

Hi. Here is my full setup for seafile on single node. I found onlyoffice docs for setting up behind nginx reverse proxy and partially rewrote it for caddy-docker-proxy.
This setup is behind nginx proxy manager, which is responsible for https.
Hope it helps.

docker-compose.yml
services:
  caddy:
    image: ${SEAFILE_CADDY_IMAGE:-lucaslorentz/caddy-docker-proxy:2.9-alpine}
    container_name: seafile-caddy
    restart: unless-stopped
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy
    healthcheck:
      test: ["CMD-SHELL", "curl --fail http://localhost:2019/metrics || exit 1"]
      start_period: 20s
      interval: 20s
      timeout: 5s
      retries: 3
    labels:
      caddy: ":80"
      caddy.0_map: "{header.x-forwarded-proto} {proto_override}"
      caddy.0_map.~^$: "{scheme}"
      caddy.0_map.default: "{header.x-forwarded-proto}"
      caddy.1_map: "{host} {this_host}"
      caddy.1_map.~^$: "${SEAFILE_SERVER_HOSTNAME}"
      caddy.1_map.default: "{host}"
      caddy.2_map: "{header.x-forwarded-host} {host_override}"
      caddy.2_map.~^$: "{this_host}"
      caddy.2_map.default: "{header.x-forwarded-host}"

  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-pro-mc:13.0-latest}
    container_name: seafile
    restart: unless-stopped
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    environment:
      - INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
      - SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
      - INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
      - SITE_ROOT=${SITE_ROOT:-/}
      - NON_ROOT=${NON_ROOT:-false}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
      - ENABLE_SEADOC=${ENABLE_SEADOC:-true}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
      - CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
      - MEMCACHED_HOST=${MEMCACHED_HOST:-memcached}
      - MEMCACHED_PORT=${MEMCACHED_PORT:-11211}
      - SEAF_SERVER_STORAGE_TYPE=${SEAF_SERVER_STORAGE_TYPE:-}
      - S3_COMMIT_BUCKET=${S3_COMMIT_BUCKET:-}
      - S3_FS_BUCKET=${S3_FS_BUCKET:-}
      - S3_BLOCK_BUCKET=${S3_BLOCK_BUCKET:-}
      - S3_KEY_ID=${S3_KEY_ID:-}
      - S3_SECRET_KEY=${S3_SECRET_KEY:-}
      - S3_USE_V4_SIGNATURE=${S3_USE_V4_SIGNATURE:-true}
      - S3_AWS_REGION=${S3_AWS_REGION:-us-east-1}
      - S3_HOST=${S3_HOST:-}
      - S3_USE_HTTPS=${S3_USE_HTTPS:-true}
      - S3_PATH_STYLE_REQUEST=${S3_PATH_STYLE_REQUEST:-false}
      - S3_SSE_C_KEY=${S3_SSE_C_KEY:-}
      - ENABLE_NOTIFICATION_SERVER=${ENABLE_NOTIFICATION_SERVER:-false}
      - INNER_NOTIFICATION_SERVER_URL=${INNER_NOTIFICATION_SERVER_URL:-http://notification-server:8083}
      - NOTIFICATION_SERVER_URL=${NOTIFICATION_SERVER_URL:-${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/notification}
      - ENABLE_SEAFILE_AI=${ENABLE_SEAFILE_AI:-false}
      - SEAFILE_AI_SERVER_URL=${SEAFILE_AI_SERVER_URL:-http://seafile-ai:8888}
      - SEAFILE_AI_SECRET_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - MD_FILE_COUNT_LIMIT=${MD_FILE_COUNT_LIMIT:-100000}
    labels:
      # caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy: ":80"
      caddy.reverse_proxy: "{{upstreams 80}}"
      caddy.reverse_proxy.0_header_up: X-Forwarded-Host {host_override}
      caddy.reverse_proxy.1_header_up: X-Forwarded-Proto {proto_override}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
  
  seadoc:
    image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:2.0-latest}
    container_name: seadoc
    restart: unless-stopped
    volumes:
      - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared
    environment:
      - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - DB_NAME=${SEADOC_MYSQL_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - NON_ROOT=${NON_ROOT:-false}
      - SEAHUB_SERVICE_URL=${SEAFILE_SERVICE_URL:-http://seafile}
    labels:
      # caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy: ":80"
      caddy.@ws.0_header: "Connection *Upgrade*"
      caddy.@ws.1_header: "Upgrade websocket"
      caddy.0_reverse_proxy: "@ws {{upstreams 80}}"
      caddy.1_handle_path: "/socket.io/*"
      caddy.1_handle_path.0_rewrite: "* /socket.io{uri}"
      caddy.1_handle_path.1_reverse_proxy: "{{upstreams 80}}"
      caddy.2_handle_path: "/sdoc-server/*"
      caddy.2_handle_path.0_rewrite: "* {uri}"
      caddy.2_handle_path.1_reverse_proxy: "{{upstreams 80}}"
    depends_on:
      db:
        condition: service_healthy
        
  db:
    image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
    container_name: seafile-mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--connect",
          "--mariadbupgrade",
          "--innodb_initialized",
        ]
      interval: 20s
      start_period: 30s
      timeout: 5s
      retries: 10

  redis:
    image: ${SEAFILE_REDIS_IMAGE:-redis}
    container_name: seafile-redis
    restart: unless-stopped
    command:
      - /bin/sh
      - -c
      - redis-server --requirepass "$$REDIS_PASSWORD"
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}

  elasticsearch:
    image: ${SEAFILE_ELASTICSEARCH_IMAGE:-elasticsearch:8.15.0}
    container_name: seafile-elasticsearch
    restart: unless-stopped
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms2g -Xmx2g"
      - "xpack.security.enabled=false"
    ulimits:
      memlock:
       soft: -1
       hard: -1
    mem_limit: 4g
    volumes:
      - "${SEAFILE_ELASTICSEARCH_VOLUME:-/opt/seafile-elasticsearch/data}:/usr/share/elasticsearch/data"

  onlyoffice:
    image: ${ONLYOFFICE_IMAGE:-onlyoffice/documentserver:8.1.0.1}
    restart: unless-stopped
    container_name: seafile-onlyoffice
    environment:
      #- DB_TYPE=${DB_TYPE:-mariadb}
      #- DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      #- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      #- DB_PWD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - JWT_ENABLED=true
      - JWT_SECRET=${ONLYOFFICE_JWT_SECRET:?Variable is not set or empty}
    volumes:
      - ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/logs:/var/log/onlyoffice
      - ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/data:/var/www/onlyoffice/Data
      - ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/lib:/var/lib/onlyoffice
    labels:
      caddy: ":80"
      caddy.handle_path: "/documentserver/*"
      caddy.handle_path.reverse_proxy: "{{upstreams 80}}"
      caddy.handle_path.reverse_proxy.0_header_up: X-Forwarded-Host {host}/documentserver
      caddy.handle_path.reverse_proxy.1_header_up: X-Forwarded-Proto {proto_override}