ど素人がリバースプロキシ越しでGitLab Mattermostを使えるようにするまで

# 動機
仲間内でプライベートにgit開発する必要が発生。意を決してGitLabを入れる。説明書も充実、ど素人でも意外と簡単!
GitLabをいじっていると発見、チャット? Mattermost? 面白そう!
(2行ともフラグ)

なお、以下はたまたまうまく行ったという体験記であり、最適な/あるべき設定とは異なる可能性がありますので、ご了承下さい。

# 検索で来られた方向け、エラー別対処法
- `The requested scope is invalid, unknown, or malformed.`
    - -> `gitlab_scope`を空にせず、`read_user`を入れておく
- `SSO through OAuth 2.0 not available on this server.`
    - -> `gitlab_scope`に`openid`を書かない
- GitLabのAdmin->ApplicationsでNew applicationする時にScopesをチェックしないと、保存できない
    - -> `read_user`と`openid`をチェックしておく。`read_user`だけでも大丈夫かも。
- `oauth Bad response from token request.`
    - -> リバースプロキシで、HTTPヘッダの`X-Forwarded-Proto`に`https`をセットする
- MattermostのWebSocketが切れて`Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.`
    - -> リバースプロキシで、WebSocketが通るようにする 

# 前提
- 構築済みリバースプロキシ
    - relayd (OpenBSD7.1)
        - TLSを終端
- 構築済みGitLab
    - Omnibus GitLab Community Edition 15.2.2
    - Ubuntu Server 20.04

# Mattermost
## Mattermostのインストール
- GitLabと同じホストがいいか、別なホストがいいか
- インストールすると証明書取得などが走るようだが、リバースプロキシ越しにするにはどうすればよいのだろう

