Mermaidで矢印をめちゃめちゃ繋ぐと楽しい

ボックスと矢印で関係性を記述したグラフがたいへん簡単に描けるMermaidというツールを使ってみたので紹介します。

構成図が描きたい

ひとつ前の『Nextcloudをロードバランシング』という記事を仲間内で見せたところ、わけわかんねえよ構成図描けよ、と言われたので、気になってたMermaidというグラフマークアップツールを使ってみました。

mermaid-js.github.io

こいつはテキストで内容物をゴジョゴジョっと書くだけでグラフ(ノードとエッジで構成された数学的な意味のグラフ…なんだけど、実はパイチャートとかも描けるらしい)が描けてしまうというツール。トップページにいろいろ載ってる。

mermaidトップページの画像

マークアップに必要な文法の解説もいろいろあるんだけど、オレはとりあえずライブエディタkubernetesのチュートリアルの例を突っ込んで、いろいろいじってカラダで覚えました。

それで出来た図がこれなんだけど:

さっきの記事の図

こいつがこのくらいの記述でできるわけです:

graph LR
client-->thenet[Internet]-->router[<b>FreeBSD</b><br>ルータ兼 <br> ロードバランサ<br>兼Redis<br>Nextcloud予備];
router-->linux[<b>Linux</b><br>Nextcloud]
linux --> windows[<b>Windows</b><br>dbserver]
router .-> windows
subgraph home[家]
router
end
classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
class router,linux,windows,ingress,service,pod1,pod2 k8s;
class thenet plain;
class home,cluster cluster;

ここで使った要素は:

  • graph LRで左から右に行く図
  • 文字を書くとそのままノードになる(router[<b>FreeBSD</b><br>ルータ兼 <br> ロードバランサ<br>兼Redis<br>Nextcloud予備]のように名称と表記を分けられる)
  • 矢印で関係性を記述
  • 囲み部分はsubgraph
  • 色付けや装飾はclassDefで書いたものをclass宣言で割当て

という感じ。

気に入ったのが、こいつはグラフ(数学的な)記述ツールなので、エッジ(矢印)を適当に足したり引いたりしてやると、関係性のガラっと変わったグラフが一瞬で描けてしまうこと。

上図にたどり着くまでは紆余曲折あるのでお見せしましょう。まずは最初のバージョン。

最初のバージョン

なんか関係性がヘンです。dbserverはルータじゃなくてNextcloudと通信するでしょ?とかそういうの。それで直したのが次。

ver. 2。もうこんなもんでええやろ

一気にわかりやすくなりました。

これでいいじゃんと思ったんだけど、いらんバージョンアップをしてみる。

構成図を見たがためにわからなくなる例

いやー、Linuxが調子悪かったらFreeBSDからdbserverにアクセスすることもあるんですよ、といいながら足してみたら一挙におかしな感じになりました。

ちょっと矢印の意味が統一されてないよね? アクセスの流れと頻度でやろうかな。ということで整理:

 

まだなんかおかしい

いや、これって単にFreeBSDマシンから見た流れだよね? もうユーザー視点で整理したほうが良くね?  ということで出来たのが完成版:

完成版

頻度を反映したり

頻度を反映しよう

矢印増やしたくない? てことで足したり

あかんやろ

みたいなことが、数行のコピペだけでできてしまうわけです。

これらは以下のように、コードの記述的には「linux --> windows」の行を増やしたり

 linux --> internet
 windows --> client

の2行を足したりしてるだけです。やるなグラフ理論

Mermaidのページに初めてアクセスしてから最初のバージョンを出すまでに30分くらいかかってますが、そのあと最後の図までの足したり引いたりは、全部で20分とかです。グラフ最高!!

Joplinで使えます

もうひとつ大事なことがあります。最後の2枚はOnline Editorじゃなく、Joplinに標準で入ってるインラインプラグインで描いてるんです。

JoplinはEvernote代替を目指してるノートアプリですが、組み込みのMarkdownエディタがたいへん強力で、書いたMDが即座にフォーマットされるライブコーディングエディタになってます。

そしてmermaidに関しても、記述が即座に図に反映されてくれます。つまり、だいたい手元で完結してていじり放題です。

