Nextcloud運用

NextcloudのExternal StorageサービスでのArray to string conversionエラーに対処

エラー概要

Nextcloud 28.x以降にバージョンアップしてから、ログで以下が大量に出力され続けていました。

Array to string conversion at /var/www/html/nextcloud/lib/private/Files/Cache/Scanner.php#224

こちらの対処を行います。

エラーが出る要件

  1. Nextcloud 28.x以降を利用している。
  2. External Storageプラグインを利用している。
  3. このプラグインで、S3(乃至はS3互換のオンラインストレージ)をマウントしている。
  4. マウントしたストレージにファイルやフォルダを保存した。

詳細:Nextcloud Hub 8, copying files to an External Storage configured as primary storage isn't reliable

環境

解決策

上記issueに

Pretty sure this would be fixed by #43794. At least in my limited testing using the merge request as a patch: https://patch-diff.githubusercontent.com/raw/nextcloud/server/pull/43794.diff

とあったので、この通りに実施します。

さっくりとした手順

  1. rootに昇格します。
  2. パッチファイルを入手します。
  3. ファイルを適用します。
  4. Apacheを再起動します。

root昇格

sudo su -

Nextcloudはwww-dataユーザーのみアクセス可能と、厳しめのアクセス権が設定されているので、ここで昇格させます。

ディレクトリ移動

cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。

cd lib/private/Files/Cache

ファイルバックアップ

cp -pi Scanner.php /path/to/backup/directory/Scanner.php.$(date +%Y%m%d)

任意のバックアップディレクトリを指定します。

diff -u Scanner.php /path/to/backup/directory/Scanner.php.$(date +%Y%m%d)

差分がなければバックアップは成功です。

パッチ適用

sudo -u www-data wget https://patch-diff.githubusercontent.com/raw/nextcloud/server/pull/43794.diff
sudo -u www-data patch < 43794.diff 

patching file Scanner.phpと返ってくればOKです。

パッチ適用確認

diff -u /path/to/backup/directory/Scanner.php.$(date +%Y%m%d) Scanner.php
                                                }
 
                                                // Only update metadata that has changed
