Mastodon / GNU social はブログである

GNU social のインストール

Mastodon ブームに乗って GNU social をインストールしてみました。

このところ Mastodon が大流行のようで、その流れに乗って mastodon.cloud にアカウントを作ってみて、そこで情報を仕入れていくつかの記事を読んでどんなものかが少しづつわかってきました。割と早い時期に目にしてたいへん参考になったのは「gnusocial や mastodon の哲学」です。

早速自分でもインスタンスを立ててみようかと思いましたが、環境が整っていれば簡単そうなものの、その環境を準備するのが面倒くさい。そこで Mastodon と交流可能な GNU social を見てみることにしました。参考になったのは「GNU socialのインストール」です。

GNU social のインストールは、インストール版 WordPress を使ってことのある人にとっては簡単です。その説明を読めば分かるように、基本的に要件は PHP, MariaDB(MySQL), Web サーバー(Apache など)で、WordPress のそれと同じです。

まず https://git.gnu.io/gnu/gnu-socialから GNU social を入手し、Web サーバーでアクセスできるところに展開します。既に WordPress を動かしているサーバーなら、https://expample.net/social などのようにサブディレクトリでもいいでしょう。

それから、データベースにアカウントを用意しておきます。

そしてブラウザからアクセスします。あとは欄を埋めるだけです。サイト名、データベースのID、パスワード、管理者の名前、パスワードなどです。これで設定ファイル config.php が作られます。

これで終わり。このへんの手順も WordPress の「5分でインストール」にそっくりです。

一人だとちょっとさびしい

GNU social や Mastodon のタイムラインは

  1. 自分の発言
  2. 自分がフォローしている人たちの発言
  3. ローカル = 同一インスタンスのユーザーの(A)の和
  4. ネットワーク = 同一インスタンスのユーザーの(B)の和(だと思う)

があります。おひとり様インスタンスだと、(C)や(D)の意味がないので、ちょっとさびしいです。

要はブログである

おひとり様インスタンスを立ち上げてみて、WordPress そっくりのインストール過程からも感じたのは、「これは要はブログである」ということです。実際「マイクロブログシステム」と言われています。Twitter もそう言われていましたが、同一サーバー(名前空間)にすべてのユーザーがいるためにそれを意識することがなくなっていました。

自分の発言はブログで言うところの「記事」に相当し、その記事にコメントがついたりトラックバックしているようなものと考えることができます。記事を極端に短くして、コメント/トラックバックを短期間に大量に投げ合っているイメージです。「フォロー」というのは RSS で情報をやり取りして自分のブログに相手方の記事を混ぜ込むようなものです。ブログの記事を寄せ集める Planet (そういえば最近とんと聞かなくなった言葉です) に似ています。

このように考えるとストンと腹に落ちました。Mastodon や GNU social は自分の書く記事と大量のコメントをデータベースに蓄え、それを整形して表示するものと言えます(もちろん他のインスタンスに情報を送る機能を持っていて、それが肝なのですが)。デフォルトの GNU social の見かけに対して、はじめから添付されている qvitter を使うようにすると、同じ中身を Twitter そっくりにして表示します。WordPress で言うところの「テーマ」と同様に、GNU social も外見を変更できます(INSTALL の Themes の節を参照)。

それにしても、ブログをぎゅっと圧縮すると、あたかも IRC やネットニュース(NNTP) のような様態になるとは面白いことです。

やっぱりブログである

「ブログの集合体」と考えると、たとえば「そろそろマストドンについて語っておくか」に見られるような批判は、当たらないとは言わないまでもピント外れと言うべきでしょうか。

たとえば WordPress を自分のサイトに導入してブログを始める。それ自体はとやかく言われることではないでしょう。そうやってブログを運用する大抵のサイトは、アカウント作成を開放して不特定多数の人がそこに書き込む権限を渡すようなことはしません。一人か、もしくは特定少数のライターに権限を与えて運用されています。それと対比すれば mastodon.cloud や mstdn.jp はかなり特殊な状態です。逆に、ユーザー側からしても同じです。他所のブログサイトにアカウントを作れるからと言って、得体がしれないのに個人情報を渡すのだとすれば、それはユーザー側にも落ち度があります。何も Mastodon や GNU social の問題ではありません。