さいきんは50人くらいのクラスで授業とかやってるんで、資料作りが大変だったんですが、こんな感じで定形に流し込むだけで関係性を記述できるグラフが簡単に描ける、しかもその場で…! ほとんど夢のようです。

いやー、便利な世の中になったよね。やり放題ですわ〜。

Nextcloudをロードバランシング

たいへん遅いマシンで動いているNextcloudの負荷を少しでも分散したいシリーズ。今回はロードバランシング。バックエンドのサーバは1台だけで、まったくロードバランスできてないけどロードバランス構成をとりたい。やりたいからやる。という話です。

ちゃんと書こうと思ってたけど、書いてみたら何をやったか結構忘れてて、後から読んだらわけがわからなそうな備忘録ができました。いつものことだ。

分散には成功したので、バックエンドのサーバは今後その気になれば増やせるけど、全体的な狙いはどちらかと言うと、なんでもやらせすぎな家サーバの負荷分散です。

ちょっと前に、dbサーバにWindowsマシンを投入しましたが、今回は、非力だけど家サーバよりは強いCPUを持ちSSDも積んだLinuxマシンを投入してウェブサーバとし、こいつにNextcloud本体の負荷(php-fpm)を丸投げします。

目標

以下の形を目指しました。

構成図
  • 新サーバはUbuntu22.04ltsのノート。CPUはCeleron 1000Mと、これまたどんくさいCPUを積んでますが、FreeBSDマシンよりは高速でメモリが8GB、SSDが1TBあるのでNextcloudしか動かさなければ軽そう。
  • ロードバランサはFreeBSD 13の家サーバ。CPUがAthron Neo N36Lの10年以上前のマシンですが、メモリは16GBでディスクは20TBくらい積んでる(ZFS)。これまでのNextcloudサーバそのもので、今後もルータでありファイルサーバでありトラブル時の代替サーバです。

やったこと

  1. 新サーバでテストインスタンスが動くとこまで持っていく。
    • phpモジュール等のインストールや設定が済んでないと引っ越しもできないため、 一番簡単な条件出しとして、実際に /var/www/nextcloud-test にサラからインストールして動かす。 
    • Nextcloudのインストールはこれの通りに普通にやる:

      Installation and server configuration — Nextcloud latest Administration Manual latest documentation

    • nginxはhttpのみに設定する(listenを443→80に)
    • phpは22.04の標準の8.1がNextcloud未対応ということで使えず、8.0を

      How to Install PHP 8.0 on Ubuntu 22.04 LTS - LinuxCapable

      に書いてあるとおりにしてインストール。
    • phpまわりのモジュールのインストールや設定はいろいろあるけど、まあドキュメントのとおりにやれば大丈夫。 
      • ただしメモリキャッシュは複数のNextcloudを動かすのに備え、APCuに加えRedisも使って分散キャッシュやファイルロックができるようにしておく。Redisはこれまでのサーバで動いてるのでこれを使う。
      • (ちなみにデータキャッシュはウェブサーバが1台だけならAPCuの内部キャッシュだけでよい。Redisが動いているのは、元サーバのNextcloudインストール時にドキュメントに書いてあるものを闇雲に全部動かしたため。同様の経緯でmemcachedも動かしたが、こちらはまったく不要なので今回止めた。)
      • php-fpmだけでなく、コマンドラインから使うoccなどがメモリキャッシュを使えるように(しないとエラーが出る)、/etc/php/8.0/mods-available/apcu.iniでapcまわりの設定をしておく。
  2. ロードバランサでのSSLアンロード & HTTP変換実験
    • これまでのサーバにはSSLアンロードとRedisサーバを担当してもらう。
    • httpのロードバランサ(リバースプロキシ)にはHAProxyとかあるけど、nginxのみの簡単な設定で行ける
    • 参考ドキュメント:

      How To Set Up Nginx Load Balancing with SSL Termination | DigitalOcean

    • このドキュメントはけっこう長いけど、それはSSLを動かすところやウェブサーバがロードバランサとしか通信しないようにするところなどに紙幅を割いているから。
    • ウチでは元のサーバでSSL自体は動いていたし、後背はイントラネットでロードバランサ=ウェブサーバ間のセキュリティはあまり考える気がないため、骨の骨の設定である "Virtual Host File And Upstream Module" という項の内容しか多分やってない。
      • これは本質的にはnginx.confで2箇所設定するだけ:
      • upstream mywebapp1 {
            server 10.130.227.11;
            server 10.130.227.22;
        }
      • server {
            listen 80;
            server_name example.com www.example.com;
        	
            location / {
                proxy_pass http://mywebapp1;
                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;
            }
        }
      • upstreamはserverに前置して設定する。
      • upstreamで設定した名前(この例ではmywebapp1)を server 内の location / のproxy_pass に渡す。
      • mywebappをhttp://でアクセスするのがキモ。たったこれだけとは!
    • Let's Encryptのワイルドカードな証明書を使っているので、既存インスタンスのホスト名をnextcloud、新サーバにリダイレクトするホスト名をnextcloud2として設定した
      • server項を書き足して既存のNextcloudインスタンスと分けて
      • upstreamとhttpで通信する
  3. 新サーバで旧サーバの環境をNFSマウントしてテスト。FreeBSDUbuntuhttpdを担うユーザーのデフォルトのUID/GIDが違ってて面倒だったが、Ubuntu側でFreeBSDと同じ80:80にして解決。これで解決してくれるUbuntuはすごく楽。もうそれなりに動く。
  4. 新サーバで旧サーバの環境をrsync(80GBに5、6時間かかった。Joplinの細かいファイル群が重い)で丸コピーしてテスト。ちゃんと動く。あとは、テストインスタンス側のconfig/config.phpのoverwrite関係だけが「設定」の「概要」にある「セキュリティ&セットアップ警告」に引っかかる状態。
  5. 旧サーバを止めてrsyncし直して(今度は4分しかかからず)切り替え。overwrite関連は、Reverse proxy — Nextcloud latest Administration Manual latest documentation の最後のとこにあるExampleとにらめっこして設定したので、「セキュリティ&セットアップ警告」も「すべてのチェックに合格しました。」となる。よしよし。
  6. すっかり安定して動いてると思ってたら、スマホアプリから写真がアップロードできず、さんざん悩んだ。 request entity too large とか言ってくる。
    • これはロードバランサのnginxでclient_max_body_size 512M; を入れてなかったため
    • ロードバランサはただ投げるだけかと思っていたら、デフォルトの制限などは効いてくるのでした。
    • 何が起きてるのかまったくわからなかったが、NextCloudで413エラーが表示される問題【Nginx】 というページで納得。
    • 手を抜いて安心してた場所でひどい目にあうのはいつものことだね…。

