Добавить в корзинуПозвонить
Найти в Дзене

Домашнее облако: запускаем полнотекстовый поиск и онлайн-редактор документов

Чем
больше мы начинаем использовать свое собственное облако, тем больше
файлов туда загружаем. Из этого следует, что нам требуется быстрый поиск
по файлам и по возможности онлайн просмотр и редактирования файлов,
чтобы тратить минимум времени на операции поиска и
просмотра/редактирования документов. В этой статье постараемся настроить
полнотекстовый поиск (Elasticsearch) и on-line просмотр/редактирование файлов через Onlyoffice. # Создаем файлы
touch {docker-compose.yml,.env} Структура .env: ONLYOFFICE_SECRET=<your_secret> # Устанавливаем необходимые компоненты для onlyoffice
docker exec --user www-data nextcloud-app php occ app:install onlyoffice
# Установка онлайн-редактора
docker exec --user www-data nextcloud-app php occ app:install documentserver_community
# Отключаем, в случае наличия
docker exec --user www-data nextcloud-app php occ app:disable fulltextsearch_sql
# Устанавливаем необходимые компоненты для elasticsearch
docker exec --user www-data nextcloud-app php occ app
Оглавление

Потребность и актуальность

Чем
больше мы начинаем использовать свое собственное облако, тем больше
файлов туда загружаем. Из этого следует, что нам требуется быстрый поиск
по файлам и по возможности онлайн просмотр и редактирования файлов,
чтобы тратить минимум времени на операции поиска и
просмотра/редактирования документов. В этой статье постараемся настроить
полнотекстовый поиск (
Elasticsearch) и on-line просмотр/редактирование файлов через Onlyoffice.

docker-compose

  1. Создаем необходимые файлы:

# Создаем файлы
touch {docker-compose.yml,.env}

Структура .env:

ONLYOFFICE_SECRET=<your_secret>

  1. Перед запуском Docker устанавливаем в Nextcloud:

# Устанавливаем необходимые компоненты для onlyoffice
docker exec --user www-data nextcloud-app php occ app:install onlyoffice
# Установка онлайн-редактора
docker exec --user www-data nextcloud-app php occ app:install documentserver_community

# Отключаем, в случае наличия
docker exec --user www-data nextcloud-app php occ app:disable fulltextsearch_sql
# Устанавливаем необходимые компоненты для elasticsearch
docker exec --user www-data nextcloud-app php occ app:install fulltextsearch
docker exec --user www-data nextcloud-app php occ app:install files_fulltextsearch
docker exec --user www-data nextcloud-app php occ app:install fulltextsearch_elasticsearch

# Устанавливаем страницу поиска
docker exec --user www-data nextcloud-app php occ app:install thesearchpage

Устанавливаем ПО для OCR:

# Войти в контейнер как root
docker exec -it --user root nextcloud-app /bin/bash

# Обновить список пакетов и установить Tesseract с русским и английским языками
apt-get update
apt-get install -y tesseract-ocr tesseract-ocr-eng tesseract-ocr-rus ocrmypdf

# Проверить, что установка прошла успешно
tesseract --version

# Выйти из контейнера
exit

Активируем приложение для OCR:

docker exec --user www-data nextcloud-app php occ app:enable files_fulltextsearch_tesseract

  1. В docker-compose.yml запускаем только необходимые сервисы, структура docker-compose.yml:

services:
elasticsearch:
image: nextcloud/aio-fulltextsearch:latest
container_name: nextcloud-elasticsearch
stop_grace_period: 3m
hostname: elasticsearch
# depends_on:
# - db
# - app
environment:
- ES_JAVA_OPTS=-Xms4g -Xmx4g
- bootstrap.memory_lock=true
- cluster.name=nextcloud
- discovery.type=single-node
- logger.org.elasticsearch.discovery=WARN
- http.port=9200
- xpack.license.self_generated.type=basic
- xpack.security.enabled=false
- indices.query.bool.max_clause_count=8192
volumes:
- ./config_elasticsearch:/usr/share/elasticsearch/data:rw
ports:
- 9200:9200
- 9300:9300
dns:
- 9.9.9.9
restart: unless-stopped
ulimits:
memlock:
soft: -1
hard: -1
cap_add:
- IPC_LOCK
deploy:
resources:
limits:
cpus: '4'
memory: 8192m
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health?local=true"]
interval: 30s
timeout: 10s
retries: 5
start_period: 40s
networks:
- default

