讓 nextcloud 有全文檢索能力FullText Search ElasticSearch

nextcloud 搜尋很好用,若能有全文檢索能力就更棒了,於是外掛 fulltextsearch_elasticsearch就登場了。

開發團隊只針對還在維護的nextcloud版本進行更新,也就是說一旦我們的nextcloud已經EOL了,就不會再收到ElasticSearch的更新。

以下是甘苦談

原本使用的nextcloud 25.x 能搭配ElasticSearch 7.x ,但遇到外掛存在非常嚴重效能低下問題(兩萬個檔案有設定分享,100人使用,建立索引表算一算需要至少三、四個月,太誇張了);由於nextcloud 25版已經停止維護,於是我只剩下升級nextcloud一途。 

我的nextcloud架設在 CentOS 7,docker上面跑好多容器,很穩定;但nextcloud要升級到26時候,出現容器dns錯亂,無法進行dns查詢,只好先還原回25版。

初步認定是CentOS 7或docker版本過於老舊,但我不敢隨意升級docker,最後只能將nextcloud資料複製到新的虛擬主機(RockyLinux 9.4),測試由25升級到26,然後26升級27 結果就很正常,沒有出現dns錯亂問題。

移轉注意事項請參考「將nextcloud從CentOS7移轉到RockyLinux9。

** 升級nextcloud到27,搭配新fulltextsearch外掛,初始索引要18小時,效率差了百倍以上。

開始安裝囉

安裝 ElasticSearch 8.x(ES 8) 引擎

Nextcloud 26或以上必須搭配 ES 8,最新docker版本可至此查詢 https://hub.docker.com/_/elasticsearch

#RockyLinux 9.4、docker 27.0.2

##############  檔案 ./docker-compose.yaml  ################

version: "3.9"

services:
elasticsearch:
build:
context: .
dockerfile: ./docker/es/Dockerfile
container_name: elasticsearch

environment:
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.http.ssl:enabled=false
ports:
- 9200:9200
- 9300:9300
networks:
- elastic
restart: always
volumes:
- indexdata:/usr/share/elasticsearch/data
# 索引過的資料將存放到 /usr/share/elasticsearch/data裡面

networks:
elastic:
driver: bridge

volumes:
indexdata:
driver: local

###########################################################



################ 檔案 ./docker/es/Dockerfile ###############
FROM elasticsearch:8.14.2
# ingest-attachment 一定要安裝
RUN bin/elasticsearch-plugin install ingest-attachment
###########################################################
# 執行容器
docker-compose up -d

安裝完畢,瀏覽器測試一下引擎是否正常 http://ip:9200/ ,事後需填入到nextcloud外掛設定裡面。

nextcloud 安裝外掛 fulltextsearch

#若安裝出問題,請移除app後,再刪除以下資料庫資料,之後就可以正常安裝了
drop table oc_fulltextsearch_indexes;
drop table oc_fulltextsearch_ticks;
delete from oc_appconfig where appid='fulltextsearch';
delete from oc_appconfig where appid='fulltextsearch_elasticsearch';
delete from oc_appconfig where appid='files_fulltextsearch';
delete from oc_appconfig where appid='files_fulltextsearch_tesseract';
DELETE FROM oc_migrations WHERE app='fulltextsearch';
DELETE FROM oc_preferences WHERE appid='fulltextsearch';

外掛需要設定

外掛安裝完畢,還需要填入引擎網址、與索引名稱,其他預設值即可。

「檢查」外掛設定是否正常

docker exec -t --user www-data <nextcloud容器名稱> php occ fulltextsearch:check

「測試」外掛設定是否正常

 docker exec -t --user www-data <nextcloud容器名稱> php occ fulltextsearch:test

一切正常後,就可以開始建立索引表了,這裡建議定期重做索引。

 docker exec -t --user www-data <nextcloud容器名稱> php occ fulltextsearch:index

這裡強烈建議「文件掃描PDF檔」需要利用acrobat adobe pro版內建文字辨識功能(OCR),進行一次自我辨識

第一次初始化索引建立後,才可以使用

最後還需要額外執行live指令,針對後續異動的檔案進行索引

# 自動索引官方沒建議怎做,我自己是在容器本體VM(RL9.4)利用console常駐執行
# 這樣做比較麻煩,需要注意重開後需要手動做
docker exec -t --user www-data <nextcloud容器名稱> php occ fulltextsearch:live

** 有一次我要刪除原本的索引,一直失敗,搞了很久很久很久很久,才發現要先進入容器下指令才有用

docker exec -t --user www-data <nextcloud容器名稱> php occ fulltextsearch:reset

** 目錄裡面新增「 .noindex」 這個檔案,就可以不做index

** 若有安裝tesseract ocr這個外掛,記得進nextcloud容器,額外安裝相關程式(此功能我一直沒成功過)

apt install tesseract-ocr tesseract-ocr-chi-tra-vert  tesseract-ocr-chi-tra tesseract-ocr-chi-sim  tesseract-ocr-script-viet tesseract-ocr-script-hant tesseract-ocr-script-hant-vert