ともあれ完成です。あとはこれを丸コピーすれば複数のインスタンスで動かすことも可能。

感想

むちゃくちゃ速くなりました!…相対的には。

絶対的にはまだ微妙な性能です。Talkアプリをタップしてからチャンネル一覧が出るまで、たっぷり5秒かかる。以前は12秒くらいかかってたので人間的なスピードになったけど、まだ満足とは言い難い。

分散によって実験しやすくなったので、今後もいろいろ投入してみたい。

今後やりたいこと

これやりたい。

  • 新サーバが止まる時には元サーバを上げておきたい
  • 元サーバのNextcloudは普段は止めておくが、nginxの設定をいじるだけで動かせる状態にはしておきたい
  • というわけで、新旧サーバでファイルの同期は取っておく必要がある

から。

旧サーバのNextcloudインスタンスは新サーバにNFSマウントしてあり、そのままローカルファイルシステム同様にアクセス可能なため、同期そのものはrsyncで容易に取れるわけです。

Nextcloudの構成はwebサーバ、ストレージ、データベースから成る。ウェブサーバは今回設定し、データベースはdbサーバをそのまま使うので、あとはファイルの同期だけ取れば、すぐに復旧できる。

NFSのキャッシュを頑張るとか、Union FSを使うとか考えたんだけど、realtime rsyncでぐぐったら出てきたlsyncdが便利そう。lsyncdはディレクトリに変更があったら即座にrsyncを走らせて同期をとってくれるやつです。

ちょっと今週はもう時間がないけど、次はこれを入れようと思います。

NextcloudをSSL無しで使う

備忘録。

NextcloudをSSL無しで使うには、httpdの方の設定を変えます。Nextcloudの方はいじらない。ウチはnginx。

  1. listenするポートを443から80に
  2. ssl_certificateとssl_certificate_keyの行を削除
  3. fastcgi_param HTTPS on; の行を削除

でいけます。

