Seafile + OnlyOffice + Docker (Готовый стек для self-hosted альтернативы Nextcloud)

Делюсь полностью рабочими конфигурационными файлами, которые я выстрадал и проверил в бою.
Это полноценная замена Nextcloud на базе Seafile — более лёгкая, быстрая и с отличной синхронизацией. В комплекте:

  • Seafile (Community Edition 13.0.18) — само хранилище, работает как часы.

  • OnlyOffice (8.1.0.1) — онлайн-редактор документов, таблиц и презентаций, идеально встраивается в Seafile.

  • SeaDoc — редактор документов (ещё одна фича Seafile).

  • Notification Server — для уведомлений и мониторинга (ping-эндпоинт).

Всё завернуто в Docker Compose, все версии образов зафиксированы (исключить внезапные обновы).
Настройки вынесены в единый .env — легко править под себя.

:rocket: Как использовать

  1. Подготовьте чистую VM (Debian 12) с достаточным дисковым пространством (минимум 20–30 ГБ, или столько, сколько вам нужно облачного пространства).

  2. Установите Docker и Docker Compose (если ещё не сделано).

  3. Создайте директорию ( /opt/seafile) и поместите в неё все файлы:

    • .env (переименуйте, подставьте свои данные)

    • seafile-server.yml

    • seadoc.yml

    • onlyoffice.yml

    • notification-server.yml

  4. Отредактируйте .env:

    • Замените your.domain.ru на ваш реальный домен (например, drive.example.com).

    • Сгенерируйте надёжные пароли для JWT_PRIVATE_KEY, SEAFILE_MYSQL_DB_PASSWORD, REDIS_PASSWORD, INIT_SEAFILE_MYSQL_ROOT_PASSWORD, ONLYOFFICE_JWT_SECRET.
      Можно использовать команду (в терминале):
      openssl rand -base64 32 | tr -dc 'a-zA-Z' | head -c 32; echo

    • Укажите ваш email и пароль администратора Seafile (INIT_SEAFILE_ADMIN_EMAIL, INIT_SEAFILE_ADMIN_PASSWORD).

    • Если у вас другой часовой пояс, измените TIME_ZONE.

  5. Запустите стек:

cd /opt/seafile
docker compose up -d
  1. Проверьте логи и доступность сервисов:
  • Seafile: http://ваш-ip:8080 (после настройки Traefik будет доступен по домену)

  • OnlyOffice: http://ваш-ip:6233/welcome/

  • Notification Server: http://ваш-ip:8083/ping (должен ответить {"ret":"pong"})

:globe_with_meridians: Доступ из интернета (опционально)

Я использую Traefik как внешний прокси с автоматическими SSL-сертификатами.
Вы можете адаптировать конфигурацию под свой прокси (nginx, Caddy и т.д.).
Для Traefik пример конфига:

http:
  routers:
    seafile-main:
      rule: "Host(`seafile.example.com`) && !PathPrefix(`/notification`)"
      entryPoints: ["websecure"]
      tls:
        certResolver: letsencrypt
        options: modern@file
      middlewares:
        - chain-public@file
        - seafile-headers@file
      service: seafile-main

    seafile-notification:
      rule: "Host(`seafile.example.com`) && PathPrefix(`/notification`)"
      entryPoints: ["websecure"]
      tls:
        certResolver: letsencrypt
        options: modern@file
      middlewares:
        - chain-public@file
        - notification-headers@file
      service: seafile-notification

    onlyoffice:
      rule: "Host(`office.example.com`)"
      entryPoints: ["websecure"]
      tls:
        certResolver: letsencrypt
        options: modern@file
      middlewares:
        - chain-public@file
        - onlyoffice-headers@file
      service: onlyoffice

  services:
    seafile-main:
      loadBalancer:
        servers:
          - url: "http://<IP_вашего_сервера_Seafile>:8080"

    seafile-notification:
      loadBalancer:
        servers:
          - url: "http://<IP_вашего_сервера_Seafile>:8083"
        healthCheck:
          path: /ping
          interval: 10s
          timeout: 3s

    onlyoffice:
      loadBalancer:
        passHostHeader: true
        servers:
          - url: "http://<IP_вашего_сервера_Seafile>:6233"

  middlewares:
    seafile-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"
          X-Forwarded-Host: "seafile.example.com"
        customResponseHeaders:
          X-Frame-Options: "SAMEORIGIN"
          Content-Security-Policy: "frame-ancestors 'self' https://seafile.example.com"

    notification-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"
          X-Forwarded-Host: "seafile.example.com"

    onlyoffice-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"
          X-Forwarded-Host: "office.example.com"
        customResponseHeaders:
          X-Frame-Options: ""
          Content-Security-Policy: "frame-ancestors 'self' https://seafile.example.com"
        stsSeconds: 31536000
        stsIncludeSubdomains: true
        stsPreload: true
        forceSTSHeader: true
        browserXssFilter: true
        contentTypeNosniff: true
        referrerPolicy: "strict-origin-when-cross-origin"
        permissionsPolicy: "geolocation=(self), camera=(self), microphone=(self)"