サーバーの設置は自由なソフトウェア実装が存在するだけではだめで、十分な性能を持ったコンピューターと十分なネットワーク帯域が必要になる。GNU SocialはPHPで実装されているし、マストドンはRuby on Railsで実装されている。実行には普通にWebサーバーを運営するのと同じだけの煩わしさがある。

これだけサーバーの実行が面倒だと、結局、既存のサーバーを利用するものが大半だろう。その結果、どこかの学生が1個人が運営している怪しげなサーバーに人が集中する。これはとても問題だ。

自分でやってみて実感しましたが、「これだけサーバーの実行が面倒だ」とは思いません。何度も引き合いに出しますが、インストール版 WordPress がこれだけ広がっているなら、それとほぼ同じ手間で設置できるものですから、同じくらい広まる可能性はあります。そもそも知らなかったという人たちが多いのだと思います。私自身、GNU social という言葉はどこかで小耳に挟んでいたものの、それが何かということを知ろうとはしていませんでした。それが今回の Mastodon 大流行でちょっと触ってみる気になったのです。これから雨後の筍のごとく、あちこちでおひとり様インスタンスが立ち上がるでしょう。

ブログシステムの WordPress も近年になってホスティング会社が簡単にセットアップできる仕組みを提供しています。それと同様になればかなり広まるでしょう。さっそくさくらのクラウドのスタートアップスクリプト Mastodon が現れています。

脱中央集権化

ところで、はじめに紹介した記事「gnusocial や mastodon の哲学」でも強調されている理念に「脱中央集権化 decentralization」があります。それは、今回の大流行に関係しているでしょうか。

もし多くの人がその理念を好ましく思っているなら、いま日本で大流行の LINE などより XMPP のようなオープンなメッセージングシステムが受け入れられていてもいいように思います。ところが登場時期については全く逆で、XMPP のほうがずっと前から存在するのに後から出てきた LINE があっという間に広まりました。

理念よりも、何かもっと表面的なこと—たとえば見た目のいいアプリとか—がきっかけのようにも思えます。XMPPサーバーを公開して数年経つのに登録者はあんまり増えていないからなあ。

Gajim で IRC

PC の中を整理していたら、2012年のメモが出てきました。そのまま捨てていいものか判断に悩んだので、ここに転記してから捨てることにします。

Gajim という XMPP クライアントから IRC を使う、というものです。いまさらIRCもないのですが……。

中継先の設定

まず、中継先を設定します。

操作 → サービスを探索 → … で「アドレス」に、IRC中継を行ってくれている適当なXMPPサーバーを入力します。たとえば step.im とします。「IRCトランスポート」を選択し、一番下の「登録」をクリックします。これで、名簿の「中継先」の欄に、irc.step.im ができます。

チャンネルの登録

次に、その名簿の欄のサーバー名を右クリックして、「コマンドを実行…」とします。「Join channel」を選んで「進む」をクリックします。