Nginx Example Configurations — Nextcloud 9 Server Administration Manual 9 documentation

より。Wayback Machineの奥底に眠ってる古いドキュメントです。

・・・・

SSLを外すとか、まあ普通はそんなことやらんと思うんですが、SSLターミネーション付きのnginxロードバランサの後ろにNextcloudサーバを置いて、

 

Nextcloudサーバ ==http== ロードバランサ(ルータ)==https== インターネット

 

という形にしたい。で、いま内部のネットワークでテスト用のNextcloudを動かしてるんですが、それでちょっと詰まった箇所のメモ。

元情報:

I don't want to use HTTPS - ℹ️ Support - Nextcloud community

NextcloudのデータベースサーバをM1なMac miniにまかせたら死んだ(オレが)

 

Nextcloud便利だけど重い

Nextcloudという「オープンソースのSynology」みたいな、ファイルサーバーベースのウェブアプリケーションスイート("self-hosted productivity platform")があります。

ウチではDropboxの代替として導入したところ、家族用のSlackを内部アプリのTalkで置き換え、Evernote代替のJoplinの保存先として設定し…という感じで順調に依存度を高めてます。

ところが、これが動いてる家庭内サーバが遅い。HP Proliant Microserverという10年くらい前のSOHO用サーバで、NTT-Xストアで2万くらいで買えたために一時期流行ったモノ。ドライブベイが5本あってeSata接続されてるので足回りはそこそこ速いものの、CPUが当時の省電力タイプ(AMD Athlon II)なので、NextCloudみたいな Web サーバ + PHP + DB構成の現代的なサーバープログラムを動かすにはいかにも力不足。*1

PHPのアップデートやキャッシングやJITコンパイラの導入など、できることはやりつくしました。

さすがにもうこのサーバは古すぎるなあ、新しいのほしいけど、この手の部内用サーバってクラウドに置き換えられて絶滅しちゃってるんだよなあ…。

高可用性への道

と思っていたところ、こんなドキュメントを見つけました。

An Insiders Look into scaling Nextcloud by Matthias Wobben

Nextcloud社はサーバをオープンソースで開発しつつ商用サポート版とかを売る商売をやってまして、これはそのセールスエンジニアが書いたプレゼンです。

アーキテクチャ解説の部分に、こんな連続図がありました:

全体の構成



Nextcloudプログラム本体



データベース



ファイル群



分ける

 

ふむふむ・・・と見ていって、9ページでスパッと分かれたのを見たときは、思わず「かっけー!」って叫びましたね。なんかとろくさいと思ってたNextcloudは、実はキレイに分割できるアーキテクチャになっていた。

Nextcloud社では、この形で(さらに負荷分散を加えることで)最大5万から10万ユーザーを実現してるとのこと。プレゼンの後半には実際の導入例とかが載ってました。

いやーすばらしい!

このスケーラビリティは、モダンなウェブアプリなら当然ちゃあ当然…なのかもしれませんが、オレは自分で実用的にいじってるものがきちんと分散できる状況にあったことがなく、むしろ複数のサーバを仮想化で1台にまとめるとかの事例ばかり見てきたわけです。

だから、眼の前のものを分割してパフォーマンスブーストができる、という事例を現実感を持って眺められたことで感動しました。こいつはやってみたい!!

家庭内ロードバランシングしてみる

それで自分ちのことを考えてみると、特に重いのがデータベース。MariaDBというMysqlの派生プロジェクトのやつで、Mysqlより(もちろんSQLiteとかよりはずっと)速いらしいんですが、NextCloudを使っているときにtopで監視してると、

  1. MariaDBがCPUを100%近く使う
  2. 数秒で落ち着くと、いくつも起動してるphp-fpmのチャイルドプロセスがそれぞれ20-50%ずつ使う
  3. 数秒で落ち着くと、手元の表示が出始める

というパターンが頻出します。データベースとphpが足を引っ張ってる。データベースが片方の足を、phpがもう片方の足を引っ張って、思い切り沼に引き込まれてる感じ。

これらのCPU boundな処理を外注できれば高速化できそうです。

んで、データベースサーバは切り出すのに最適です。

まず、

  • もともと分離されてるのが本来の形だから簡単なはず

である上に、

  • 使用容量が小さい
  • CPUとdisk I/Oが重い