** 以前安裝Micro$oft單機版sharepoint,是個重量級系統,早就有全文檢索功能,但實在是太吃系統資源了,果斷不用。

docker上的nextcloud 為何要移轉到新的vm上?

為何要移轉到新的虛擬主機上? 因為原本虛擬主機已經是EOL了,若nextcloud升級,會面臨資料庫版本不符、docker版本過舊問題;需要另外安裝新虛擬主機、安裝新docker,升級資料庫版本,才能解決nextcloud無法升級問題。

作法如下:

  1. 使用mysqldump 將nextcloud資料匯出,並匯入到新的vm上的資料庫
  2. 將 volume 資料匯出,新docker建立相對應的volume後,再將匯出的資料丟進volume裡面
  3. docker 拉取nextcloud原本images後,重新啟動nextcloud容器
  4. 確認啟動成功後,才能進行nextcloud升級

Nextcloud又一個坑,使用onlyoffice造成的

上次提到我又回歸使用 onlyoffice 75.1版,過了一段安穩日子後,沒想到居然遇到有個pdf,裡面小圖片不見的靈異現象,我還罵同事眼睛業障重,叫同事把看不到圖的那個pdf檔案,直接下載改用adobe reader看看,結果是「要不是我親眼所見,我是萬萬不能相信啊」,還真的連我都業障重,onlyoffice就是看不到小圖片,而adobe reader可以。

後來我先解除onlyoffice檢視pdf檔案設定,改使用nextcloud外掛 pdf.js, 就可以看到原本看不到的小圖片了,坑真的很多很大。

問題雖暫時解決,但pdf.js 功能太少了,不能鎖下載,也不能有浮水印,Gold害。

在沒有更好的處理方案前,我只好先搞定“公司規定不能下載PDF”的規定;最後手動修改程式,直接暴力停用pdf.js的下載功能
環境是:nextcloud 26,pdf.js 2.6