:pushpin: Пояснения для сообщества

  • Замените seafile.example.com и office.example.com на ваши реальные домены.

  • Вместо <IP_вашего_сервера_Seafile> укажите локальный IP машины, на которой запущен Seafile (например, 192.168.1.100).

  • chain-public@file – это ссылка на цепочку middleware, которая обычно включает CrowdSec, rate limit и базовые заголовки безопасности. Вы можете определить её в отдельном файле или заменить на свои middleware.

  • modern@file – TLS-опции, например:

tls:
  options:
    modern:
      minVersion: VersionTLS12
  • Middleware seafile-headers, notification-headers и onlyoffice-headers уже описаны здесь же – они добавляют необходимые заголовки для корректной работы Seafile и OnlyOffice (в частности, для работы OnlyOffice в iframe).

:file_folder: Состав файлов

Файл Назначение
.env Все настройки (пароли, пути, домены)
seafile-server.yml Основной стек: MariaDB, Redis, Seafile
seadoc.yml Сервис SeaDoc
onlyoffice.yml OnlyOffice Document Server
notification-server.yml Сервер уведомлений (нужен для мониторинга)

:warning: Важно

  • В файлах нет чувствительных данных — только шаблоны. Все секреты вы задаёте сами в .env.

  • Версии образов жёстко зафиксированы (никаких latest), чтобы ничего не сломалось при обновлениях.

  • Если вам нужен антивирус (ClamAV) — официальная интеграция в Docker-версии Seafile не работает (отсутствует clamdscan в контейнере). Я отказался от неё, но вы можете попробовать самостоятельно.

:backhand_index_pointing_right: Версия от 28.02.2026, проверено в работе.

notification-server.yml

services:
  notification-server:
    image: ${NOTIFICATION_SERVER_IMAGE}
    container_name: notification-server
    restart: unless-stopped
    volumes:
      - ${SEAFILE_VOLUME}/seafile/logs:/shared/seafile/logs
    ports:
      - "8083:8083"
    environment:
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER}
      - 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}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT}
      - NOTIFICATION_SERVER_LOG_LEVEL=${NOTIFICATION_SERVER_LOG_LEVEL}
      - NOTIFICATION_SERVER_URL=${NOTIFICATION_SERVER_URL}
      - INNER_NOTIFICATION_SERVER_URL=${INNER_NOTIFICATION_SERVER_URL}
    depends_on:
      db:
        condition: service_healthy
      seafile:
        condition: service_healthy
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net
artidev@debian-external:/opt/seafile$ cat onlyoffice.yml
services:
  onlyoffice:
    image: ${ONLYOFFICE_IMAGE}
    restart: unless-stopped
    container_name: seafile-onlyoffice
    ports:
      - "${ONLYOFFICE_PORT}:80"
    environment:
      - JWT_ENABLED=true
      - JWT_SECRET=${ONLYOFFICE_JWT_SECRET:?Variable is not set or empty}
      - PROXY_TRUSTED=true
      - PROXY_PROTOCOL=https
      - PROXY_HOST=office.yourdomain.ru # заменить на свой реальный
      - PROXY_PORT=443
    volumes:
      - ${ONLYOFFICE_VOLUME}/logs:/var/log/onlyoffice
      - ${ONLYOFFICE_VOLUME}/data:/var/www/onlyoffice/Data
      - ${ONLYOFFICE_VOLUME}/lib:/var/lib/onlyoffice
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

seadoc.yml

