Ubuntu Weekly Recipe

第700回セルフホスト可能なチャット・タスク管理サービスMattermost

Mattermostと言えば、Slackと双璧をなすFLOSSでセルフホスト可能なチャットサービスです。もともとはチャット機能がメインではあったのですが、昨年リリースされた6.0からは定型ワークフローを管理する「Playbook」と、かんばんライクなタスク管理ツールである「Boards」が統合され、⁠オンラインコラボレーションツール」とも言えるほど機能が充実しています。今回は改めて、Mattermostのインストールから紹介しましょう。

祝「第700回」!

2008年1月から開始した本連載も、今回で第700回を迎えることになりました。これもひとえに常日頃から本連載をご贔屓にしていただいている読者の皆様のおかげです。ありがとうございます[1]⁠。

思えば連載開始から14年。いろいろなことがありました。100年に一度の大噴火が発生したり、国内では戦後最大級の大噴火が発生したり、100年に一度のパンデミックが発生したり、国内で観測史上最大の巨大地震が発生したり……なんか、最後を除いて比較的最近の話ですね[2]⁠。

最近は年によって連載回数が50回を切ることもあったため年明けでの700回となりましたが、今後も世の中がどういう状況になろうとも、本連載はできるだけ週刊を維持しながら継続していきたいと思っています。これからもご愛読だけでなく、反応・感想のご提供、場合によっては執筆もよろしくお願いいたします。

さて、今回はそんな第700回を記念することなく、通常運用でお届けします。

ただのチャットではなくったMattermost

Mattermostは言わずとしれた、Slackと双璧をなすFLOSSでセルフホスト可能なチャットサービスです[3]⁠。SlackはSaaSとして提供されるサービスですが、MattermostはSaaSも運営しているものの、オープンソースあることを標榜しセルフホスト可能になっています。

セルフホストした場合は、当然チャンネル数やユーザー数、メッセージ数、チーム数に限界はなく[4]⁠、チャットサービスとして最低限必要なことはほぼできる状態です。また、プラグイン機能も有しており、必要に応じて機能拡充も可能です。さらにより高機能な有償プランも用意されています。こちらはSSOやAD/LDAPなど認証系の機能拡充やサポートの追加などがメインとなります。

Software Designでも3年近く前に、⁠短期連載]Mattermost[導入+構築]入門」と題して次のような連載が掲載されていました。

COVID-19による生活様式が変わる前の話ではあるものの、今でも通じる話が数多く残されています。特に第1回や第4回はチャットをチームで運用する上での考え方や課題をおさえているため、新たに導入したい人には参考になるでしょう。

もちろんセルフホストするならその分運用コストはかかりますし、トラブル時のリスクは当然存在します。Slackはフリープランであっても、その制約さえ受け入れられる環境なら十分に価値のある選択肢です。Slackで環境をがっつり構築しているのであれば、あえてMattermostに移行する必要はないでしょう。しかしながらSlackが合わない、なんらかの理由、たとえばクラウドサービスの利用に制約がかかっているなどの場合は、Mattermostも十分選択肢に入ってくるのではないでしょうか。

またSlackの場合16歳未満は利用禁止ですし、Discordも13歳未満利用禁止等の規約が存在します。それに対してMattermostをセルフホストする場合は、そのような制約は(少なくともクローズドなサービスとして運用する限りにおいては)ありません。仕事で使う場合はともかく、より若い人も参加するローカルコミュニティでチャットを利用したいなら、Mattermostが活きてくるのです[5]⁠。

さらに最近は、定型ワークフローを管理する「Playbook」と、かんばんライクなタスク管理ツールである「Boards」がMattermostに正式に統合され。ただのチャットシステムというよりは「コラボレーションツール」とも言うべきサービスへと成長しました。

他にもSlackからの差異をいくつかあげておきましょう。

  • メッセージにMarkdownフォーマットを使える。勝手にビジュアルエディタになったりしない[6]
  • スレッドへの返信はすべてチャンネルのタイムラインに投稿される。スレッドへの返信が突然チャンネルに登場したり、しなかったりというよくわからない状態を回避できる[7]
  • バックアップが簡単。たとえばmysqldump/rsyncで必要なものはすべてバックアップできる
  • テーマを自由に作れる。発言内応だけじゃなくて、見た目も痛チャットにできる!
  • オーディオ・ビデオコール、画面共有は未実装。基本的に他サービスをチャットから呼び出す形になる

ちなみにMattermostのドキュメントには、Slackからの移行方法もありますので、とりあえずMattermostインスタンスを立ち上げて既存のSlackデータをインポートして使い勝手を試してみるといった使い方も可能です。

UbuntuでMattermostを利用するには