というデータベースサーバの条件が、

  • CPUパワーを余らせてる
  • ディスクは250GBで小さすぎ

というM1 Mac miniにピッタリだったから。

mimi(M1 Mac mini の hostname)、キミに決めた! 働いてもらうぜ!

Mac mini M1にMariaDBをインストールして分散

さっそくmimiでport searchしてみるとmariadb-10.8-serverというのが見つかりましたのでインストール。元のサーバのmariadbデータのバックアップを持ってきて流し込み、アクセス権を設定し、元のサーバのNextcloudのnextcloud/config/config.phpを編集して接続できるようにしました。

それで動かしてみたら速い!…?

速いんだけど、思ったほどではないっすね~。php-fpmが処理の大部分の時間を使っていて、こちらのほうが重い。反応時間は2/3くらい。

Mac mini M1にphp-fpmをインストールして分散

それではこのクソ重いphpもmimiにまかせてしまいましょう。mimiにphpをインストールして、Webサーバのnginx.confのlocalhost:9000をMac miniに向ける…ん? 動かない。

オレは勘違いしてました。php-fpmの動いてるマシンにリダイレクトするだけで分散できるんだろうと。この勘違いは、nginx.confのphp-fpmの設定にあります。phpの処理はlocalhostのポート9000に飛ばすようになっている→ということは、データも何もかも一緒に飛ばしてくれるんだよね? と。だってデータベースサーバってそういう分割なんですもん。

ところがphp-fpmは、phpスクリプトを直接処理できないウェブサーバのための機構であり、phpスクリプトとはもともと簡易な動的なページ生成(「ホームページ」を訪れたら中に現在時刻が出てるとか)のためにあります。ここらへんはデータベースサーバとは根本的に違った出自だからしょうがない。

というわけで、これは処理部分だけ飛ばすわけにはいかず、プログラムやデータの入ったファイルシステムが見えている必要があります。(上の分割図でいうところのWebサーバ部分)。

Mac mini M1でファイルサーバからnfsマウントして分散

で、元のサーバからこのあたりをnfsエクスポートしてmimiでマウントして実験してみると…なんかファイルシステムが見えない。index.phpを処理しに行ったphp-fpmプロセスが返ってきません。

しかもここでトラブル発生。mimiのmariadbがCPUを使い切って暴走してます。元のサーバからのアクセスをそのままにして実験したのが悪かった? しかしデータベースなんて複数マシンから同時アクセスされるのが普通じゃないの??

とりあえずmimiのnginxを止めて、mariadbは再起動。

諦めてデータベースサーバの分散だけでよしとする…だがしかし

とりあえず調子良く動いているので安心していたところ、夜になって急にNextcloudの反応がなくなりました。504 Bad Gatewayとか出る。

nginxのログを見てみるとphp-fpmがタイムアウトしてます。これはデフォルト60秒なので、Nextcloudのアップデート時なんかには出ることがあるエラー。

そんなに負荷が高いのかと思って、サーバでtopを見てみると…静かなもんです。いつもよりぜんぜん使われてないというか、php-fpmが上に来てない。

ps auxw | grep phpで見るとphp-fpmのプロセス自体は動いてる。なのにnginxに処理が戻らない。なんか起きてますな…。

変わったことといえばmariadbの分散…というわけでmimiを見てみると、なんかMariadbの負荷が高いですね…。ちょっと再起動してみる。反応変わらず。

とりあえずこの時点でデータベースのバックアップを取ってみる。テーブルが壊れてるとかならバックアップもまともに取れないだろうから、そのときは移行したときのバックアップまで巻き戻す…あれ? 普通にバックアップ取れる。データベースじゃないのか…。

php-fpmのエラーログを見ても、特にエラーは出てない模様。php.iniかなんかでログレベルをdebugまで上げてやると、チャイルドプロセスの展開状況を毎秒知らせてくるレベルでログを吐くんですが、これをやっても出ない。

サーバの環境がなにかぶっ壊れたかなあ、とphpを一旦アンインストールして再インストールしてみたり、はては

freebsd-update upgrade

までやってみたけど、やっぱりphp-fpmの処理が返ってこない状況は変わりません。

やっぱりやっぱりデータベースじゃないの?と思ってmysqlコマンドで接続してみると、普通に接続できる。やっぱりデータベースじゃないのか…と諦めて寝ました。