services:
  seadoc:
    image: ${SEADOC_IMAGE}
    container_name: seadoc
    restart: unless-stopped
    volumes:
      - ${SEADOC_VOLUME}:/shared
    # ports:
    #   - "80:80"
    environment:
      - DB_HOST=${SEAFILE_MYSQL_DB_HOST}
      - DB_PORT=${SEAFILE_MYSQL_DB_PORT}
      - DB_USER=${SEAFILE_MYSQL_DB_USER}
      - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - DB_NAME=${SEADOC_MYSQL_DB_NAME}
      - TIME_ZONE=${TIME_ZONE}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - NON_ROOT=${NON_ROOT}
      - SEAHUB_SERVICE_URL=${SEAFILE_SERVICE_URL}
    depends_on:
      db:
        condition: service_healthy
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

seafile-server.yml

services:
  db:
    image: ${SEAFILE_DB_IMAGE}
    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}:/var/lib/mysql"
    networks:
      - seafile-net
    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}
    container_name: seafile-redis
    restart: unless-stopped
    command:
      - /bin/sh
      - -c
      - redis-server --requirepass "$$REDIS_PASSWORD"
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD}
    networks:
      - seafile-net

  seafile:
    image: ${SEAFILE_IMAGE}
    container_name: seafile
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - ${SEAFILE_VOLUME}:/shared
    environment:
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME}
      - SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME}
      - TIME_ZONE=${TIME_ZONE}
      - INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL}
      - INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL}
      - SITE_ROOT=${SITE_ROOT}
      - NON_ROOT=${NON_ROOT}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT}
      - ENABLE_GO_FILESERVER=${ENABLE_GO_FILESERVER}
      - ENABLE_SEADOC=${ENABLE_SEADOC}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL}://${SEAFILE_SERVER_HOSTNAME}/sdoc-server
      - CACHE_PROVIDER=${CACHE_PROVIDER}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_PORT=${REDIS_PORT}
      - REDIS_PASSWORD=${REDIS_PASSWORD}
      - MEMCACHED_HOST=${MEMCACHED_HOST}
      - MEMCACHED_PORT=${MEMCACHED_PORT}
      - ENABLE_NOTIFICATION_SERVER=${ENABLE_NOTIFICATION_SERVER}
      - INNER_NOTIFICATION_SERVER_URL=${INNER_NOTIFICATION_SERVER_URL}
      - NOTIFICATION_SERVER_URL=${NOTIFICATION_SERVER_URL}
      - ENABLE_SEAFILE_AI=${ENABLE_SEAFILE_AI}
      - SEAFILE_AI_SERVER_URL=${SEAFILE_AI_SERVER_URL}
      - SEAFILE_AI_SECRET_KEY=${JWT_PRIVATE_KEY}
      - MD_FILE_COUNT_LIMIT=${MD_FILE_COUNT_LIMIT}
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

.env

COMPOSE_PATH_SEPARATOR=,
COMPOSE_FILE=seafile-server.yml,seadoc.yml,onlyoffice.yml,notification-server.yml
SEAFILE_IMAGE=seafileltd/seafile-mc:13.0.18
SEAFILE_DB_IMAGE=mariadb:10.11.16
SEAFILE_REDIS_IMAGE=redis:8.6.1
SEADOC_IMAGE=seafileltd/sdoc-server:2.0.9
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:13.0.10
ONLYOFFICE_IMAGE=onlyoffice/documentserver:8.1.0.1

BASIC_STORAGE_PATH=/opt
SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-data
SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db
SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data
ONLYOFFICE_VOLUME=$BASIC_STORAGE_PATH/onlyoffice

SEAFILE_SERVER_HOSTNAME=your.domain.ru
SEAFILE_SERVER_PROTOCOL=https
TIME_ZONE=Europe/Moscow
JWT_PRIVATE_KEY=password must be at least 32 characters long
SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_PORT=3306
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=password
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db
CACHE_PROVIDER=redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=password
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=password
INIT_SEAFILE_ADMIN_EMAIL=your e-mail
INIT_SEAFILE_ADMIN_PASSWORD=e-mail application password
ENABLE_SEADOC=true
ENABLE_NOTIFICATION_SERVER=true
NOTIFICATION_SERVER_LOG_LEVEL=info
NOTIFICATION_SERVER_URL=https://your.domain.ru/notification
INNER_NOTIFICATION_SERVER_URL=https://notification-server:8083
ENABLE_SEAFILE_AI=false
MD_FILE_COUNT_LIMIT=100000
ONLYOFFICE_PORT=6233
ONLYOFFICE_JWT_SECRET=password must be at least 32 characters long