IRCチャンネル(先頭には#は不要)に、たとえば「wordpress」と入力し、IRCサーバーに「irc.freenode.net」と入力し、「実行」をクリックします。

チャンネルに参加

操作 → グループチャットに参加 → … → 新しいグループチャットに参加 と進み、

ニックネーム (適当に)
談話室 wordpress%irc.freenode.net
サーバー irc.step.im
パスワード (適当に)

のように入力します。談話室名は、IRC のチャンネル名とサーバー名を「%」でつなげたものにします。ニックネームは適当ですが、NickServ に登録しているならそれを入力し、パスワードもそれに合わせます。

……と、5年ほど前のメモを見ながら試しにやってみてできはしましたが、何しろいまでは IRC をぜんぜん使っていないので、いったい何の役に立つのやら。

Google Talk は生きている、のか?

先日、ChatSecure という携帯端末向け XMPP クライアントを試してみたとき、Google Talk (Google トーク)をふつうの XMPP として使えることに気がつきました。

2015年の初めころ、Google Finally Kills Off GoogleTalk and XMPP (Jabber) Integration などの記事を見て、XMPP との互換性を捨てて「Google ハングアウト」に移行する形で Google Talk はなくなったものだとばかり思っていました。そう、No, it’s not the end of XMPP for Google Talk というタイトルの記事を読んでいても、です。

これらの記事を目にした前後からついその時に至るまで、自分がふだん使っているクライアント Gajim で Google Talk のアカウントにログインできなくなっていました。それで「ああ、終わったんだな」と思い込んでしまったのです。

ところが先日 ChatSecure を試した際、その ChatSecure では GMail アカウントを用い、まったく他所の XMPP サーバーのアカウントの間でチャットできたのです。

前の記事を今よく読み返してみると、

Note that you can still continue to use the Google Talk Service with a third party XMPP client and the Google Talk XMPP servers continue to federate with other domains.

とあります。

ではどうして、PCのクライアントからはログインできなかったのでしょう? いろいろ検索して調べてみてわかったことは、Google アカウントの「2段階認証」を有効にしていたためにクライアント Gajim からログインできなかったようです。自分もこの2段階認証に切り替えたのが、ちょうど前の記事が出てそれを読んだ頃だったのかもしれません。

アプリ パスワードでログイン」というヘルプがその解決法でした。そこにあるとおりにパスワードを生成し、それを Gajim で使うことで無事にログインできました。いったんログインできてしまえば、あとはまったくふつうの XMPP アカウントとして使うことができます。

時系列的にまとめると

  • Google は 2005年ころ Google Talk というサービスを始めた。それは XMPP の拡張で、サードパーティの XMPP クライアントでも利用でき、また他の XMPP サーバーとも相互に会話できた。
  • Google は 2013年に Google Hangout という、Google Talk 後継のサービスを始めた。この時点で「Google Talk というサービスは終了」と言われているが、Google Hangout の機能のうちの文字によるチャットは Google Talk 互換であり、つまり XMPP として利用できた。
  • 2015年2月、Google 自身による Google Talk アプリ(Windows版)は廃止された。(Android版や、FirefoxやChromeの拡張機能の版も存在していたと思うが、たぶん同じ頃に消えたのだろう)
  • この2015年2月に「Google Talk は死んだ」と言われた。たとえば You Have No Choice: Google To Shutdown GTalk Feb. 23, Hello Hangouts など。しかしその記事でもじっくり読んでみると、However, users who are unable to give up GTalk can use third-party Windows apps, such as the open-source Miranda IM, Jitsi, and Psi, to continue using GTalk. と最後のほうに書いてある。

ということのようです。ただし「安全な接続」については注意が必要です。それこそ前の記事に書いたような、OTR など終端間暗号化(E2EE)を用いるのがいいかもしれません。

ChatSecure — 携帯端末向け XMPP クライアント

ChatSecure という XMPP クライアントの存在を教えられて、手元の Android 端末にインストールしてみました。

インストールは簡単。初期設定はまずアカウントです。Android端末だとたいていは google アカウントが入っているはずで、ChatSecure にもそれを使うかという画面になります。他の XMPP サーバーにアカウントがあってそれを使いたい場合は横にスワイプしてそこで設定します。

ChatSecure の特徴は、このアプリの名前や開発元(The Guadian Project)からわかるように、何と言っても「暗号化」です。OTR (Off-the-Record) という規格にしたがって、終端間暗号化でチャットできます(もちろん相手先もこれに対応していること)。 OTR については、「OTRでオフレコチャット!」の記事などが詳しいです。

「大した内容のチャットじゃなし、暗号化なんて別にどうでもいい」と思うかもしれませんが、巷で流行している LINE のようなサービスと比較して書いてみます。

クライアント-サーバー間が暗号化されているか

これは TLS(SSL) でも実現できます。Wi-Fi 接続やら、インターネット接続プロバイダー、回線会社など途中経路での盗み見・改竄を防げます。

サーバー-サーバー間が暗号化されているか

独立していて他のサーバーとの相互乗り入れができない、ほとんどのメッセージングサービスではあまり関係がないかもしれません。XMPP はサーバー間の相互接続が当たり前ですが、それらのサーバーが適切に設定されていればサーバー-サーバー間も暗号化されています(ちょっと古い記事ですが、Support for STARTTLS and SASL in s2s Connections の図がちょうどいいイメージです)。

サーバー内でも暗号化されているか

TLS でクライアント-サーバー間が暗号化されていても、たいていの場合、サーバー内では復号されて相手先の読めるところに保存されます。サーバー内で何がなされているか、ユーザーは知るすべがありません。サーバーの運営者を信用できるかどうかにかかってきます。発信時に個々のメッセージを暗号化(つまり終端間暗号化 End-to-End Encryption (E2EE))すればここで盗み見・改竄されることを防げます。

端末内の余計な情報を収集していないか

ChatSecureこれは通信の暗号化とは関係ありません。たとえば LINE では、端末内のアドレス帳など余計な情報を収集したりすることがあります。LINE のアプリはソースが公開されていませんので、本当のところ何をしているかはわかりません。独立型チャットサービスでしかもサードパーティのクライアントが許されていないようなものは、運営者をもう単に信じるかどうかという問題です。XMPP や OTR といったオープンな規格、ejabberd のようなオープンソースのサーバー、ChatSecure のようなオープンソースのクライアントという組み合わせでは、そのような信頼できない行為を隠しようがありません。

ChatSecure は OTR を使わなくてもよくできた XMPP クライアントだと思います。見た目は直感的で、操作に戸惑うこともあまりなさそうです。日本語化もされていますし、さほど詳しくないような人にもお勧めできます。

チャットサポートを構築する (その4) 連絡先の設定とまとめ

共有名簿 (shared roster)

ふつうの XMPP では、相手先名簿 (roster) は JID に紐付けられ、サーバーに保持されています。ところが匿名サーバーの場合、接続要求があった際にそのアカウントが新たに一時的に生成されるため、その JID には相手先名簿がありません。そこで、XMPP の共有名簿(shared roster)という機能を使うことにします。

ejabberd の設定ファイル ejabberd.cfg では

{modules,
 [
  ...
  {mod_shared_roster,[]},
  ...
]}.

とモジュールを有効化しておきます。

ejabberd のウェブ管理画面の「ヴァーチャルホスト -> anonymous.example.net -> 共有名簿グループ」の画面で、まずひとつのグループを作成します。たとえば

  • 名前: support
  • 説明: サポート窓口
  • メンバー: support@example.net
  • 表示グループ: (空欄)

のようにします。ここで support@example.net は、窓口側(問い合わせを受ける側)の JID です。

さらにもうひとつグループを作成します。

  • 名前: all
  • 説明: 全ユーザー
  • メンバー: @all@
  • 表示グループ: support

ここで @all@ は、「全ユーザー」を意味します。

これで、「anonymous.example.net の全ユーザーの名簿に support グループのメンバー(ここでは support@example.net のみ)を自動的にセットする」ことができ、上述の(3)をクリアできました。

チャットサポート構築のまとめ

ここまでで、どうにかチャットサポートを構築できました。まとめますと、「チャットサポート」に求められる要件、

  1. アプリケーションの事前インストールが不要
  2. アカウント(JID)の登録が不要
  3. 連絡先が登録済み

に対して、(1)は Converse.js を導入することで、(2)はクッキーを利用し匿名サーバーを設定することで、そして(3)は共有名簿 (shared roster) を使うことでクリアして、一応「チャットサポート」的なものができました。そしてこれらを WordPress のサイトに導入するために プラグイン化しました。試しにこのサイトに設置してみました。画面の右下に小さなタブが見えると思います。

とりあえずはできたものの、課題も残っています。

前にも書いたとおり、事前接続のところがよく理解できていないこともあって、匿名サーバーだと使えますが、特定の JID を事前設定しようとするとうまくいきません。また、ページ遷移に対応できていません。

匿名サーバーの場合、共有名簿を使ってみましたが、多重に読み込んでいるのか、同じ相手先が増殖することがあります。どういうことなのかよくわかりません。また、これは匿名サーバーの宿命なのですが、接続した時点で相手先からは認証されていないので(その時点で生成された ID なので当然)、その相手先の在席状況が不明で「オフライン」と表示されてしまいます。印象が悪いので、WordPress のプラグインではこれを隠すようにしてみました。

今回、恥を忍んで中途半端な状態でも公開してこのような文を書いたのは、誰か能力のある人がちゃんとした実装を教えてくれることを期待してのことです。XMPP ならまだしも、Strophe.js や Converse.js で検索しても、とにかく日本語での情報は非常に少なく、どこで聞いたらいいかもわからないほどです。

何かわかる方がありましたら、教えてください。または情報をぜひ公開してください。お願いします。

チャットサポートを構築する (その3) Converse.js を WordPress で使うプラグイン ConverseJS for WordPress

(その1)テストのページに示したように、Converse.js は、css と設定のための script を読みこめば簡単に設置できます。ということは、WordPress のサイトにも設置できます。これを実現するプラグインを作り、公開しました。

GitHub にも置いています

Converse.js を同梱しているので、このプラグインをインストールするだけで済みます。

ダッシュボード -> 設定 -> Converse.js で、主な設定値の変更ができるようにしています。設定値の詳細は Converse.js のマニュアルを参照してください。

設定項目の最初の Converse.js URL は、空白にすると、プラグイン同梱の converse-min.js を読み込みます。ただのファイル名 converse.jsconverse-no-otr.min.jsconverse-no-locales-no-otr.min.js と書くと、やはりプラグイン同梱のものを読み込みます。外部のものを使いたい場合は、正しい URL を設定してください。

2番めの BOSH Server URL は、空白にすると、Converse.js が用意しているテストのための https://bind.opkode.im を使います。なるべくほかの BOSH サーバーを指定してください。

(その2)にも書きましたように、事前接続はまだよく理解していないので、正しい実装ができていません。設定の prebind (事前接続)にチェックを入れ、JID とパスワードを入力しておくと、正しく接続できて名簿も取得できるように見えるのですが、会話ができません。Converse.js の GitHub でのこの議論と同じだと思うのですが、具体的にどうしたらいいかわかりません。詳しい方がありましたら、ぜひ教えてください。下に述べるように、匿名サーバーに接続してチャットサポート的に使うことはできます。

設定例

オープンな XMPP クライアント

初期状態のままで、ふつうの XMPP クライアントのようになります。右下にウィンドウが表示されているはずです。JID とパスワードを入力すれば、そのまま使用できます。

チャットに使用するアカウント (JID と呼ばれます)を持っていなければ、公開サーバー(たとえば STEP.im)で作ることができます。あるいは WordPress.com のアカウントを持っていれば、name@im.wordpress.com の形で、JID として使うことができます。

facebook のチャットにも使えます(たぶん)。JID に (ユーザー名)@chat.facebook.com を入力します。facebook はその中で閉じているので、facebook 以外と会話することはできません。

チャットサポート

匿名サーバーに事前接続することで、チャットサポートの形にすることができます。

prebind にチェックを入れます。JID 欄には匿名サーバーのホスト名だけを入れます。パスワード欄は空のままにしておきます。これで、これが設置してあるページを開くと、自動的に匿名サーバーに接続し、IDを割り振られます。

一応これで使えるのですが、やはり事前接続の正しい理解と実装ができていないので、ページ遷移(WordPressの同一サイト内で別のページに移動した場合)に対応していません。いったん接続が切れて、また新たに接続する(匿名サーバーだと新しいIDになってしまう)ことになってしまいます。詳しい方がありましたら、ぜひ教えてください。

この項もう少し続く

チャットサポートを構築する (その2) サーバー ejabberd の準備

前回の「チャットサポートを構築する (その1)」は、Converse.js を設置し、(テストのページ)のように、普通の XMPP クライアントとして使えるというところまででした。

BOSH サーバー

ここからしばらく、サーバー側の設定の話になります。

クライアントが Converse.js などウェブベースのもので内部状態を保持できないような場合、BOSHという仕組みを介することで、接続を維持します。XMPP サーバーの ejabberd の場合、設定ファイル ejabberd.cfg次のように書くことで、BOSH サーバーにもなります[1]

ポート 5281 (HTTPSの場合)を listen するところに http-bind と書き足します。

{listen,
 [
  ...
{5281, ejabberd_http, [
       ...
       http_bind,
       ...
       ]}
  ...
]}

モジュールの設定のところで

{modules,
 [
  ...
  {mod_http_bind, []},
  ...
]}

を読み込むようにします。

匿名サーバー

XMPP サーバーには匿名サーバーという機能を持つものがあります。一般にクライアントがサーバーに接続する場合、事前に登録して作成しておいた user@example.net という形をした JID と、パスワードが必要になりますが、匿名サーバーは、そのサーバー名だけを指定して接続を試みると、@ より前のユーザー名を乱数のようにそのつど生成して接続します。

サーバーアプリケーション ejabberd の場合、ejabberd.cfg につぎのように設定して SASL 匿名サーバー (anonymous.example.net という名前だとします) を設置します。

{hosts, [ ..., "anonymous.example.net"]}.

{host_config, "anonymous.example.net", [
                               ...
                               {auth_method, anonymous},
                               {anonymous_protocol, sasl_anon},
                               {s2s_default_policy, deny},
                               {{s2s_host,"example.net"}, allow},
                               ...
]}.

s2s_... は、匿名サーバーに接続したユーザーは特定のサーバー以外への通信を禁止するという設定です。

クライアント側の事前接続

ここからクライアント側の話です。

「チャットサポート」として利用できるためには

  1. アプリケーションの事前インストールが不要
  2. アカウント(JID)の登録が不要
  3. 連絡先が登録済み

であることが必要です。前回はこの最初の項目、Converse.js をごくふつうに設置する(テストのページ)ところまで行いましたが、このままでは客側にアカウント (JID) を入力してもらわなければなりません。

Converse.js のマニュアルに Server-side authentication という章があります。別の何らかの方法で事前にサーバーに接続しておき、その情報を引き継げば、上述の2番めの項目をクリアできます。接続先を匿名サーバにすればパスワードも不要になります。しかし、マニュアルには具体的な方法はありません。

次のような方法を考えてみましたがこれで正しいのかよくわかっていません。とりあえず(ある場合には)うまくいっています。もし詳しい方がありましたら、ぜひ教えてください。

Converse.js の初期設定を書く <script> のところの先頭に書き足します。

<script TYPE="text/javascript">
var BOSH_SERVICE = 'https://anonymous.example.net:5281/http-bind';
conn = new Strophe.Connection(BOSH_SERVICE);
conn.connect('anonymous.example.net', '', onConnect);

function onConnect(status)
{
     wpCookies.set('jid', conn.jid);
     wpCookies.set('sid', conn.sid);
     wpCookies.set('rid', conn.rid);
}

Strophe.js は Converse.js に同梱されているので、Converse.js を利用できるようにしていれば、使えます。接続すると JID、SID、RID が確定するので、それをクッキーとして書き出します。ここでは WordPress の wp-include/js/utils.js を利用した記述 wpCookies.set になっていますが、もちろんそれでなくてもかまいません。

それに続く Converse.js の設定では

require(['converse'], function (converse) {
    converse.initialize({
        ...
        bosh_service_url: BOSH_SERVICE,
        prebind: true,
        jid: wpCookies.get('jid'),
        rid: wpCookies.get('rid'),
        sid: wpCookies.get('sid'),
        ...
    });
});
</script>

と、bosh_service_url を指定し、prebindtrue とし、jid, rid, sid をクッキーから読み込みます。

この項まだ続く

  1. BOSH サーバーには2種類あります。local BOSH サーバーは、入り口はどこからでも接続できますが、ローカルのアカウントにしか接続できません。それに対して open BOSH サーバーは、他所のサーバーのアカウントにも接続できます。ejabberd の BOSH は local タイプです。