Mattemorstに興味を持ったところで、UbuntuにMattermostをインストールする方法を紹介しましょう。方法としては主に次の3種類が存在します。

  1. リリースされているバイナリアーカイブをそのまま利用する
  2. Mattermost OmnibusでDebianパッケージとしてインストールする
  3. Docker Composeでデプロイする
  4. Kubernetesでデプロイする
  5. GitLab Omnibusに組み込まれたものを利用する

Mattermostはバージョン毎に、バイナリアーカイブをリリースしています。MattermostのバックエンドはGo言語で記述されており、データベースと通知用のMTAだけインストールしておけば、そのアーカイブを展開するだけでMattermostのデプロイはほぼ完了です。よって他のサーバーソフトウェアに比べても、依存関係がほぼないという意味では、Mattermostのデプロイは比較的インストールが簡単です。

ちなみにバイナリアーカイブはEnterprise EditionとTeam Editionの両方が提供されています。Team EditionはEnterprise Editionからオープンソースでない機能を削除したものです。さらにEnterprise Editionには「フリーモード」が存在し、ライセンスアンロックをしない限りはTeam Editionと同じ動作になります。よってMattermost側は、有償機能を使うかどうかに関わらず、将来的にライセンスアンロックできる可能性を残せる、Enterprise Editionの利用を推奨しているようです。

Mattermost OmnibusはDebianパッケージとして、Mattermostをインストールし構築してくれるツールです。Ubuntu 18.04/20.04 LTSのみサポートしています。Mattermost/PostgreSQL/Nginx/Certbotあたりは個々のソフトウェアの独自リポジトリ・PPAを使うことになるのと、構成がある程度決め打ちになってしまうものの、今回の例の中ではもっとも簡単に導入できる方法です。ただしすべてのコンポーネントがシングルサーバーにインストールされます。

Docker Composeは公式が配布しているdocker-compose.ymlを使う方法です。Kubernetesを利用した方法は、すでにKubernetes環境が存在し、なおかつ操作に習熟しているのであれば良い選択肢でしょう。

ちなみにGiLab Omnibusには最初からMattermostが同梱されています。よって設定を変更するだけでMattermostが使えるようになります。

今回は一番簡単な2番目のMattermost Omnibusを紹介します[8]⁠。

Mattermost Omnibusのインストール

今回はサーバー版のUbuntu 20.04 LTSにデプロイすることを考えましょう。ちなみにすでにUbuntuが用意されているなら、Ubuntuのリリースに依存せず、環境を汚すこともないLXD上でデプロイするのがおすすめです

まずはインストールスクリプトをダウンロードします。いきなりシェルに渡してもいいのですが、管理者権限で実行するなら一度中身を確認して、何をするか把握しておいたほうが安全です。

$ curl -LO https://deb.packages.mattermost.com/repo-setup.sh
$ sha256sum repo-setup.sh
203908888a9fc6c751966e5e779995da8696b61152878bfa7f2cd886a32b0bcf  repo-setup.sh
$ cat repo-setup.sh

このスクリプトは端的に言うと、次のリポジトリのリポジトリ鍵をapt-keyコマンドで追加して、リポジトリをadd-apt-repositoryするというものです[9]⁠。つまりこのスクリプト自体は単にリポジトリを追加するだけです。

$ sudo bash repo-setup.sh

これにより「mattermost-omnibus」パッケージをインストールできるようになります。試しにパッケージの情報を確認してみましょう。

$ apt policy mattermost-omnibus
mattermost-omnibus:
  Installed: (none)
  Candidate: 6.2.1-0
  Version table:
     6.2.1-0 500
        500 https://deb.packages.mattermost.com focal/main amd64 Packages
     6.1.0-0 500
        500 https://deb.packages.mattermost.com focal/main amd64 Packages
(以下略)

$ apt show mattermost-omnibus
Package: mattermost-omnibus
Version: 6.2.1-0
Priority: optional
Section: base
Maintainer: Mattermost Team <[email protected]>
Installed-Size: unknown
Depends: python3, python3-psycopg2, ansible, postgresql-13 (>= 13.1-1.pgdg20.04+1), nginx (>= 1.18.0-1~focal), certbot (>= 0.40.0-1), python3-certbot-nginx (>= 0.40.0-0ubuntu0.1), debconf, mattermost (= 6.2.1-0)
Download-Size: 5852 kB
APT-Sources: https://deb.packages.mattermost.com focal/main amd64 Packages
Description: Mattermost Omnibus Package
 Metapackage to install Mattermost server and its dependencies

N: There are 57 additional records. Please use the '-a' switch to see them.