SEADOC_MYSQL_DB_NAME=seahub_db
SEAFILE_SERVICE_URL=https://seafile
SEAFILE_LOG_TO_STDOUT=false
ENABLE_GO_FILESERVER=true
SITE_ROOT=/
NON_ROOT=false
SEAFILE_AI_SERVER_URL=https://seafile-ai:8888
MEMCACHED_HOST=
MEMCACHED_PORT=

Команды для генерации случайного набора символов:

openssl rand -base64 32 | tr -dc 'a-zA-Z' | head -c 32; echo

Если нужно больше/меньше символов:
Для 16 букв:
openssl rand -base64 16 | tr -dc 'a-zA-Z' | head -c 16; echo

Для 24 букв:
openssl rand -base64 18 | tr -dc 'a-zA-Z' | head -c 24; echo

Для 64 букв:
openssl rand -base64 48 | tr -dc 'a-zA-Z' | head -c 64; echo

После развертывания стека, нужно отредактировать системный файл конфигурации: seahub_settings.py

Пример моего рабочего seahub_settings.py имеет следующий вид.

# -*- coding: utf-8 -*-
SECRET_KEY = будет сгененрирован в процессе установки
TIME_ZONE = 'Europe/Moscow'

EMAIL_USE_SSL = True
EMAIL_HOST = ''        # smpt server
EMAIL_HOST_USER = ''    # username and domain
EMAIL_HOST_PASSWORD = ''    # password
EMAIL_PORT = 
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER

ENABLE_ONLYOFFICE = True
ONLYOFFICE_APIJS_URL = 'https://office.yourdomain.ru/web-apps/apps/api/documents/api.js'
ONLYOFFICE_JWT_SECRET = '' # должен совпадать с .env
ONLYOFFICE_FILE_EXTENSION = ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'odt', 'fodt', 'odp', 'fodp', 'ods', 'fods', 'ppsx', 'pps', 'csv')
ONLYOFFICE_EDIT_FILE_EXTENSION = ('docx', 'pptx', 'xls', 'csv')
OFFICE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024
ONLYOFFICE_FORCE_SAVE = True

SERVICE_URL = 'https://drive.yourdomain.ru'
FILE_SERVER_ROOT = 'https://drive.yourdomain.ru/seafhttp'

:pushpin: Как использовать

  • Отредактируйте содержимое файла, который находится в папке conf вашего Seafile (обычно /opt/seafile-data/seafile/conf/) с помощью команды:
sudo /opt/seafile-data/seafile/conf/seahub_settings.py
  • Замените все yourdomain.ru на свой реальный домен.

  • Перезапустите контейнер Seafile, чтобы изменения вступили в силу:

docker restart seafile

Источник: Setup community edition - Seafile Admin Manual

5 лайков

Не в первый раз сталкиваюсь с тем, что в compose файлах фиксируются версии образов.

У меня это работает так - версия указана latest, деплою сервис, настраиваю проверяю, гоняю в тестовой среде, потом делаю бэкап и переношу в продуктив.

Далее этот сервис живёт месяцами-годами без изменения ровно до того момента, пока я сам не решу передеплоить docker-compose, а если что-то сломается, то из бэкапа откачусь обратно.

Поделись опытом, какой у тебя подход к обновлению. Вот задумался, может я что-то упускаю и мой вариант не самый оптимальный.

За статью спасибо, ещё не добрался до своего облака, буду иметь ввиду на будущее.

P.s. с дебютом :saluting_face::partying_face:

У меня в PVE настроено ежедневное бекапирование всех LXC и VM, храню X дней.

Если есть обновление просто меняю версию, разворачиваю, проверяю решаю проблему при необходимости, если не вышло - в топку на какое-то время. Откатываю бекап.

Я не особо продвинутый user в самохостинге, Linux. Поэтому все приходит с течением времени и я не претендую на истину в последней инстанции.

P.S. Спасибо!

1 лайк

Многие приложения используют фикс по версиям. Тот же Authentik. Это нормальный поход, если не лень отслеживать изменения и баги. К слову, мне лень. Ставлю latest и делаю бекап VM раз в день

Мне нравится подход с закреплением мажорной версии или минорной
Например, указываем 2.5 вместо 2.5.1

1 лайк

на что бэкапы делаете и сколько это место занимает. например если нет pbs можно ли сделать бекапы на нас?

Можно, но возникают вопросы с дедубликацицией, по сути, каждый бэкап занимает столько места, сколько показывает сам PVE размер диска, поэтому учитывайте этот факт.