データベースをWindowsに移してみる

もともと24/7でまったく止まらずにちゃんと動いていたものが急に調子が悪くなり、しかも原因不明となれば、変えたところがおかしいに決まっているわけです。

しかし負荷分散してアプリを軽くする実験を後退させたくもない。

そしてデータベースサーバは本当に何にでもインストールできる。

というわけで翌朝。これもわりに遊んでるくせに高速な、図書室のWindows 10マシンにMariadbをインストールしてみました。管理の作法がいろいろ違っててめんどくさかったけど、サクッと入って快調に動作。

(軽くハマったのはデータベース本体の管理。「データベースサーバプログラムに接続できるように設定する」ということと「特定のデータベースに接続できるように設定する」ということって違うのね…。mimiに入れたときもやったはずだけど、まだ慣れてない)

それでこちらのデータベースに接続してみると…Nextcloud復活したよ!!

macOS is not UNIX!!

大人しくしてればいいものを実験を続けました。せめてphpを分散できないかなあと。

しかしMacのnginxがNFSマウントしたボリュームの中のファイルを全く読めない。

これはphp-fpmとの絡みを考えたくなかったので静的ファイルで実験したり、macOS特有のファイルアクセス制限を逃れるために置き場(nginxのdocument root)をいろいろ変えたりしたんだけど、どうしても読めないんですね。nginxの設定そのものがおかしい?と思って/Users/me/Public/の下にindex.htmlを作ってやるとあっさり読めるんですが、同じファイルがNFSの中に入ると読めない。

しかもこれ、エラーはPermission DeniedではなくOperation not permittedが出る。

そうはいってもやっぱり権限問題なんじゃない?と思って sudo _www cat index.html とやると普通に読める…。

サーバ側の設定がおかしいのかもなあ…と思って、Pop!_OS(Ubuntu派生のたいへん使いやすいデスクトップLinux)の入ったノートPCでnfsマウントしてみると、めちゃめちゃあっさりnginxから読めるw

というわけで、ブン投げました。Macはサーバにならん。

さらに頑張ってなんとか動かしたとしても、またAppleが破壊的な変更をやってくるだろうということが容易に予想がつくので、学習資源が再利用不能すぎるんですよね。

なのでmimiはそういうことに使わないでよし。です。php-fpmの処理だけならRasPi4とかでも現行サーバよりは軽くなるはず。

ふりかえり

mimiのMariadbは最新版を入れたんですが、マシンがM1であることを考えると、バージョンが新しすぎたかも。次に実験するときは、よく枯れたやつを入れてみます。それでも十分速いはずだし、謎のエラーが出なくなるなら素晴らしい…しかし出なくなるかなw

*1:CPU Markは478とかで、10万オーバーな最新のRyzen Threadripper PRO 5995WXの1/200とかしかありません。何だよ10万オーバーて。ベジータ様か。

NextCloudのWebDAV URLはNextCloudのドキュメントで見よう(Joplin連携)

また備忘録。

ずっと探してたEvernoteの代替としてJoplinを使い始めた。オープンソースEvernoteの置き換えを目指したという、まさに探してた方向性のアプリ。

https://joplinapp.org/

https://joplinapp.org/

Markdownでメモが書けるだけでなく、ウェブクリッパーがちゃんとあるし、Evernoteからの移行ツールも完備。すばらしい。

ただし、クラウド型アプリの常として、どこからでもアクセスできるファイルの保存先が必要。有料ユーザー/無料ユーザーというのは無いので(Joplin Cloudという有料クラウドは提供されている)、自分で用意しなければならない。Amazon S3とかOneDriveとかは対応しているのだが、使い勝手のいいGoogle Driveは使えない。しかしウチにはNextCloudがあるので盤石。

と思ったんだけど、ウチのNextCloudをsync先として設定しようとしたところ、"Check synchronization configuration" が通らない。

設定はJoplinのFAQの "Nextcloud sync is not working" にある通り、NextCloudファイルのルート直下にJoplinフォルダを作った上で、NextCloudのWebDAV URLとして

[NextcloudURL]/remote.php/webdav/Joplin

と設定した。ユーザー名もパスワードも何度も試した。が、通らない。こういう時はなんかポカをやってるのがオレのデフォルトなので慎重に調べたが、問題なく見える。