などを考えつつ、とりあえず入れてみるか、と思い、[Mattermostの本家インストールマニュアル](https://docs.mattermost.com/guides/deployment.html)を見て、おもむろに
```shell-session
sudo apt install mattermost-omnibus -y
```
したら、Nginxが競合するためか、失敗。
そこから調べはじめて…えっGitLabに入っているの? (事前調査不足)
[GitLabによるMattermostの説明](https://docs.gitlab.com/ee/integration/mattermost/)を見ると、

> This document applies to GitLab 11.0 and later.
> You can run a GitLab Mattermost service on your GitLab server. Mattermost is not part of the single application that GitLab is. There is a good integration between with GitLab, and our Omnibus installer allows you to easily install it. But it is a separate application from a separate company.

なるほど、そうでしたか…。
ということで、GitLabと同じホストで、GitLab Mattermostを動かす方針にする。新たにインストールは不要。

## GitLab Mattermostの設定(その1)
### 基本設定
```ruby:/etc/gitlab/gitlab.rb
### GitLab Mattermost
###! These settings are void if Mattermost is installed on the same omnibus
###! install
# gitlab_rails['mattermost_host'] = "https://mattermost.example.com"

mattermost_external_url 'http://mattermost.example.com'
mattermost['enable'] = true
mattermost['service_address'] = "0.0.0.0"
```

`gitlab_rails['mattermost_host']`は、今回はコメントの通り、same omnibus installなので、とりあえずそのままにしておく。

`url`は、[GitLabのGitlab Mattermostマニュアル](https://docs.gitlab.com/ee/integration/mattermost/)によると、

> GitLab Mattermost expects to run on its own virtual host. In your DNS settings, you need two entries pointing to the same machine. For example, gitlab.example.com and mattermost.example.com.

とのことだが、実際には同じQFDNでも動作しているようだ。

`service_address`は、デフォルトが`127.0.0.1`となっており、これではリバースプロキシからアクセスできないのでは? と思ったが、`0.0.0.0`にすればNIC側でもlistenしてくれるとのこと。なるほど。

### リバースプロキシをMattermostで用意しない設定
```ruby:/etc/gitlab/gitlab.rb
mattermost_nginx['enable'] = false
```
設定ファイル上、デフォルトでは`false`になっているような書き振りだったが、明示的に書く必要があった。これで、構築済みリバースプロキシを利用できる。
なお、デフォルトで、ポートは8065、プロトコルはHTTPの模様。よって、リバースプロキシ側でTLSを終端という現状の構成で問題なさそう。ということが後で分かった。

### アプリケーション連携の設定
ようやく本題。
```ruby:/etc/gitlab/gitlab.rb
mattermost['gitlab_enable'] = true
mattermost['gitlab_id'] = "12345656"
mattermost['gitlab_secret'] = "123456789"
mattermost['gitlab_scope'] = ""
mattermost['gitlab_auth_endpoint'] = "http://gitlab.example.com/oauth/authorize"
mattermost['gitlab_token_endpoint'] = "http://gitlab.example.com/oauth/token"
mattermost['gitlab_user_api_endpoint'] = "http://gitlab.example.com/api/v4/user"
```
`endpoint`の`url`は、適切に合わせた後、
`id`と`secret`は、GitLabのAdmin->Applicationsで生成した値を取ってくる。
そのため、話を一旦GitLabのAdmin->Applicationsの設定に移す。

## GitLabの設定
Admin->Applicationsで、デフォルトで`GitLab Mattermost`という設定が入っていた。
…が、最初設定が理解できず、一旦DestroyしてNew applicationすることに。
すると、複数の項目を入力する必要があった。

### Callback URL
[Mattermostの設定マニュアル](https://docs.mattermost.com/onboard/sso-gitlab.html)によると、
```
https://{mattermost-site-name}/login/gitlab/complete
https://{mattermost-site-name}/signup/gitlab/complete
```
を書けばよい。{mattermost-site-name}は適切に置き換える。

### Trusted
Yesにすると、連携時の承認画面が飛ばされた。デフォルトのNoのままでも、連携はできたため、このままにする。

### Confidential
とりあえず、デフォルトのYesのままにした。

### Scopes
先ほどの[Mattermostの設定マニュアル](https://docs.mattermost.com/onboard/sso-gitlab.html)によると、

> For Mattermost Team Edition, select read_user and openid.

とあるが、先ほどの[GitLabのGitlab Mattermostマニュアル](https://docs.gitlab.com/ee/integration/mattermost/)によると、

> Note that you do not need to select any options under Scopes. Choose Save application.

とある。
どっちなんだ! と思いつつ、何か1つはチェックしないと保存できないため、`read_user`と`openid`をチェックした。

最後に、Save applicationを押し、追加された項目のName部分を押すと、`Application ID`と`Secret`が取得できるので、それぞれ`gitlab.rb`の`gitlab_id`と`gitlab_secret`部分にコピーする。

## GitLab Mattermostの設定(その2)
残るは`gitlab_scope`の設定。
先述の通り、`read_user`と`openid`を書けばよいかと思いきや、`openid`が入っていると、`Gitlab SSO through OAuth 2.0 not available on this server.`というエラーが発生する。
かといって、何も書かないと、`The requested scope is invalid, unknown, or malformed.`というエラーが発生する。
そこで、とりあえず`read_user`だけ書いてみた。

# リバースプロキシの設定
## HTTPヘッダの設定
これで万事うまくいくかと思いきや、`oauth Bad response from token request.`というエラーが発生。
[こちら](https://github.com/mattermost/mattermost-server/issues/19750)によると、リバースプロキシで`X-Forwarded-Proto`に`https`が設定されている必要がある模様。
relaydでは、ググって出てきた[こちら](https://matrix-org.github.io/synapse/latest/reverse_proxy.html)も見つつ、以下のように設定。
```conf:/etc/relayd.conf
match request header set "X-Forwarded-Proto" value "https"
```
## WebSocketの設定
ようやくGitLabのアカウントでMattermostに入れるようになったが、チャット画面でWebSocketが切れるエラーが発生。
relaydは、[本家マニュアル](https://man.openbsd.org/relayd.conf.5)によると

> Allow connection upgrade to websocket protocol. The default is no websockets.

できる素敵なオプションがあるため、以下のように設定。

```conf:/etc/relayd.conf
http websockets
```

# その他はまりどころ
- 環境によっては(?)/etc/hostsでGitLabのホスト名とMattermostのホスト名を書いてと[うまくいくとのこと](https://qiita.com/sunack/items/cc5d5ba24a15612399a8)
    - 結果的には今回の環境では不要だった
- デフォルトではGitLabアカウント連携でないとMattermostアカウントが作れないと[マニュアルにあった](https://docs.gitlab.com/ee/integration/mattermost/)気がするが、そうなっていなかったような…
    - > By default GitLab Mattermost requires all users to sign up with GitLab and disables the sign-up by email option. See Mattermost documentation on GitLab SSO.



# 感想
- 疲れたけど、実際やってみると、いろいろ勉強になったので、環境汚れる覚悟でやってみるのもいいですね
    - Docker化していなかったが、VMのスナップショットを使う手もあったのを忘れていた
- お手軽なrelaydが意外と色々対応できる
- 中国語の情報が多いのは、GitHubが使えないからか?
    - [こちら](https://ddeevv.com/question/mattermost-mattermost-server-17499.html)を参考にしました
    - リンク先で何かあっても何もできません(勘がはたらかず…)

# 今後
- まず話し相手を増やして使ってみないことには…
- MattermostはRTCで画面共有もできるんですか?
    - UDPの8443?
- websocketd調査