PBS я пока не разобрался, но такое ощущение, что бэкап весит в 2 раза больше места, чем сам исходник, с дедубликацией во первых бэкапирование быстрее происходит за счет снижения пересылок (по сути, создаются инкрементаьные бэкапы), а во вторых, значительно сокращается занимаемое место
У меня сейчас так

Количество резервных копий на сейчас 957 (но я добавил пропущенные хосты и через пару недель должно перевалить за 1000)
Фактор дедупикации почти 18, т.е. виртуально резервные копии занимают 4 817 ГБ, а по факту 268 ГБ
Поскольку, дедупликация не на уровне бэкапа, а по всему хранилищу, то после унификации инструментов и операционок (у меня alipine в основном), то LXC контейнер сразу же после подготовки к работе практически не занимает место в бэкапе.

87 групп, это отдельные виртуалки и сервисы, на 957 снимков это значит, что в среднем у меня хранится по 11 резервных копий одного сервиса и все равно это меньше 18 (т.е. дедубликация еще выше за счет использованя одного блока несколькими независимыми сервисами)

Но надо учесть, что создание снимка контейнера или виртуалки не очень надежное т.к. могут потеряться данные которые находятся в оперативке, поэтому, там, где это возможно, у меня создаются резервные копии средствами самого сервиса и выгрузка из в PBS

1 лайк

Лично у меня подключен третий HDD 2.5 диск объемом 500Гб, на который по расписанию делаются бекапы средствами PVE.

1 лайк

Что-то не получается у меня… Подозреваю что дело в nginx (как обратный прокси). Сделал 2 урла для seafile и onlyoffice. По ним идет все открывает по папкам ходишь, файлы создаёшь, но когда пытаешься открыть файл для редактирования в onlyoffice не запускается совсем onlyoffice. Пишет что “Онлайн-просмотр не применим к этому формату файла”. В seahub_settings.py все прописал.
И seadoc тоже не работает “Ошибка загрузки содержимого документа”
Может у кого-то был опыт с nginx поделитесь настройками.

Подозреваю что проблема с заголовками:

customRequestHeaders:
X-Forwarded-Proto: “https”
X-Forwarded-Host: “seafile.example.com

У меня по началу было, что я не мог ничего сохранить, хотя все открывалось.

Так же проверьте JWT_PRIVATE_KEY и ONLYOFFICE_JWT_SECRET их 2 и они разные.

Сами страницы я так понимаю открываются: seafile.example.com и onlyoffice.example.com ?

спасибо за быстрый ответ!
но что-то я вообще не вижу такого:
customRequestHeaders:
X-Forwarded-Proto: “https”
X-Forwarded-Host: “seafile.example.com

это в настройки вэб сервера надо прописывать?

JWT проверил.

на seafile открывается сам seafile, на onlyoffice там заглушка открывается

Эти параметры нужно задать в Nginx, попробуйте у Ai спросить описав свою проблему, показав ей все файлы.

Например. Развернул стек seafile + onlyoffice но “описание проблемы“ подозреваю что проблема в передаче заголовков, в качестве реверспрокси использую ПО nginx версии.

Мои файлы: можете показать все из статьи. Не ведитесь на: вот тут можно улучшить или еще лучше сделать. Это будет бесконечно. Можно ссылки кидать на HTTPS with Nginx - Seafile Admin Manual Using ONLYOFFICE Docs behind the proxy Onlyoffice Server behind a nginx proxy - Docs - ONLYOFFICE Community

это я уже делал))) только потом сюда написал. спасибо за подсказку) попробую через traefik c вашим конфигом

Мне ответила так:

Судя по описанию, проблема классическая: OnlyOffice и SeaDoc не могут связаться с Seafile из-за неправильных заголовков или JWT. Давайте разбираться по шагам.