それでまあ、結論は表題の通りでした。NextCloudのドキュメントにありました。

docs.nextcloud.com

NextCloudのファイルサーバにWebDAVでアクセスするときのURLは

[NextcloudURL]/remote.php/dav/files/NextCloudのユーザー名/

だった。

つまり、NextCloudのファイルサーバの一番上の階層にJoplinディレクトリを作った場合は、

[NextcloudURL]/remote.php/dav/files/NextCloudのユーザー名/Joplin

となる。

WebDAVから使ったことがなくてわからなかったけど、考えてみたらマルチユーザーのファイルサーバなんだから当たり前だ。

ハマった人もきっといるかなー、と思って書きました。

 

追記2022/05/20

肝心のNextCloud WebDAVのURLが間違ってたので、ちょっと書き直した。

Nextcloudのアップデータが途中で504 Gateway Timeout。さらにコマンドラインのアップデートツールが見つからない

備忘録。

バックアップやダウンロードに時間がかかることがあるので、NextCloudのウェブアップデータは失敗することが多いです。ウチの場合、バックアップが成功したりしなかったり、ダウンロードは確実に止まってしまいます。

ダウンロードは事前に落としたのをすばやくコピーとかしても(よくないけど)いいんですが、バックアップが不安定なのはストレス。

これにハマる人は多いようで、ぐぐってみると、みんなコマンドラインから updater.phar を実行しています。なんかダサい。

しかも手元のNextCloud 22.0にはupdater.pharがありませんでした。どういうこと?

というわけで、根本的に解決することにした。プロセスをタイムアウトさせないようにする。

