AWSでmastodonサーバを立てる


とってもとっても出遅れたmastodon祭り（まだやってる？）
よくあるmastodon立ててみた記事に触発されてやってみた。

ハマりどころが結構あり、できた！と思ったらwebsocketがエラーになってて
通知がこないとか色々大変だった。


だいたい以下の構成でやってみた。

* EC2はなるべく安くなるように。CentOS7で。
* EC2にdockerとdocker-composeでmastodonを入れる
* データベースは外出ししないでdocker内のイメージのまま
* ELBでSSLする（証明書はAWS無料のやつを使う）
* nginxでproxyする
* mastodon用のメールサーバはgmailを利用する
* 画像ファイルとかの保存先はS3


## EC2

* microインスタンス
* ストレージは最低でも8Gくらいはあったほうがいい。
* CentOS7
* とりあえずセキュリティグループでport 80 と 22を空けておく

> 最初Amazon Linuxでやっていたがmastodonがdockerの結構新しいverを求め、
> Amazon Linux用のDocker パッケージリポジトリが古くて
> 更新したかったけど見つからなくて泣く泣くCentOSに切り替えた

## OS setup


yum更新

```
sudo yum update
```

rootのパスワード設定

```
sudo passwd root
```

SELinuxをoff

> 毎度のことながらnginxを起動してpermission errorになって
> やっとSELinuxのことを思い出す

```
sudo setenforce 0
sudo vi /etc/selinux/config
```

```
#SELINUX=enforcing
SELINUX=disabled
```

swapを増やす
```docker build``` あたりでメモリが不足するので。

```
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

```


## WEBサーバの準備

### install nginx

```
sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
sudo yum -y update nginx-release-centos
sudo yum -y --enablerepo=nginx install nginx
sudo chkconfig nginx on
sudo service nginx start
```

ブラウザから ```http://[EC2インスタンスのIP]``` で接続してnginxのページが見えることを確認

### ELB作成

適当にELBを作成する。

この時点ではHTTPのみでOK

作成したELBのDNS名からnginxのページが見えることを確認

## お名前.comで取得したドメインからELBのDNSへの転送設定

今回はネームサーバはお名前.comをそのまま使う。
（ネームサーバをAWSのRoute53に移管することもできるが別手順）

ドメインNaviを開き、以下のようにCNAMEレコードを追加する