vi /var/www/html/apps/viewer/js/viewer-main.js
# 找到以下字串,將紅色部分刪掉
,e.canDownload?t(“NcActionLink”,{attrs:{download:……,e._v(” “),e.canDelete?…

cd /var/www/html/apps/files_pdfviewer
egrep -r "toolbarViewerRight" .|more
# 找到toolbarViewerRight 後面加上 hidden='true'

另外,安裝完pdf.js 我不確定是否要執行”啟用” javascript功能,但還是記下來好了(官網有特別提到此指令)

docker exec --user www-data -it nextcloud2 php occ config:app:set files_pdfviewer enable_scripting --value=yes

			
		

nextcloud帳號停用會發生什麼事情

所有分享的檔案與目錄,都會失效
  1. 若公司綁定M$ Active Directory(網域主控伺服器),只要停用主控站帳號即可,不會造成分享的檔案目錄失效,而nextcloud的帳號也不需停用

  2. 若沒有綁定網域主控伺服器,則需要移轉檔案所有權(files:transfer-ownership),然後再停用nextcloud的帳號。

    使用該帳號進行移轉



    使用指令方式移轉

https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/occ_command.html#file-operations

另外還可透過資料庫,查詢所有分享連結,以及其擁有者,語法如下

# 例如某個連結失效了 https://cloud.test.com/s/T8wnofnnZjHk93e
# 我們可以透過以下語法,找到哪個帳號停用了
select * from (
select uid_owner uid,ldap_dn name,token from oc_share,oc_ldap_user_mapping where uid_owner=owncloud_name
union
select uid_owner uid,displayname name,token from oc_share,oc_users where uid_owner=uid
) as NewUnionTable
where token='T8wnofnnZjHk93e'

nextcloud誤刪檔案,還原失敗

慘,我的錯。

解決方式:
1. 到nextcloud該使用者目錄,找出<user>/files_trashbin/files 複製到 <user>/files
2. 執行 php occ files:scan –all

若出現 Exception during scan: “files/xxx”) is locked 則進入資料庫,刪除資料表資料 DELETE FROM oc_file_locks WHERE 1;

刪除之後,再次執行 php occ files:scan –all 還原檔案後,原本分享的狀態可能會不見,要自己重新設定了。

nextcloud 聯盟功能Federation

先講結論,nextcloud聯盟功能分享的目錄,並不會把檔案傳到對方服務器。(這樣就無法達到檔案兩邊都有的需求)

如何正確啟用聯盟功能

1. 啟用「Federation」app
2. 在管理介面->分享頁面,做好設定以及加入遠端服務器


3. 設定檔加上「allow_local_remote_servers = true」

修改 config/config.php

或是下指令

occ config:system:set allow_local_remote_servers --value true --type bool

4. 同步位址簿(需加入crontab定期執行)

occ dav:sync-system-addressbook 
occ federation:sync-addressbooks

5. 分享目錄給遠端的聯盟使用者

6. 遠端使用者將會接收到分享目錄的請求

nextcloud還原甘苦談

幾天前我想把nextcloud 25.0.11 升級到 26.0.5 ,這麼多年來從18版一路高歌升到25版,都沒遇到問題,這次卻栽了無法升級,原因卡在資料庫那段,這問題似乎無解,在不想等待的情況下,我決定還原回去。

2023/9/22 發現我25.0.11升級會出錯,官方馬上釋出25.0.12 ,但我升級還是失敗,原來資料庫mariadb 10.3.2版本有問題,我直接docker pull mariadb:10.3 後面不接了,這樣就從25->26能升級成功

還原步驟:

我先將restic 所備份最新版nextcloud備份的snapshot掛載起來,接著停用目前的資料庫(mariadb 10.3.2 多個容器共用);再將nextcloud的相關volume、資料庫還原,結果失敗,失敗原因不明,docker看log也看不出來,web登入出現「Nextcloud the server was unable to complete your request」錯誤,真真急死人;後來爬文,歸納問題可能有三種:目錄權限沒設定好、資料庫問題與ldap無法連線。

不屈不撓檢查才發現原來是我偷懶,當初所有容器所用到的資料庫都統一讓唯一的資料庫容器管理,現在要還原,我停止資料庫容器後,只有還原其中nextcloud的資料庫,其他資料庫不還原,導致重新啟動資料庫容器時,nextcloud資料庫居然有一些資料表損毀(ENGINE=InnoDB)。

好在損毀的資料表是oc_authtoken,只要重建就好了,但是重建失敗,mysql會說該資料表已在,但是query時,mysql又說沒有該資料表,網上有位苦命工程師說建資料表時,遇到這情形,請改用ENGINE=MyISAM格式就能成功,我照著做之後,nextcloud又恢復往日雄風還原成功,但重建的資料表MyISAM跟其他使用InnoDB的資料表格格不入,以後要找一天將資料庫修復才行。
這故事告訴我們,還原資料庫容器要全部都還原,不可只還原其中一部分資料庫。

CREATE TABLE `oc_authtoken` (   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,   `uid` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '',   `login_name` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '',   `password` longtext COLLATE utf8_bin,   `name` longtext COLLATE utf8_bin NOT NULL,   `token` varchar(200) COLLATE utf8_bin NOT NULL DEFAULT '',   `type` smallint(5) unsigned NOT NULL DEFAULT '0',   `remember` smallint(5) unsigned NOT NULL DEFAULT '0',   `last_activity` int(10) unsigned NOT NULL DEFAULT '0',   `last_check` int(10) unsigned NOT NULL DEFAULT '0',   `scope` longtext COLLATE utf8_bin,   `expires` int(10) unsigned DEFAULT NULL,   `private_key` longtext COLLATE utf8_bin,   `public_key` longtext COLLATE utf8_bin,   `version` smallint(5) unsigned NOT NULL DEFAULT '1',   `password_invalid` tinyint(1) NOT NULL DEFAULT '0',   PRIMARY KEY (`id`),   UNIQUE KEY `authtoken_token_index` (`token`),   KEY `authtoken_last_activity_idx` (`last_activity`),   KEY `authtoken_uid_index` (`uid`),   KEY `authtoken_version_index` (`version`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

以上重建table失敗

CREATE TABLE `oc_authtoken` (   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,   `uid` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '',   `login_name` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '',   `password` longtext COLLATE utf8_bin,   `name` longtext COLLATE utf8_bin NOT NULL,   `token` varchar(200) COLLATE utf8_bin NOT NULL DEFAULT '',   `type` smallint(5) unsigned NOT NULL DEFAULT '0',   `remember` smallint(5) unsigned NOT NULL DEFAULT '0',   `last_activity` int(10) unsigned NOT NULL DEFAULT '0',   `last_check` int(10) unsigned NOT NULL DEFAULT '0',   `scope` longtext COLLATE utf8_bin,   `expires` int(10) unsigned DEFAULT NULL,   `private_key` longtext COLLATE utf8_bin,   `public_key` longtext COLLATE utf8_bin,   `version` smallint(5) unsigned NOT NULL DEFAULT '1',   `password_invalid` tinyint(1) NOT NULL DEFAULT '0',   PRIMARY KEY (`id`),   UNIQUE KEY `authtoken_token_index` (`token`),   KEY `authtoken_last_activity_idx` (`last_activity`),   KEY `authtoken_uid_index` (`uid`),   KEY `authtoken_version_index` (`version`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

改成MyISAM就成功重建table

nextcloud雲端檔案,新增額外屬性

公司有追蹤「檔案過期」需求,最方便就是賦予檔案新的屬性—過期日,作為nextcloud粉絲,當然由nextcloud著手,萬幸有個app customproperties能達到要求,最後再寫個程式追查一下資料庫資料表oc_properties 過期日資料,就可以完成系統自動通知功能,定期通知檔案主人快到期,讓主人進行延展或是不再追蹤。

但是該app已經有一陣子沒更新了,不支援nextcloud 25以上版本,有人告知可以小改繼續在25、26版使用,真是幸運,我也依樣畫葫蘆,弄了一個能支援25~28的版本來,有興趣的可以按此下載,下載後先解開zip可得tar.gz檔案,再解開成一個目錄「customproperties」,將整個目錄放在nextcloud的custom_apps目錄裡,並且確認目錄權限正確後,回到nextcloud就會出現「 Custom Properties」外掛,即可啟用。

1 2 3 4