あとはmattermost-omnibusパッケージをインストールするだけなのですが、ここで注意が必要です。Mattermost Omnibusはインストールしたらドメイン名とメールアドレスを要求し、その情報を元にCertbotでサーバー証明書を取得しようと試みます。インストールしようとしているサーバーが指定したドメインで到達可能なら問題ないのですが、テスト環境であればそうでない可能性は高いでしょう。そこで環境変数MMO_HTTPS=falseを指定してサーバー証明書の取得を抑制します。

少し長くなりますが、インストールしたときのログは次のとおりです。

$ sudo MMO_HTTPS=false apt install mattermost-omnibus
(中略)
0 upgraded, 53 newly installed, 0 to remove and 0 not upgraded.
Need to get 310 MB of archives.
After this operation, 229 MB of additional disk space will be used.
Do you want to continue? [Y/n]
(中略)
Setting up mattermost-omnibus (6.2.1-0) ...
config file "/etc/mattermost/mmomni.yml" successfully saved
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Update debconf variables with json file values] **************************
ok: [localhost] => (item={'key': 'mattermost-omnibus/domain', 'value': 'mm.example.org'})
ok: [localhost] => (item={'key': 'mattermost-omnibus/email', 'value': ''})

TASK [Ensure that NGINX is running] ********************************************
skipping: [localhost]

TASK [Check if certificate already exists] *************************************
skipping: [localhost]

TASK [Generate SSL Certificate] ************************************************
skipping: [localhost]

TASK [Renew SSL certificate] ***************************************************
skipping: [localhost]

TASK [Configure NGINX https template] ******************************************
changed: [localhost]

TASK [Delete default NGINX configuration file] *********************************
changed: [localhost]

TASK [Restart NGINX service with the new configuration] ************************
changed: [localhost]

TASK [Create database user] ****************************************************
 [WARNING]: Module did not set no_log for no_password_changes
changed: [localhost]

TASK [Create database for Mattermost] ******************************************
changed: [localhost]

TASK [Create system user] ******************************************************
changed: [localhost]

TASK [Ensure file permissions] *************************************************
changed: [localhost] => (item=/opt/mattermost)
changed: [localhost] => (item=/var/opt/mattermost/data)
changed: [localhost] => (item=/var/log/mattermost)

TASK [Generate mattermost env variables] ***************************************
changed: [localhost]

TASK [Generate systemd service] ************************************************
changed: [localhost]

TASK [Enable and restart Mattermost service] ***********************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=12   changed=10   unreachable=0    failed=0    skipped=4    rescued=0    ignored=0



 ___ ___   ____  ______  ______    ___  ____   ___ ___   ___   _____ ______