onlyoffice:
container_name: onlyoffice-documentserver
image: onlyoffice/documentserver:latest
# depends_on:
# - db
# - app
restart: always
volumes:
- ./config_onlyoffice:/var/www/onlyoffice/Data
environment:
- JWT_ENABLED=true
- JWT_SECRET=${ONLYOFFICE_SECRET}
ports:
- '8080:80'
env_file: ".env"
networks:
- default
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/welcome/"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s

networks:
default:
name: nextcloud-network
driver: bridge
attachable: true

Секцию depends_on в итоговом файле можно раскомментировать, так как мы ждем запуска базы данных и самого Nextcloud. Для elasticsearch секция dns
имеет важное значение, так как иначе Вы не сможете скачать образ из-за
«блокировок». Также важно, чтобы все контейнеры были в одной сети и за
это отвечает секция networks.

Проверка запуска:

  1. Onlyoffice: http://<your_ip>:8080/welcome/ - должны увидеть страницу приветствия Onlyoffice.
  2. Elasticsearch:

$ curl http://localhost:9200/
{
"name" : "elasticsearch",
"cluster_name" : "nextcloud",
"cluster_uuid" : "****************",
"version" : {
"number" : "8.17.3",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "***************",
"build_date" : "2025-02-28T10:07:26.089129809Z",
"build_snapshot" : false,
"lucene_version" : "9.12.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}

Настройка поиска по файлам

Эти действия не влияют на полнотекстовый поиск, но сильно ускоряют поиск внутри самого Nextcloud.

# Настраиваем базу данных для поиска по файлам
docker exec -it nextcloud-postgres psql -U nextcloud -d nextcloud -c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
docker exec -it nextcloud-postgres psql -U nextcloud -d nextcloud -c "CREATE INDEX CONCURRENTLY IF NOT EXISTS fs_name_gin_trgm ON oc_filecache USING GIN (name gin_trgm_ops);"
docker exec -it nextcloud-postgres psql -U nextcloud -d nextcloud -c "CREATE INDEX CONCURRENTLY IF NOT EXISTS fs_path_gin_trgm ON oc_filecache USING GIN (path gin_trgm_ops);"

Настройка полнотекстового поиска

Настраиваем Elasticsearch:

# Выбираем платформу поиска
docker exec --user www-data nextcloud-app php occ config:app:set fulltextsearch search_platform --value="OCA\\FullTextSearch_Elasticsearch\\Platform\\ElasticSearchPlatform"

# Отключаем строку поиска
docker exec --user www-data nextcloud-app php occ config:app:set fulltextsearch app_navigation --value="0"

# Настройка ElasticSearch
docker exec --user www-data nextcloud-app php occ fulltextsearch_elasticsearch:configure '{"elastic_host": "http://nextcloud-elasticsearch:9200", "elastic_index": "cloud", "analyzer_tokenizer": "standard"}'
# Устанавливаем количество реплик равным 0
curl -X PUT "localhost:9200/cloud/_settings" -H 'Content-Type: application/json' -d '{"index": {"number_of_replicas": 0}}'

# Индексировать локальные файлы
docker exec --user www-data nextcloud-app php occ config:app:set files_fulltextsearch files_local --value="1"

# Индексировать внешние файлы
docker exec --user www-data nextcloud-app php occ config:app:set files_fulltextsearch files_external --value="1"

# Индексировать групповые папки
docker exec --user www-data nextcloud-app php occ config:app:set files_fulltextsearch files_group_folders --value="1"

# Максимальный размер файла для индексации (в МБ)
docker exec --user www-data nextcloud-app php occ config:app:set files_fulltextsearch files_size --value="50"

# Индексировать PDF
docker exec --user www-data nextcloud-app php occ config:app:set files_fulltextsearch files_pdf --value="1"

# Индексировать офисные документы
docker exec --user www-data nextcloud-app php occ config:app:set files_fulltextsearch files_office --value="1"

Для Tesseract
не понял, как сделать через команды, поэтому делаем через UI (Параметры
сервера -> Полнотекстовый поиск): Сброс индекса в случае его
наличия:

-2

docker exec -it -u www-data nextcloud-app php occ fulltextsearch:stop
docker exec -it -u www-data nextcloud-app php occ fulltextsearch:reset

Создание файла стоп-слов:

mkdir -p config_elasticsearch/stopwords/
touch config_elasticsearch/stopwords/ru_RU.txt
echo "и\nв\nне\nна\nс\nпо\nчто" > config_elasticsearch/stopwords/ru_RU.txt

Запустить процесс индексирования в фоне:

# Запуск в фоне индексации
nohup docker exec -u www-data nextcloud-app php -d memory_limit=-1 occ fulltextsearch:index > /tmp/fulltext_index.log 2>&1 &
# Просмотр лога
tail -f /tmp/fulltext_index.log

Просмотр результатов индексирования:

$ curl http://localhost:9200/_cat/indices\?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size dataset.size
yellow open cloud V_uK0nSIQliHcQZfOJEEmA 1 1 111064 1 12.2gb 12.2gb 12.2gb

$ curl -s "http://localhost:9200/cloud/_count" | jq .count
111104

После окончания индексирования включаем индексацию измененных файлов:

# Создаем конфиг
$ sudo nano /etc/systemd/system/nextcloud-fulltext.service
[Unit]
Description=Nextcloud Full Text Search Live Worker
After=docker.service
Requires=docker.service

[Service]
Type=simple
ExecStart=/usr/bin/docker exec -u www-data nextcloud-app php -d memory_limit=-1 occ fulltextsearch:live
Restart=always
RestartSec=10
User=root

[Install]
WantedBy=multi-user.target

# Запустить сервис
$ systemctl daemon-reload
$ systemctl enable --now nextcloud-fulltext

# Перезапустить
$ sudo systemctl restart nextcloud-fulltext.service

# Посмотреть логи
sudo journalctl -u nextcloud-fulltext.service -f

В
процессе индексации столкнулся с такой проблемой, которую не знал, как
решить, и только после множества попыток и поисков ответов на вопросы
нашел решение. Оказывается, Elasticsearch очень плохо работает с большим
количеством мелких файлов, которые у меня были в папках .git и .env. Решил это созданием в этих папках файла .noindex, который указывает Elasticsearch не индексировать этот путь:

# Найти папки .git/.venv*/.env* и создать внутри .noindex
find /main/documents -type d -name ".git" -exec touch {}/.noindex \;
find /main/documents -type d -name ".venv*" -exec touch {}/.noindex \;
find /main/documents -type d -name ".env*" -exec touch {}/.noindex \;

Работа
с ошибками Elasticsearch отдельная тема, так как не нашел, как точечно
работать с ними. Если ошибка возникает, то она указывает на конкретный
идентификатор файла внутри базы данных Nextcloud.

# Пример ошибки в логе
┌─ Errors ────
│ Error: 4/4
│ Index: files:83013800
│ Exception: OCA\FullTextSearch_Elasticsearch\Vendor8\Elastic\Elasticsearch\Exception\ClientResponseException
│ Message: unknown error


└──

То есть Вы не можете по идентификатору понять, какой это файл, но есть способ, как увидеть путь к нему:

# Заходим в контейнер базы данных
$ docker exec -it nextcloud-postgres psql -U nextcloud -d nextcloud
# Выполняем запрос
SELECT fileid, path, name, size, mtime
FROM oc_filecache
WHERE fileid = 83013800;

# Удалить файл из индекса
docker exec -it nextcloud-elasticsearch curl -X DELETE "http://localhost:9200/cloud/_doc/files:83094143?pretty"

Также можно создать файл .noindex, если хотите исключить папку из индексирования.

Настройка онлайн-редактора

Параметры сервера -> ONLYOFFICE. В поле «Адрес ONLYOFFICE Docs» прописываем адрес нашего сервера http://<your_ip>:8080.
Далее можно настроить какие типы файлов открывать при необходимости или
ставить настройки по умолчанию. На этом настройка закончена.

Итог

В сухом остатке:

  1. Мы значительно ускорили поиск по файлам внутри самого Nextcloud, так как настроили соответствующие индексы.
  2. У нас появился полнотекстовый поиск по документам, в том числе по изображениям.
  3. У нас появилась удобная страница с выводом результатов поиска и взаимодействия с ним.
  4. Мы имеем возможность открывать и редактировать документы онлайн, без необходимости их скачивать к себе на устройство.
-3
-4
-5

Ссылки:

  1. Как запустить прокси-сервер для сервисов?
  2. Как установить Docker?
  3. Как запустить сервис с собственным облаком?

*.wikipedia.org - РКН: иностранный владелец ресурса нарушает закон РФ.