[Heroku] 無料で Mastodon を動かす(~v1.3.3未満) [マスト丼]

PTA会長業が多忙で、Heroku でちゃんと `Mastodon` 動かすのに時間がかかってしまいました。ただ動かすだけなら、`Heroku Button`でちょろっと設定するだけなんですが、完全な状態で動かすには一手間いります。

ただ、その一手間を入れても、ある程度は Herokuの無料範囲で使えるので、「試してみたい」という方はこちらをどうぞ。

# 前提条件

- Heroku アカウントを持っている
- (推奨)Heroku アカウントでクレジットカードを登録している
- Heroku CLI が導入済み
- Git が使える
- (強く推奨)Amazon S3 が使える
- (推奨)自由にメールを送信できるサーバ(smtp)がある

# Heroku へ本体を deploy

なにはともあれ、本体を deploy しましょう。

[Heroku Guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Heroku-guide.md) の `Heroku Button` をクリックします。該当ページのタイトルのすぐ下にあるので問題ないですね。このボタンです。

![Screen Shot 2017-04-23 at 11.30.46.png](https://qiita-image-store.s3.amazonaws.com/0/37263/99202ac7-c5b3-6057-254a-cb823ce426e3.png "Screen Shot 2017-04-23 at 11.30.46.png")

なにやら、色々と入力項目があるので、各々説明していきます。

## App Name を登録しよう

Heroku へアプリケーションを登録すると、`xxxx.herokuapp.com` というホスト名が割り当てられます。この `xxxx` を入力します。一意でなければならないのですが、入力してみると、OKかNGかすぐにわかりますので、適当に入力してみて、好きな名前を決めましょう。なお、何も入力しなければ、Heroku が勝手に割り当ててくれますが、今回は訳あって入力する必要がありますので、必ず何か入力してください。

![Screen Shot 2017-04-23 at 11.32.17.png](https://qiita-image-store.s3.amazonaws.com/0/37263/e5091bd7-d386-ab4a-db1b-4c9294a37843.png "Screen Shot 2017-04-23 at 11.32.17.png")

## Heroku に関する定義情報を入力しよう

次に、環境変数を入力する項目が並んでいます。そのうち、冗談から順番に入力していきましょう。まずは、Heroku の基礎情報の入力です。

![Screen Shot 2017-04-23 at 11.43.01.png](https://qiita-image-store.s3.amazonaws.com/0/37263/ac8ac9c7-22bf-7fa4-1d99-16f3b48a719c.png "Screen Shot 2017-04-23 at 11.43.01.png")


各項目については、次の通り入力してください。なお、入力項目の前に「`*`」がついているものは、必須項目になります。

|項目名| 設定内容・説明 |
|:--|:--|
|Heroku|Herokuを使う場合は、これが`true`でなければなりませんので、このまま|
|LOCAL_DOMAIN|Mastodonがアクセスすることになるホスト名です。先に入力した `App Name`.herokuapp.comになります。ここで入力する必要があるので、`App Name` は必ず入力しなければなりませんです|
|LOCAL_HTTPS|Herokuは標準でhttpsも使えますので、特に何もなければ `true`で良いです|
|SINGLE_USER_MODE|Mastodonを一人だけで使う場合には、ここを`true`にしておいてください|

他にもなにやら 3つほどありますが、「`autogenerated`」となっているとおり、自動的に割り振られますので、これらの項目は無視です。

## Amazon S3 の設定

次は Amazon S3 の設定です。アイコンや背景の画像ファイル、投稿した画像ファイルなどの保管場所になります。Heroku ではローカルのファイルシステムが利用できず、ファイルを永続化させられないので、S3 に頼る必要があります。入れなくても試す分にはなんとかなるとは思いますが、24時間以内にファイルがなくなって切ない思いをするので、個人用でもちょっと使ってみようという場合は S3を使いましょう。

![Screen Shot 2017-04-23 at 11.54.58.png](https://qiita-image-store.s3.amazonaws.com/0/37263/2ddb5629-27a8-f0bb-05cb-4124fec3e9e4.png "Screen Shot 2017-04-23 at 11.54.58.png")

|項目名| 設定内容・説明 |
|:--|:--|
| S3_ENABLED |S3を使わない場合には`false`に変更します。`true`の場合は以下の項目すべて必要です|
|S3_BUCKET|S3のバケット名を入力します。`s3://`やバケット下のフォルダ名など不要で、バケットの名前だけにします|
|S3_REGION|使用するS3リージョン名を指定します。Tokyoなら`ap-northeast-1`とかになりますね。ただ、`us-east-1`のときだけうまくいかないので、`S3_HOSTNAME`環境変数の設定が必要みたいです。俺だけ? [^1] |
|AWS_ACCESS_KEY_ID|AWSへアクセスするためのアクセスキーを指定します|
|AWS_SECRET_ACCESS_KEY|同様にシークレットキーを指定します|

[^1]: 私の使っている `us-east-1` の場合、URL が `s3.amazonaws.com` になって、リージョン名が入ってこないので、`S3_HOSTNAME` に `s3.amazonaws.com` を指定して難を逃れています。なんでだろ。

### S3を使う場合の注意事項

S3を利用する場合、`IAM Policy` または `Bucket Policy` に記述が必要です。前者は元ネタのサイトに書いてあるとおりですが、私は試したことないです。いずれも、サンプルを残しておきますので、ご参考に。いずれも `mstdn` というバケットの場合ですので、皆様の環境にあわせて変更ください。

```IAM_Policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Resource": [
                "arn:aws:s3:::*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::mstdn",
                "arn:aws:s3:::mstdn/*"
            ]
        }
    ]
}
```

```Bucket_Policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mstdn/*"
        }
    ]
}
```

## SMTPの設定

最後に、送信メールサーバの設定です。メールによるユーザ登録を利用する場合は必ず必要ですが、なくても自分で Validation可能なので、個人で使う分には必死になることはないです。私は、[Heroku Guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Heroku-guide.md)が勧めてくださった[mailgun](https://www.mailgun.com/)を素直に使うほどの、純粋に生きています。

![Screen Shot 2017-04-23 at 11.50.21.png](https://qiita-image-store.s3.amazonaws.com/0/37263/7d46fe82-686c-1cb1-153d-b41807606823.png "Screen Shot 2017-04-23 at 11.50.21.png")

|項目名| 設定内容・説明 |
|:--|:--|
| SMTP_SERVER |SMTPメールサーバのホスト名またはIPアドレスを入力します|
| SMTP_PORT |SMTPメールサーバのポート番号|
| SMTP_LOGIN |SMTP認証が必要な場合のユーザ名|
| SMTP_PASSWORD |同じく、その時のパスワード|
| SMTP_DOMAIN |メールドメインの指定が必要であれば、指定します|
| SMTP_FROM_ADDRESS |mastodonから送信されるメールのFROMを指定します|
| SMTP_AUTH_METHOD |SMTPの認証方式を指定します。デフォルトだと`plain`ですが、指定したほうが安心です|
| SMTP_OPENSSL_VERIFY_MODE |SMTP認証時のSSL/TLSの定義。たいてい放置で良さげ|
| SMTP_ENABLE_STARTTLS_AUTO |SSL/TLS認証を行う場合は`true`です。こちらも標準で`true`|

これら環境変数は、Deployした後からでも追加・変更できますので、Herokuの必要最小限だけでも設定したら、進んでしまうのも一つの手です。ただ、まとめて入力できるのはここしかないので、入れられるならなるべく入れてしまったほうがあとが楽です。

詳細は、`actionmailer` 機能で調べてみてください。私もよく知らん。

## Deploy しよう!!

ここまでまちがいなく入力できたら、一番下の `Deploy`ボタンをクリックしましょう。Heroku へ deployが始まります。

![Screen Shot 2017-04-23 at 11.57.48.png](https://qiita-image-store.s3.amazonaws.com/0/37263/408ef1fc-e596-27ac-53b1-8e2e5b426dd7.png "Screen Shot 2017-04-23 at 11.57.48.png")

5分以上はかかると思います。お茶でもしばいて待っていただくか、仮眠でも取っておいてください。まだ半分と終わっていません。

次の通り、`Deploy to Heroku` の文字が緑色になれば、正常に Deployされましたヽ(´ー｀)ノやったね

![Screen Shot 2017-04-23 at 12.03.53.png](https://qiita-image-store.s3.amazonaws.com/0/37263/ea93d0fa-95f8-084a-3f43-fc9f415bcd9b.png "Screen Shot 2017-04-23 at 12.03.53.png")

中身が気になる方は、「 _Show build log_ 」をクリックすると、デプロイのログが見られますので、そちらもどうぞ。ここで、`View`ボタンをクリックすると、下のよくみる Mastodon画面が出てきますので、ここまで来たらひとまず成功です。この状態で、一応使えます。

## 本体Deployまでで

一応動いている風ですが、実は非同期通信系が完全に動いていないので、他のインスタンスとの連携やメール送信はできませんが、ユーザ登録やローカルでのメッセージ送受信はできます。

そこで、バックエンドの Workerも動かしてあげます。先程の画面で「 _Manage App_ 」というボタンがありますので、そちらをクリックしてみましょう。画面が切り替わったら「 **Resouces** 」タブに移動します。

![Screen Shot 2017-04-23 at 12.21.36.png](https://qiita-image-store.s3.amazonaws.com/0/37263/defb1804-9d78-1274-d13b-7be87daded8c.png "Screen Shot 2017-04-23 at 12.21.36.png")

なんとなく、「 _Worker_ 」というやつが動いていない気がします。はい、実際動いてないです。なので、右側の鉛筆みたいなのをクリックしてください。`$0.00` の左横のスライドスイッチが動かせそうなので、青くなるように動かしましょう。これで起動するように支持することになります。うまく動いたら `Confirm` ボタンをクリックすると、_Worker_ くんが起動します。これで、メールの送信と他インスタンスとの連携が可能になります。

![Screen Shot 2017-04-23 at 12.23.16.png](https://qiita-image-store.s3.amazonaws.com/0/37263/c3d791b1-a65b-49e7-4dff-c6ec47ad41a8.png "Screen Shot 2017-04-23 at 12.23.16.png")


ここまでで、`Mastodon`の本体がDeployできて、必要な機能はほぼ利用可能な状態になっています。ただ、残念ながら、この状態だと `Streaming API`が利用できないので、`Mastodon` 画面をボーッと眺めていても、リアルタイムに更新していってくれません。残念です。「俺は漢だ、更新は自分でやるぜ」という方はここで完成です。おめでとうございます。

俺は、Streaming も使いたい...っ!! という方は、このあともご覧ください。

# Heroku で Streaming API を使う

ここまではGUIだけで済んでいたのですが、ここからは唐突にCUIばっかりになります。ひとまず Heroku CLIが使える状態であることを前提に進めます。

## Streaming 用の Heroku App を準備する

適当な空フォルダへ行って、次の通りコマンドを打っていきます。このあと、コマンドの結果などでは、実際のコマンドの結果がそのまま入っている部分があります。これらは、臨場感を出すためにそのままにしているだけで、ここで定義したアプリケーションはすでに削除済みで利用はできませんので、「よーしパパハッキングしちゃうぞー」はできませんので、予めご承知おきください。

### Heroku App の作成と環境変数の割当

```bash:ソースコードの入手
$ git clone https://github.com/tootsuite/mastodon.git
Cloning into 'mastodon'...
remote: Counting objects: 28567, done.
remote: Compressing objects: 100% (67/67), done.
remote: Total 28567 (delta 23), reused 1 (delta 1), pack-reused 28499
Receiving objects: 100% (28567/28567), 35.03 MiB | 78.00 KiB/s, done.
Resolving deltas: 100% (17381/17381), done.
```

以後、新しく作成された `mastodon` ディレクトリ配下で作業を実施

```bash:Herokuアプリ作成
$ heroku create
Creating app... done, ⬢ gentle-island-20654
https://gentle-island-20654.herokuapp.com/ | https://git.heroku.com/gentle-island-20654.git
```

`heroku create` で、特にApp名を指定せずに作成すると、このように勝手にアプリ名が割り当てられます。以後、この`gentle-island-20654` を使って、作業を実施したとします。なお <deploy済本体のApp名> は、先程 Deployしたアプリケーションの名前を入れます。作業内容としては、デプロイ済みの `Heroku Postgres` と `Heroku Redis`のこれらデータベースの接続設定を、新しい Streaming API用のサーバにも割り当てているだけです。

```bash:DB環境変数の定義
$ heroku config:set `heroku config:get DATABASE_URL --app <deploy済本体のApp名> | awk -F'[@:/]' '{ printf "DB_USER=%s\nDB_PASS=%s\nDB_HOST=%s\nDB_PORT=%s\nDB_NAME=%s\n",$4,$5,$6,$7,$8 }'` --app gentle-island-20654
Setting DB_USER, DB_PASS, DB_HOST, DB_PORT, DB_NAME and restarting ⬢ gentle-island-20654... done, v3
DB_HOST: ec2-23-23-111-171.compute-1.amazonaws.com
DB_NAME: d3da5gkauvkrtc
DB_PASS: 9dbad98dce67d765f1852e9e262ba02980de6280114ebae88c04b710a3486a34
DB_PORT: 5432
DB_USER: arudjmvubxsuiw
```

```bash:Redis環境変数の定義
$ heroku config:set `heroku config:get REDIS_URL --app <deploy済本体のApp名> | awk -F'[@:/]' '{ printf "REDIS_PASSWORD=%s\nREDIS_HOST=%s\nREDIS_PORT=%s\n",$5,$6,$7}'` --app gentle-island-20654
Setting REDIS_PASSWORD, REDIS_HOST, REDIS_PORT and restarting ⬢ gentle-island-20654... done, v4
REDIS_HOST:     ec2-34-204-242-91.compute-1.amazonaws.com
REDIS_PASSWORD: p1348825873d3bea268d1f1c7665d40b63e3d0ca4bfb7301c314dd3ac44e1891b
REDIS_PORT:     22739
```

```bash:Node.js本番指定
$ heroku config:set NODE_ENV=production --app gentle-island-20654
Setting NODE_ENV and restarting ⬢ gentle-island-20654... done, v5
NODE_ENV: production
```

Streaming App側では `Node.js`のみを利用します。`Node.js`を使いますよという宣言も行います。

```bash:buildpackの指定
$ heroku buildpacks:set heroku/nodejs
Buildpack set. Next release on gentle-island-20654 will use heroku/nodejs.
Run git push heroku master to create a new release using this buildpack.
```

### 起動方法の指定

`mastodon` ディレクトリのルートに、`Procfile` というファイルがありますので、次のように書き換えます。

```Procfile
web: npm start
```

その後、変更を反映するために `git commit`します。

```bash:commit
$ git add -A && git commit -m 'Changed Streaming'
[master 527a13e6] Changed Streaming
 1 file changed, 1 insertion(+), 2 deletions(-)
```

### Streaming用アプリのデプロイ

`git`コマンドを使って、Heroku へデプロイします。`Node.js`側のみのデプロイなので、先程より時間はかからないはずです。

```bash:git
$ git push heroku master
Counting objects: 28321, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (10524/10524), done.
Writing objects: 100% (28321/28321), 34.99 MiB | 3.94 MiB/s, done.
Total 28321 (delta 17201), reused 28321 (delta 17201)
remote: Compressing source files... done.
remote: Building source:
remote:
---(snip)---
remote:        https://gentle-island-20654.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/gentle-island-20654.git
 * [new branch]        master -> master
```

## Streaming サーバアドレスの指定

最後の局面までやってきました。先にデプロイした本体側から、Streamingサーバへ接続するように、環境変数を設定します。

```bash:Streamingサーバの設定
$ heroku config:set STREAMING_API_BASE_URL=https://gentle-island-20654.herokuapp.com/ --app mstdn-prfm
Setting STREAMING_API_BASE_URL and restarting ⬢ mstdn-prfm... done, v20
STREAMING_API_BASE_URL: https://gentle-island-20654.herokuapp.com/
```

あとに作ったアプリサーバのURLが必要です。`https://〜` ですね。ドメイン名までです。ディレクトリの指定は不要です。

設定上はここまでで終わりです。一応、２つのアプリともども、一度再起動をしておくと安心かもしれません。本体側は起動にそこそこ時間がかかるため、再起動指示のあと、すぐにアクセスに行っても飯能がないか、帰ってきてもエラーが発生するかだったりします。慌てずに。

# 最後に

無料だとできることが限定されていますので、一応補足しておきますね。近い将来「有料で作る〜」も書きますので、そちらもご参考に。

- クレカ未登録ユーザは、550時間/月 Dyno (Heroku App)を稼働できます
- クレカ登録ユーザは、1,000時間/月 Dyno (Heroku App)を稼働できます
	- 1ヶ月30日の場合 1Dynoをフル稼働すると 720時間消費します。したがって、今回のように 2Dynoをずっと稼働させたまま1ヶ月使い続けることはできません (1,440時間が必要。しかし、無料枠では1,000時間まで)
- Heroku Postgres は 10,000行までです。

他にもいくらかありますが、Mastodon に限って引っかかりやすいのは上記と考えられます。

[Build apps for free on Heroku](https://www.heroku.com/free)