|   |   | /    ||      ||      |  /  _]|    \ |   |   | /   \ / ___/|      |
| _   _ ||  o  ||      ||      | /  [_ |  D  )| _   _ ||     (   \_ |      |
|  \_/  ||     ||_|  |_||_|  |_||    _]|    / |  \_/  ||  O  |\__  ||_|  |_|
|   |   ||  _  |  |  |    |  |  |   [_ |    \ |   |   ||     |/  \ |  |  |
|   |   ||  |  |  |  |    |  |  |     ||  .  \|   |   ||     |\    |  |  |
|___|___||__|__|  |__|    |__|  |_____||__|\_||___|___| \___/  \___|  |__|


  Installation successful! Join the Mattermost community for questions
  and help: https://mattermost.com/pl/default-ask-mattermost-community/

わかる人にはわかるかと思いますが、Ansibleでセットアップを行っているようです。mattermost-omnibusパッケージはインストール時にインストールされる/var/lib/dpkg/info/mattermost-omnibus.postinstの中で、ドメイン名とメールアドレスを問い合わせます。これはMMO_HTTPS=falseを指定しても同じです。

図1 ドメイン名の確認
図1

ドメイン名は最終的にブラウザーからアクセスする際の名前を入れておいたほうが無難です。これは最終的にMattermostのServiceSettings.SiteURLとして使われます。次に聞かれるメールアドレスはサーバー証明書を取得しないなら空でもかまいません。

その後、mmomniコマンドを使って設定するのですが、その中のmmonmi reconfigureでAnsibleを呼び出しています。Ansibleのプレイブックは/opt/mattermost/mmomni/ansible/に保存されています。

ちなみに、環境変数MMO_SKIP_INITIAL_CONF=yesを設定すると/var/lib/dpkg/info/mattermost-omnibus.postinstの処理がまるっとスキップされるようです。この場合は、手作業で初期化セットアップを行う必要があります。

mmomniコマンドは、Mattermost Omnibus専用のメンテナンスツールです。たとえば各サービスが動いているかどうかは次のコマンドで確認できます。

$ sudo mmomni status
[11493] nginx: running
[9646] postgresql@13-main: running
[11843] mattermost: running

設定ファイルの詳細は次回以降解説しますが、簡単な関係性は次のとおりであると覚えておけばいいでしょう。

  • Mattermost Omnibusの設定ファイルは/etc/mattermost/mmomni.yamlで、変更後の反映コマンドはsudo mmomni reconfigure⁠。
  • Mattermost本体の設定は、sudo mmctl --local config editで編集すると反映される。

Mattermost Omnibusをインストールした環境のListenしているTCPのポートを見ると次のようになっています。

$ sudo ss -ltnp
State      Recv-Q     Send-Q         Local Address:Port         Peer Address:Port    Process
LISTEN     0          128                  0.0.0.0:80                0.0.0.0:*        users:(("nginx",pid=11495,fd=6),("nginx",pid=11494,fd=6),("nginx",pid=11493,fd=6))
LISTEN     0          128            127.0.0.53%lo:53                0.0.0.0:*        users:(("systemd-resolve",pid=2057,fd=13))
LISTEN     0          128                  0.0.0.0:22                0.0.0.0:*        users:(("sshd",pid=243,fd=3))
LISTEN     0          128                127.0.0.1:5432              0.0.0.0:*        users:(("postgres",pid=9646,fd=5))
LISTEN     0          128                     [::]:80                   [::]:*        users:(("nginx",pid=11495,fd=7),("nginx",pid=11494,fd=7),("nginx",pid=11493,fd=7))
LISTEN     0          128                     [::]:22                   [::]:*        users:(("sshd",pid=243,fd=4))
LISTEN     0          128                        *:8065                    *:*        users:(("mattermost",pid=11843,fd=24))

80番ポートがNginx、8065番ポートがMattermost本体です。この状態でhttp://指定したドメイン/もしくはhttp://localhost/⁠、LXD上にインストールしているのならhttp://インスタンスのIPアドレス/でアクセスできます。

Nginxの設定について

ただし、このままだとTLSに未対応になってしまいます。ここで対応する方法は次の2種類です。

  • Mattermost OmnibusでインストールしたNginxを正しく設定する
  • 別のリバースプロキシを利用する

前者はたとえばすでに取得済みの証明書を利用して、つまりCertbotを利用せずにTLS設定を行いたい場合に便利です。

まずドメイン名のFQDNは/etc/mattermost/mmomni.ymlに記載します。次にNginxの設定のテンプレートは/opt/mattermost/mmomni/ansible/playbooks/mattermost.confにあるため、それを適切に編集します。これはAnsibleでデプロイされるという点に注意してください。最後にsudo mmomni reconfigureを反映して終了です。

後者のリバースプロキシは、たとえばLXDでデプロイする際にホストのNginxが各コンテナのリバースプロキシとして動いていて、そこでクライアントとのTLS処理を担っている場合に行います。この方法の場合、リバースプロキシから直接8065番ポートのMattermostに接続してもかまいません。ただしその場合、Mattermost OmnibusのNginxはういてしまいます。

Mattermost向けのリバースプロキシーの設定は、OmnibusのAnsibleが生成した/etc/nginx/conf.d/mattermost.confを流用するか、Mattermostドキュメントのそれを参考にすると良いでしょう。ドキュメント側はBoardsの設定が入っていないようなので、両方をマージするのも良いかもしれません。

Mattermostの初回セットアップ

Mattermostはウェブブラウザーでアクセスした際の、初回ログイン時に管理者アカウントの設定を行います。つまり外部からログインできるようになったら、なるべくはやめにアクセスする必要があります。

図2 初回ログイン時にメールアドレス、ユーザー名、パスワードを入力してログインする。パスワードは記号を入れなくてはいけない点に注意する
図2
図3 初回ログイン時はチームの作成を促される。いわゆるSlackで言うところのワークスペース。⁠System Console」で全体の設定画面にも移行できる
図3
図4 チーム名の入力。日本語も可能
図4
図5 チームURLの入力。こちらは実際のURLとして使われる点に注意する
図5
図6 ログインが完了するとその他の初期設定を促される。最初のフルネーム以外はスキップでも良い
図6

インストール直後は英語UIですが、日本語UIにも変更可能です。かなり品質の良い翻訳になっているため、日本語UIで十分生活できます。UIなどを含む個人設定は画面右上の「歯車アイコン」から設定を行います。

図7 設定の「Display」から「Language」を日本語に変更すると日本語UIになる
図7
図8 無事にセットアップが完了した
図8

これで必要最低限の設定は完了しました。必要最低限なのでまだ動かないものがいくつかあります。たとえばメール通知に必要なメールサーバーの設定等がその最たるものです。というわけで次回からは、Mattermostの個別の設定をいくつか紹介しましょう。

おすすめ記事

記事・ニュース一覧