うちはNginxなので、

    location ~ \.php(?:$|/) {

(中略)

        fastcgi_read_timeout 600;

としました。10分w

そして

sudo service nginx relstart

これで解決。ウェブからのアップデートが確実に成功するようになりました。

ただ、タイムアウト10分は他のトラブルのときには長すぎるので、アップデートが終わったらコメントアウト&リスタートしとくべし。

Ubuntu (Pop!_OS) で ls -l の出力を sort に食わせたらアルファベットの間に記号が来た。壊れてるのは誰だ。

学生に sort コマンドを教えた日の講義録を作っていて妙な現象にぶち当たった。

kmf@pop-os:~$ ls -l /var/log/ | sort 

drwx------  2 root              root                4096  2月 19 16:27 private

drwx------  2 speech-dispatcher root         4096  1月  9 09:53 speech-dispa

(中略)

-rw-rw-r--  1 root              utmp               11520  5月 13 23:02 wtmp

-rw-rw-r--  1 root              utmp              292292  5月 13 23:02 lastlog

total 91028

kmf@pop-os:~$ 

「あれー? ヘンな並びになってますね〜」とかやってみせるための例だ。

この例ではsortコマンドがlsの出力を受けて最初のパーミッション表示を使ってソートするのだが、肝心のソート内容がおかしい。dで始まるディレクトリが最初に、続いて -rw なファイル群が続き、最後に「total 91028」が表示されているのだ。

すなわち、

d → ハイフン → t

という並びになっている。

記号はアルファベットより前だか後だかに来るはずが、間に入っている。えっ?

なにかヘマでもしてるのかと思い、何度やってみても、また他のディレクトリでやっても同じ現象が起きる。

調査

はじめは、totalの部分が標準エラー出力で後から出てきたりするということなのか? などと思ったけど、2> /dev/null しても出てくるし、なによりファイルに出力を保存して sort しても同じ結果になる。

困り果てて色々やっていたところ、同じマシンにMacからsshで入った端末では再現しない、という現象が出た。

 

kmf@pop-os:~$ export LANG=ja_JP.UTF-8

kmf@pop-os:~$ LANG=C ls -l /var/log/ | sort

(中略)

-rw-rw-r--  1 root              utmp              292292  5月 15 14:20 lastlog

drwx------  2 root              root                4096  2月 19 16:27 private

(中略)

drwxr-xr-x  2 root              root                4096  5月 15 14:08 apt

total 91684

kmf@pop-os:~$

安心の「記号→アルファベット順」である。

現象が安定しないということは、もしや原因は1つではない? などと思ったが、これが緒になった。

実はこのUbuntuマシンでは、日本語manページのインストール確認作業も同時にやっており、Macから入った端末は、その一環で LANG=ja_JP.UTF-8 した環境だったのだ。

そしてこの、日本語環境にすると再現しない、というところがポイントで、UbuntuMac の違いはターミナルのロケール設定にあった。

Pop!_OS で英語設定+日本語単位系とすると、ロケール設定はこのようになる:

kmf@pop-os:~$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=ja_JP.UTF-8
LC_TIME=ja_JP.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=ja_JP.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=ja_JP.UTF-8
LC_NAME=ja_JP.UTF-8
LC_ADDRESS=ja_JP.UTF-8
LC_TELEPHONE=ja_JP.UTF-8
LC_MEASUREMENT=ja_JP.UTF-8
LC_IDENTIFICATION=ja_JP.UTF-8
LC_ALL=
kmf@pop-os:~$ 

Macからsshで入ってexport LANG=ja_JP.UTF-8 した環境ではこうなる:

kmf@pop-os:~$ locale

LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC=ja_JP.UTF-8
LC_TIME=ja_JP.UTF-8
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY=ja_JP.UTF-8
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER=ja_JP.UTF-8
LC_NAME=ja_JP.UTF-8
LC_ADDRESS=ja_JP.UTF-8
LC_TELEPHONE=ja_JP.UTF-8
LC_MEASUREMENT=ja_JP.UTF-8
LC_IDENTIFICATION=ja_JP.UTF-8
LC_ALL=
kmf@pop-os:~$

そしてsortコマンドのソート順は、強調表示した LC_COLLATE に規定されるのだ。

結論

ながながした調査の経緯は省くが(一緒に調査してくださったずけらんさん、ありがとうございました)、「壊れてるのはUnicodeコンソーシアム」が結論だ。

上記の現象は:

  • UTF-8の英語でのソート順はスペース記号とハイフン(-)を無視する
  • これはUnicodeコンソーシアムの決定であり、バグではない

ためであった。

このソート順だと、「-r」で始まる列は「r」としてソートされる。なるほどそれならd→r→tでアルファベット順になっているでないか。

まとめとしては:

  • ソート順は環境変数 LC_COLLATE で制御される
  • 西欧言語のUTF-8設定では空白とハイフンは無視される。英語ではイギリス英語(en_GB.UTF-8)はおろかシンガポール英語(en_SG.UTF-8)でも漏れなく起きる。
  • ハイフンを記号として扱いたければ LC_COLLATE=C にすれば「伝統的」なソート順(ハイフンを含む記号→アルファベット)になる
  • LC_COLLATE=ja_JP.UTF-8 とした場合も、LC_COLLATE=C と同じくハイフンが記号扱いになる

である。

実用的にはLC_COLLATE=C や LC_COLLATE=ja_JP.UTF-8 を使うのが驚き最小だと思うけど、用途によっては空白やハイフンが無視されることを選ぶべきかもしれない。

余談

この現象、日本語や英語を扱っている場合は選択の余地があるけど、フランス語やドイツ語を扱う大変だと思う。

なぜなら、フランス語やドイツ語では単語にアクサンやセディーユ、ウムラウトの付いた文字が入ってくるから。

これらの文字は、LC_COLLATE=C では、素のアルファベットの後ろに回されてしまう。LC_COLLATE=Unicode なら正しく「素の文字→記号付き文字」の順でソートされるのだが、こんどはハイフンが無視されてしまう。

kmf@pop-os:~$ echo 'a á b c f -c d é e' | tr ' ' '\n' | LANG=fr_CA.UTF-8 sort
a
á
b
-c
c
d
e
é
f
kmf@pop-os:~$ echo 'a á b c f -c d é e' | tr ' ' '\n' | LANG=C sort
-c
a
b
c
d
e
f
á
é
kmf@pop-os:~$ 

オレなら泣く。

とはいえ困るのはハイフンの扱いを選択できないことだけなので、これはsortコマンドの方で(より根本的にはロケール情報を処理するlibcに)選択オプションを設けるべきであろう。

参考

わかってる人が怒りながら返事してて示唆に富んでた。

LC_COLLATEの違いによる記号と文字、.と_の優先順位の問題。もっと良いページあると思うけど、とりあえず。

totalを消して解決するなら「ls -ld *」でいいじゃんという誘惑