:detective::male_sign: Первичная диагностика

  1. Проверка логов Seafile:

    bash

    docker logs seafile --tail 50 | grep -i error
    

    Особенно ищите ошибки, связанные с onlyoffice, seadoc, jwt или callback.

  2. Проверка логов OnlyOffice:

    bash

    docker logs seafile-onlyoffice --tail 50 | grep -i error
    

    Ошибки вида JWT verification failed или connection refused будут очень полезны.

  3. Проверка внутренней связности:
    Из контейнера Seafile должен быть доступен OnlyOffice по имени:

    bash

    docker exec seafile ping -c 2 seafile-onlyoffice
    docker exec seafile curl -I http://seafile-onlyoffice:80
    

    Аналогично для SeaDoc.

  4. Проверка конфигурации:
    Убедитесь, что в seahub_settings.py (лежит в /opt/seafile-data/seafile/conf/) прописаны правильные URL и JWT-секреты. Особенно важно:

    python

    ENABLE_ONLYOFFICE = True
    ONLYOFFICE_APIJS_URL = 'https://office.ваш-домен.ru/web-apps/apps/api/documents/api.js'
    ONLYOFFICE_JWT_SECRET = 'тот_же_что_в_файле_.env'
    ENABLE_SEADOC = True
    # Остальные настройки...
    

    После изменений не забыть перезапустить Seafile.

:wrench: Типичные проблемы с Nginx (или NPM)

Поскольку он использует Nginx Proxy Manager (NPM), нужно убедиться, что в настройках прокси передаются все необходимые заголовки. NPM по умолчанию добавляет базовые заголовки, но для OnlyOffice требуются специфичные.

Пример рабочей конфигурации для Nginx (можно адаптировать для NPM):

Для домена Seafile (например, cloud.example.com):

nginx

location / {
    proxy_pass http://<IP_сервера_Seafile>:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_redirect off;
}

Для домена OnlyOffice (например, office.example.com):

nginx

location / {
    proxy_pass http://<IP_сервера_Seafile>:6233;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Ssl on;
}

Эти заголовки сообщают OnlyOffice, что он работает за HTTPS-прокси, и позволяют корректно формировать ссылки для callback’ов.

Для SeaDoc (не требует отдельного домена, работает через Seafile).

:key: Ключевые моменты для OnlyOffice

В файле onlyoffice.yml (который лежит в /opt/seafile/) должны быть правильные значения переменных окружения:

yaml

environment:
  - JWT_ENABLED=true
  - JWT_SECRET=${ONLYOFFICE_JWT_SECRET}  # должен совпадать с .env и seahub_settings.py
  - PROXY_TRUSTED=true
  - PROXY_PROTOCOL=https
  - PROXY_HOST=office.ваш-домен.ru        # именно тот домен, который в браузере
  - PROXY_PORT=443

После изменения onlyoffice.yml необходимо перезапустить стек:

bash

cd /opt/seafile
docker compose down
docker compose up -d

:pushpin: SeaDoc: особый случай

SeaDoc — это отдельный сервис, который должен быть доступен по URL https://cloud.ваш-домен.ru/sdoc-server/. В seafile-server.yml эта переменная формируется автоматически из SEAFILE_SERVER_PROTOCOL и SEAFILE_SERVER_HOSTNAME. Убедитесь, что в .env они указаны верно:

bash

SEAFILE_SERVER_HOSTNAME=cloud.ваш-домен.ru
SEAFILE_SERVER_PROTOCOL=https

Если SeaDoc не работает, скорее всего, проблема в том, что прокси не передаёт запросы на /sdoc-server/ внутрь. В конфигурации Nginx для Seafile это должно быть покрыто общим location /, так как SeaDoc работает через основной порт Seafile.

:white_check_mark: Если ничего не помогло

  1. Проверьте, не блокирует ли файервол внутренние порты (8080, 6233, 8083) на самой VM. Для теста можно временно отключить UFW: sudo ufw disable.

  2. Попробуйте временно обойти прокси, открыв порты напрямую (например, http://<IP>:8080 и http://<IP>:6233/welcome/). Если там всё работает, проблема точно в Nginx.

  3. Сверьтесь с логами Nginx на предмет ошибок проксирования.

Пользователь молодец, что обратился – давайте поможем ему разобраться. Если он предоставит выводы логов и свои конфиги (без паролей), можно будет дать более точные советы.

1 лайк

2 дня мучал! в итоге готово)

Поделитесь с остальными что было сделано, не все используют Traefik.

В чем был затык?

а зачем ставит SeaDoc, если настраиваете Onlyoffice?

Ну чтобы попробовать и он реально крут, но менее функционален, соответственно, можно использовать для документов с версионированием и коллаборацией, а onlyoffice для офисных документов, т.к. там хорошая поддержка документов из MS Office

Подскажи, а у вас Seadoc работает нормально, в Wiki страницы создаются и редактируются нормально? Я поднял сборку без seadoc, в качестве прокси nginx, работает нормально, сейчас пытаюсь добавить seadoc чтобы Wiki пощупать, и никак не удается.