Nextcloudを本番環境で使い始めて1年ほど。やっとユーザーを「説得」しなくても使ってもらえる、本当に実用的な動作が達成できてきたので、ちょっと書いておきたくなった。
Nextcloudって?
Nextcloudはオンプレミス(自前サーバ)で使えるパーソナルクラウド環境だ。WebDAVファイルサーバを根っこに据え、その環境の上でTalk(チャット、通話、カンファレンス)、Photo(写真アーカイブ)、Map(Photo等と連携する地図)等のさまざまなアプリケーションが動く。QNAPやSynologyなど「専用アプリが動くNAS」のオープンソース実装だと考えれば想像しやすいと思う。
もともとowncloudという同種のサーバからフォークしたプロジェクトで、現在ではNext cloud GmbH (nextcloud.com) による企業サポートがあり、導入は個人から大企業・大学等まで多岐にわたる。
スケーラビリティを配慮した実装により、ランタイム、データベース、ストレージが分割可能で、最大10万人ユーザーがサポート可能である。
ウチは身内5人だけで使うために導入した。ちゃんとログが取れて写真とか消えず全文検索もできるチャットアプリや(これまでLINE、Slack、Facebook Messengerなどを使ってきたが全部要求を満たさない)、外から気軽に使えるファイルシェア方法(Dropboxを使ってきたが制限が年々厳しくなって挫折)が欲しかったのだ。公式のスマホアプリも存在し、たいへん便利に使っている。
構成
Nextcloudの必要構成はいわゆるLAMPで、ApacheやNGINXからPHPランタイムを実行し、ファイルシステムとデータベースも利用する。データベースはMySQLだけでなくMariaDB、Oracle、PostgreSQL、最小構成としてSQLiteでも動作する。
これから始める人は
たぶん一番楽にちゃんと動くのは Ubuntu 22.04 LTS (recommended) か Red Hat Enterprise Linux 8 (recommended) の上で All in one docker image を動かすことだと思う。使ったことがないのであれだが、インストールできるだけでなくパフォーマンスの出る設定になっていることが予想される。
ウチの事例
ウチの場合、Linux でなく FreeBSD で動かそうとしたとか、パフォーマンスが出ないけど非力なマシンばかりたくさん持ってたので分散しようとしたとかの事情があり、自力でしっかりチューンする必要があった。
ハードウエアは:
- FreeBSD(フロントエンド NGINX兼ルータ。HP Microserver N36L, メモリ16GB, 大量のHDD)
- Linux(PHP + ファイルシステム。Lenovo Thinksystem ST50, Xeon E-2104G, メモリ8GB, SSD 1TB)
- Windows (MariaDB。i5-2400, メモリ16GB, SSD1TB)
という変態構成である。
こんな特殊な環境でも、素のLinuxマシンにインストールした場合と設定内容は本質的に変わらない。
ちなみに、現行のXeonなLinuxサーバはごく最近導入したもので、ほんの少し前まではCeleron 1000Mの非力なノートマシンだった。ところが恐ろしいことに、Xeonマシンを投入しても3倍程度しか速くならなかった。PHPの設定が肝だったのだ(10倍程度速くなった)。
インストールと設定
公式ドキュメントの通りにやりました。作業手順としては Example installation on Ubuntu 22.04 LTS に書いてあることをチェックリストにするのが楽だと思う。
NGINX
- nginx.confは公式のNGINX設定例のコピペでOKだと思う。webrootとかサーバー名は自分の環境向けに適宜書き換える。
- fastcgi_read_timeout を増やす。ウチでは600にしてる。
デフォルト設定だと1分でphp-fpmへの接続がタイムアウトするので、Web管理画面からのNextcloudサーバーアップデートや、少し重いアプリのインストールがことごとく失敗する。
この問題への一般的な対処はコマンドライン環境で管理コマンドoccを使用することだが、nginxの設定を正しく行うとウェブインターフェイスから何でも出来て楽である。
設定してある fastcgi_read_timeoutの値600は10分間で、これなら504 gateway timeoutは出ない。作業が終わったら減らした方が良さそうだが、ウチではもう放置しており、問題は出ていない。
ウチのような分散NGINX環境ではタイムアウト設定はこれだけでは足らず、60秒でタイムアウトしてしまっていたので注意されたい(次項参照)。
分散NGINX(逆プロキシ)
ウチではFreeBSDのNGINXからPHP-FPMアクセスをLAN内Linuxサーバ(pops)に投げている。ラウンドロビンなども使える手法だが、ウチでは単なる逆プロクシとなっている。
upstream pops {
server 172.17.1.30;
}
- .phpの投げる先を、いまupstream backendに書いた名前で指定
location / {
proxy_pass http://pops;
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_pass http://pops; とhttp通信を指定しているのは、フロントエンドの FreeBSD マシンでhttpsの暗号を平文(http)に直し、LinuxのNGINXではhttpのみlistenするようにしているからだ。
htppsのサポートは Let's Encrypt でやっており、そのためのhttpアクセスなどは FreeBSD側のserverディレクティブを書く必要がある。
またこの場合、php-fpmのためのタイムアウト設定項目が増える。
client_header_timeout 600;
client_body_timeout 600;
proxy_read_timeout 600s;
こちらの設定は、散々困った挙げ句にRedditのスレッドで見つけた。NGINXの公式ドキュメントにもあるけど、まったく探しきれなかった。
PHP
ここが一番パフォーマンスに影響する。
- まず必要条件として公式のインストールドキュメントの「必要構成」部分の通りに各種のモジュールを入れる
- PHPのキャッシュを片っ端から利かす
そして非常に重要なのが、
- 同時に立ち上げる子プロセスの数をデフォルトから大幅に増やす
これはメモリの許す限り増やす。ここが勘所!
最近のphp-fpmのデフォルトは5とかだし、あまり子プロセスを増やさずに使用CPUのコア数/スレッド数に合わせるのが最適というのがマルチスレッドプログラミングの常識なんだけど、この場合は違っていた。
子プロセスを減らすのは、Nextcloudのように同時転送によるパフォーマンス向上を目指してチューンされてるアプリケーションでは明後日の方向の最適化だったみたい。php-fpmの子プロセスが同時に多数の接続を受け付けるようにプログラミングされているべきだと思うが、そうはなっていなかったのだ。
この設定は非常にわかりにくくて、最新の公式Server tuningマニュアルのphp-fpmの部分でも、子プロセス数計算機へのリンクがさらっと載ってるだけだ。
ところが少し古いバージョンのマニュアルでは、次のような設定例が掲載されていた:
pm = dynamic pm.max_children = 120 pm.start_servers = 12 pm.min_spare_servers = 6 pm.max_spare_servers = 18
pm.max_children = 120 ですと!!
しかもメモリの多いマシンではもっと増やす(上記の計算機による)。
これを見落としていたためにウチのサーバは滅茶滅茶に遅く、最大限チューンした(と思い込んでた)状態で、Talkのチャットを開くのに40秒かかってた。今は外からでも1秒で開く。
これを見落としていなければ、頑張って分散環境を作る必要もなかったかもw
MariaDB
こちらは上記の Example installation on Ubuntu 22.04 LTS の入力SQLをそのまま入れる感じ。分散環境なら、もちろんそれなりの設定が必要だが、データベース素人のオレでもぐぐればわかったので割愛。
----
まあこんな感じです。Nextcloud Hub 3ことNextcloud 25が出てからPhotoアプリなんかも使いやすくなったので、いろいろ楽しく使えます。ぜひ遊んでみてください。
今後の課題
課題というか、まだやってない作業。
ST50をちゃんと使いたいです。いまの構成だとMicroserverが一番遅くてボトルネックになっているのを解消したい。
たとえばSSLのベンチマークを走らせるとST50はMicroserverより2桁速いので(2倍ではなく2桁つまり100倍オーダ)、フロントエンドのFreeBSDマシンのNGINXでhttpsをアンロードするのは負荷分散と言うよりボトルネックという状態。
ST50に大量のメモリとディスクを積んで、SSDをキャッシュにしてルータも兼ねるオールインワン構成に戻すのが良かろうと思ってます。