-                                               $newData = array_diff_assoc($data, $cacheData->getData());
-
+                                               // i.e. get all the values in $data that are not present in the cache already
+                                               // NOTE: we serialize then unserialize here because array_diff_assoc() doesn't 
+                                               // support multidimensional arrays on its own (and otherwise internally casts any 
+                                               // embedded array elements to attempt to compare them - not only generating warnings 
+                                               // like "Array to string conversion" but also, as a resut, overlooking real differences)
+                                               $newData = array_diff_assoc(
+                                                       array_map('serialize', $data), 
+                                                       array_map('serialize', $cacheData->getData())
+                                                       );
+                                               $newData = array_map('unserialize', $newData);
+                                        
                                                // make it known to the caller that etag has been changed and needs propagation
                                                if (isset($newData['etag'])) {
                                                        $data['etag_changed'] = true;

systemctl restart apache2.service

既にrootに昇格しているので、sudoは不要のはずです。

rm 43794.diff 

エラー解消確認

  1. ブラウザでNextcloudサイトに管理者権限でログインします。
  2. 管理メニュー→ログへと進み、適用時刻以降に冒頭のログが出力されていないことを確認します。

NextcloudのDB、照合順序を変更。

NextcloudのインストールでDBを作成す際に

CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

としていました。

運用中、より正確な比較やソートが必要という判断をしたのでDBの照合順序をci(Case Insentive)ではなく、bin(Binary)に変更します。

DBを操作するため、作業前後にメンテナンスモードに入るとともに、ユーザーへの周知は徹底して行ってください。

メンテナンスモードを実行

cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

sudo -u www-data php occ maintenance:mode --on

運用中のNextcloudのURLにアクセスし、メンテナンスモードであることを確認します。

mysqldumpでバックアップを取得する

cd /hoge && pwd

任意のディレクトリを指定します。

mysqldump -h localhost -u nextcloud -p --no-tablespaces --single-transaction nextcloud > nextcloud_backup.$(date +%Y%m%d).sql

DB名やユーザーは自分の環境に合わせます。

ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

DB設定変更

mysql -u root -p
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

ALTER DATABASE nextcloud COLLATE utf8mb4_bin;
USE nextcloud;
SET @DATABASE_NAME = 'nextcloud';

DB名は自分の環境に合わせます。

SET @COLLATE = 'utf8mb4_bin';
SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE ', @COLLATE, ';')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = @DATABASE_NAME
AND TABLE_TYPE = 'BASE TABLE';
EXIT

メンテナンスモードの解除を実行

cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

sudo -u www-data php occ maintenance:mode --off

運用中のNextcloudのURLにアクセスし、普通にアクセスできることを確認します。

切り戻し

何か不具合があった場合の切り戻し手順です。上記、メンテナンスモードを有効化してから行ってください。

ls -l /hoge/nextcloud_backup.$(date +%Y%m%d).sql

バックアップを行ったディレクトリを指定します。

head -100 /hoge/nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあること、平文で読めることを確認します。

mysql -u root -p
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

二回ほど深呼吸して、落ち着いて作業しましょう。

DROP DATABASE nextcloud;
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
EXIT

mysql -h localhost -u nextcloud -p nextcloud < /hoge/nextcloud_backup.$(date +%Y%m%d).sql

この後、メンテナンスモードを解除して、以前と同じ状態か確認します。

作業後:バックアップDBの削除

平文でSQLがサーバ上にあるのは危険な状態なので、以下の措置を執ります。

cd /hoge && pwd

バックアップを行ったディレクトリを指定します。

ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

rm nextcloud_backup.$(date +%Y%m%d).sql
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルが無いことを確認します。

Nextcloudの切り戻し(ダウングレード)手順。

Nextcloud、Webからアップグレードすることはできますが下位のメジャーバージョンにダウングレードすることはできません。

アップグレードの失敗ならびにアプリの相性などで元のバージョンに戻したい場合は以下のように切り戻しを行います。

(今回の筆者のパターンは前者です)

前提

アップグレード前のnextcloudのDBを取っていること

これがなければそもそも成り立ちません。この方法で日次のバックアップを取っていました。 取っていなかった場合は別のサイトをお探しください。

nextcloud_backup.sql等のSQLを任意のディレクトリに格納してください。

環境

特記事項

データ格納ディレクトリを別パーティションにしています。

さっくりとした手順

  1. 切り戻し前のプログラムを退避させます。
  2. 切り戻しを行いたいプログラムをダウンロードします。
  3. プログラムを解凍して再配置します。
  4. コンフィグやアプリデータなどを再配置します。
  5. DBをリストアします。
  6. 切り戻しを確認します。

Nextcloudの退避

sudo mv /home/www-data/nextcloud /path/to/backup/directory/nextcloud.$(date +%Y%m%d)

退避前、退避先はそれぞれ自分の環境に合わせます。

ls -l /path/to/backup/directory/nextcloud.$(date +%Y%m%d)

退避先にディレクトリファイル一式があることを確認します。

切り戻し対象前のプログラムをダウンロード

cd /hoge && pwd

任意のディレクトリを指定します。

wget https://download.nextcloud.com/server/releases/nextcloud-29.0.8.zip

切り戻しを行う(アップグレード前)のバージョンを指定します。

unzip nextcloud-29.0.8.zip
sudo chown -R www-data:www-data nextcloud

Nextcloud(Webサービス)実行ユーザーに合わせます。

sudo mv nextcloud /home/www-data/

元々Nextcloudが配置されていたディレクトリに再配置します。

ls -l nextcloud /home/www-data/nextcloud

ディレクトリ・ファイル一式があることを確認します。

Nextcloud復旧

sudo cp -pi /path/to/backup/directory/nextcloud.$(date +%Y%m%d)/config/config.php /home/www-data/nextcloud/config/
sudo -u www-data cp -r /path/to/backup/directory/nextcloud.$(date +%Y%m%d)/apps/* /home/www-data/nextcloud/apps/
sudo -u www-data cp -r /path/to/backup/directory/nextcloud.$(date +%Y%m%d)/data/* /home/www-data/nextcloud/data/

※データ格納ディレクトリを別のパーティションにしている場合は不要です。ディスクサイズによってはcp -rの代わりにmvを用いてください。

mysql -u nextcloud -p nextcloud < /path/to/directory/nextcloud_backup.sql

-u nextcloudのDBユーザ名-p nextloudDB名です。バックアップのSQLファイルは自分の環境に合わせます。

sudo systemctl restart apache2.service
sudo systemctl restart nginx.service

切り戻し確認

  1. Nextcloudに管理者権限でログインします。
  2. バージョンが切り戻し前に戻っていることを確認します。
  3. 主要な機能が使えることを確認します。

切り戻し後のデータ削除(必要に応じて)

sudo rm -rf /path/to/backup/directory/nextcloud.$(date +%Y%m%d)
rm /path/to/directory/nextcloud_backup.sql

Ubuntu 22.04でのNextcloudのPHPを8.1→8.2にバージョンアップ。

概要

環境でNextcloudを30.xの最新版にアップデート後、以下の警告が出ました。

One or more mimetype migrations are available. Occasionally new mimetypes are added to better handle certain file types. Migrating the mimetypes take a long time on larger instances so this is not done automatically during upgrades. Use the command occ maintenance:repair --include-expensive to perform the migrations.

現在、あなたは PHP 8.1.31 を実行しています。PHP 8.1 は Nextcloud 30 では非推奨となっています。Nextcloud 31 では少なくとも PHP 8.2 が必要になる可能性があります。できるだけ早く、PHP グループが提供する公式にサポートされている PHP のバージョンにアップグレードしてください。 詳細については、ドキュメント↗を参照してください。

いくつかの欠落しているオプションのインデックスを検出しました。データベースのパフォーマンスを向上させるために、(Nextcloudまたはインストールされたアプリケーションによって)新しいインデックスが追加されることがあります。インデックスの追加には時間がかかり、一時的にパフォーマンスが低下することがあるため、アップグレード時には自動的には行われません。インデックスが追加されると、それらのテーブルへのクエリが速くなるはずです。インデックスを追加するには、occ db:add-missing-indices コマンドを使用してください。インデックスが不足: "fs_name_hash" テーブル内の "filecache". 詳細については、ドキュメント↗を参照してください。

これに対して対応を行います。

備考

Webサーバの全体的な変更を伴います。作業は慎重に、可能な限り検証環境で試してからの反映を強く推奨します。

ややさっくりしない手順

  1. Nextcloudのメンテナンスモードを有効化します。
  2. Nextcloudで用いているDBのバックアップを取ります。
  3. PHP8.2をインストールします。
  4. PHP8.2の設定を行います。
  5. PHP8.1の無効化とPHP8.2の有効化を行います。
  6. 警告に対する対処を行います。
  7. Nextcloudのメンテナンスモードを無効化します。
  8. 復旧を確認します。

メンテナンスモードを有効化

cd /path/to/nextcloud/root/directory && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

sudo -u www-data php occ maintenance:mode --on

運用中のNextcloudのURLにアクセスし、メンテナンスモードであることを確認します。

mysqldumpでバックアップを取得する

cd /hoge && pwd

任意のディレクトリを指定します。

mysqldump -h localhost -u nextcloud -p --no-tablespaces --single-transaction nextcloud > nextcloud_backup.$(date +%Y%m%d).sql

DB名やユーザーは自分の環境に合わせます。

ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

必要パッケージをインストールします。

sudo aptitude install php8.2

→ 好みでaptitudeを用いています。aptでもOKです。

sudo aptitude install php8.2-{opcache,pdo,bcmath,calendar,ctype,fileinfo,ftp,gd,intl,json,ldap,mbstring,mysql,posix,readline,sockets,bz2,tokenizer,zip,curl,iconv,phar,xml,dev,imagick,gmp}
sudo aptitude install libapache2-mod-php8.2
sudo a2dismod php8.1
sudo a2enmod php8.2
sudo systemctl reload apache2.service
php -v

表示例PHP 8.2.27 (cli) (built: Jan 2 2025 15:36:15) (NTS)

Nextcloudに併せたPHPの設定を行います。

cd /etc/php/8.2/cli/conf.d
cat <<- __EOF__ | sudo tee -a /etc/php/8.2/cli/conf.d/10-opcache.ini
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1
__EOF__
cat <<- __EOF__ | sudo tee -a /etc/php/8.2/cli/conf.d/20-apcu.ini
[apcu]
apc.enabled=1
apc.shm_size=32M
apc.ttl=7200
apc.enable_cli=1
apc.serializer=php
__EOF__
sudo cp -pi /etc/php/8.2/apache2/php.ini /path/to/backup/php.ini.$(date +%Y%m%d)

任意のバックアップディレクトリを指定します。(筆者環境/etc/old/)

diff -u /etc/php/8.2/apache2/php.ini /path/to/backup/php.ini.$(date +%Y%m%d)

差分が存在しないことにより、バックアップが取れていることを確認します。

sudo sed -i 's/memory_limit = 128M/memory_limit = 512M/g' /etc/php/8.2/apache2/php.ini

memory_limitを推奨値の512Mに置き換えます。

diff -u  /path/to/backup/php.ini.$(date +%Y%m%d) /etc/php/8.2/apache2/php.ini
-memory_limit = 128M
+memory_limit = 512M
sudo systemctl restart apache2.service

Nextcloudの警告解消

cd /path/to/nextcloud/root/directory && pwd

自分の環境に合わせます。

sudo -u www-data php8.2 occ maintenance:repair --include-expensive
sudo -u www-data php8.2 occ db:add-missing-indices
sudo -u www-data php8.2 occ maintenance:mode --off

復旧確認

  1. 設定を行ったNextcloudにアクセスします。
  2. メンテナンスモードが解除されていることを確認します。
  3. 管理者権限でアクセスし、管理者設定から上記のエラーやワーニングがないことを確認します。

備考:切り戻し

何か不具合があった場合の切り戻し手順です。上記、メンテナンスモードを有効化してから行ってください。

sudo a2dismod php8.2
sudo a2enmod php8.1
sudo systemctl restart apache2.service
php -v

→ 8.1に戻っていることを確認します。

ls -l /hoge/nextcloud_backup.$(date +%Y%m%d).sql

バックアップを行ったディレクトリを指定します。

head -100 /hoge/nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあること、平文で読めることを確認します。

mysql -u root -p
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

SELECT COUNT(*) FROM nextcloud.oc_users;

二回ほど深呼吸して、落ち着いて作業しましょう。

DROP DATABASE nextcloud;
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
EXIT
mysql -h localhost -u nextcloud -p nextcloud < /hoge/nextcloud_backup.$(date +%Y%m%d).sql

この後、メンテナンスモードを解除して、以前と同じ状態か確認します。

作業後:バックアップDBの削除

平文でSQLがサーバ上にあるのは危険な状態なので、以下の措置を執ります。

cd /hoge && pwd

バックアップを行ったディレクトリを指定します。

ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

shred -u nextcloud_backup.$(date +%Y%m%d).sql
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルが無いことを確認します。