![Kobito.L73IZY.png](https://qiita-image-store.s3.amazonaws.com/0/60056/2f029981-9a9e-9451-46ae-fc84c1238d21.png "Kobito.L73IZY.png")

反映には少し時間がかかる

## AWSからSSLを取得してELBにセット

AWSコンソールからロードバランサーを開き、リスナーの編集

ロードバランサーのリスナーにSSL(セキュアTCP)を追加、SSL証明書リンクをクリック

> HTTPSでないことに注意。HTTPSだとwebsocketのwssプロトコルを通してくれない

![Kobito.waUvm5.png](https://qiita-image-store.s3.amazonaws.com/0/60056/9671a627-4b0e-e469-6799-fc244c90afe2.png "Kobito.waUvm5.png")



「AWS 証明書マネージャ (ACM) から、既存の証明書を選択する」を選択して、「ACMから新しい証明書をリクエスト」を選択

![Kobito.Imq8oO.png](https://qiita-image-store.s3.amazonaws.com/0/60056/1ee629c2-fa76-1883-7c5a-3f5304da710e.png "Kobito.Imq8oO.png")

![Kobito.eQ9U9Q.png](https://qiita-image-store.s3.amazonaws.com/0/60056/a9fcc164-34a0-026e-30ac-1fd1881b8558.png "Kobito.eQ9U9Q.png")


リクエストを送ると ```webmaster@[yourdomain]``` とかにメールが送られ、
そのメール本文に承認画面のURLが記載されているのでブラウザで開き、 ```I Approve```を選択する

証明書が発行されたらもう一度ロードバランサーの設定画面を開き、発行された修了書を選択する

![Kobito.WvsnZz.png](https://qiita-image-store.s3.amazonaws.com/0/60056/71b4ab45-51bd-4d13-0868-36e7bb1f3716.png "Kobito.WvsnZz.png")

設定ができたらブラウザから ```https://[your domain]``` で接続してnginxのトップページにアクセスできることを確認


## mastodon設定

### 初期設定

```
sudo yum install git yum-utils device-mapper-persistent-data lvm2

```


### dockerインストール

mastodonをdocker使って入れるので。

```bash
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
    
sudo yum makecache fast
sudo yum install docker-ce
sudo systemctl start docker
sudo systemctl enable docker.service
```

### docker-composeインストール

```bash
su -
curl -L "https://github.com/docker/compose/releases/download/1.13.0/docker-compose-$(uname -s)-$(uname -m)" > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
exit
```

あとdockerグループを作って権限を割り当ててやる必要があるとのこと
[参考](http://qiita.com/DQNEO/items/da5df074c48b012152ee)

```
sudo groupadd docker
sudo gpasswd -a $USER docker
sudo service docker restart
```

### mastodonで使うgmailアカウントの用意

普通にgmailアカウントを作成

gmailにログインして「アカウント」を開き「Googleへのログイン」を選択

「２段階認証プロセス」を開始

「アカウント」に戻り「アプリパスワード」を選択

適当な名前をつけてアプリパスワードを発行、メモしておく


### mastodonの設定

#### mastodonソースコードのダウンロード

```bash
git clone https://github.com/tootsuite/mastodon.git
cd mastodon
```

#### volumeの開放

これをやっておけばmastodon上のpostgresデータとredisデータを永続化できる。
というかやっとかないとdocker落とすとデータはすべて消える。

```bash
vi docker-compose.yml
```

```
version: '2'
services:

  db:
    restart: always
    image: postgres:alpine
### Uncomment to enable DB persistance
    volumes:
      - ./postgres:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:alpine
### Uncomment to enable REDIS persistance
    volumes:
      - ./redis:/data
```

#### build

```bash
docker-compose build
```


#### シークレットキーの作成

３回投げて３つのキーをメモる。
（面倒なので１回しか取らなかったけどそれでももちろん動く）

```bash
docker-compose run --rm web rake secret
```

#### mastodon設定ファイルの編集

```bash
cp .env.production.sample .env.production
vi .env.production
```

```LOCAL_HTTPS``` はELBで証明書を管理するけど ```true``` のままでOK

> このあたり色々試したのだけれど、結局ELBで証明書を管理して内部はhttpで来る場合でも
> LOCAL_HTTPS をTrueにしておかないと内部URLがすべてhttpで返却されてしまってたので
> やはりTrueの模様。（動くかどうか不安だったけどこの設定でちゃんと動いてます）


```
LOCAL_DOMAIN=[ドメイン名]
LOCAL_HTTPS=true

PAPERCLIP_SECRET=さっき作ったシークレットキー
SECRET_KEY_BASE=さっき作ったシークレットキー
OTP_SECRET=さっき作ったシークレットキー

EMAIL_DOMAIN_WHITELIST=[example.comのようにサインアップできるEメールドメインを制限]

DEFAULT_LOCALE=ja

SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_LOGIN=ユーザーID@gmail.com
SMTP_PASSWORD=[さっきつくったアプリパスワード]
SMTP_OPENSSL_VERIFY_MODE=none
SMTP_DOMAIN=gmail.com

```

ここのgmailのSMTP関連の設定で、mastodonのサンプルをコピーした状態だと

```
#SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail
```

みたいに書いてあってよし！有効にしようとか思って

```
SMTP_DELIVERY_METHOD=smtp # delivery method can also be sendmail
```

って書いたらメールが送れなくてAction Mailerのログまで追うことになるので注意。
正しくは

```
SMTP_DELIVERY_METHOD=smtp
```

のように後ろのコメント文字までちゃんと取ってね！
（もともとの書き方がよぅ・・・）


#### DBとassetの初期設定

```
docker-compose run --rm web rake db:migrate
docker-compose run --rm web rake assets:precompile
```

#### mastodon起動

```
docker-compose up -d
```


## その他の設定

### nginxでmastodonのport3000にproxy

nginxのvirtualhostフォルダを作成

```
sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabled
```

mastodon用のnginx confを作る
ELBでSSL証明書を持つのでここではport80だけを定義


```
sudo vi /etc/nginx/sites-available/mastodon
```

```
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name mastodon.example.com;


  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  root /home/centos/mastodon/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  location / {
    try_files $uri @proxy;
  }
  
  location ~ ^/(assets|system/media_attachments/files|system/accounts/avatars) {
    add_header Cache-Control "public, max-age=31536000, immutable";
    try_files $uri @proxy;
  }

  location @proxy {
    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 https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://localhost:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    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 https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;


}

```


シンボリックリンクでsites-available -> sites-enabled

```
cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/mastodon mastodon
```


sites-enabledディレクトリをnginxに認識させる

```
sudo vi /etc/nginx/nginx.conf
```

```
include /etc/nginx/sites-enabled/*;
```



nginxの設定をするとELBのhealthチェックが失敗する(index.htmlでアクセスできないので)
AWSコンソールからELBを開き、healthチェックを以下のように編集する

![Kobito.lodemu.png](https://qiita-image-store.s3.amazonaws.com/0/60056/b100c4ee-c2ac-b272-78f1-7952df0ab206.png "Kobito.lodemu.png")


### 画像・動画・アイコン画像をS3に保存

S3のバケットを作成する

IAMを開きAmazonS3FullAccessのポリシーを持つユーザを作成し、
アクセスキーIDとシークレットアクセスキーをメモする

```
vi .env.production
```

```
S3_ENABLED=true
S3_BUCKET=...
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
S3_REGION=...
```

```
docker-compose stop
docker-compose start
```

## 管理者の作成

ユーザ作った後で

RAILS_ENV=production && \
    docker exec -it $(docker ps -q -f name=mastodon_web_1) bundle exec rails mastodon:make_admin USERNAME=[target username]