[WIP]mastodon インスタンスセットアップのあゆみ


## 事前情報
### 公式
- [tootsuite/mastodon: A GNU Social-compatible microblogging server](https://github.com/tootsuite/mastodon)
- [documentation/Resources-needed.md at master · tootsuite/documentation](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Resources-needed.md)

### 先達
- [さくらのVPSで自分の Mastodon サーバを最速でつくる方法 - Qiita](http://qiita.com/hekki/items/c3f42c31632105389c79)
- [さくらの VPS + CentOS7 で 俺専用 Mastodon インスタンスを立ててみた話 | WWW WATCH](https://hyper-text.org/archives/2017/04/mastodon-instance-single-user.shtml)
- [自分用マストドンのインスタンスをVPS上のUbuntu 16.04で立ててみた – しりわけ](https://otya.me/tech/service/masutodon-on-vps-ubuntu/)
 

## 環境情報
- [VPS（仮想専用サーバー）｜さくらインターネット - 無料お試し実施中](http://vps.sakura.ad.jp/)
- 2Gプラン（月額 972円）
- Ubuntu 16.04

## サーバの設定
### OSの入れかえ
`さくらのVPSコントロールパネル`からポチポチっと設定します。
ログインに使う、ubuntuユーザのパスワードを設定するので、忘れないようにしましょう。
忘れたら再インストールすればいいです。

ここから先はsshでサーバにログインして作業を進めます。
インストールが終わったら、とりあえず


```
sudo apt-get update
sudo apu-get upgrade -y
```

します。

### sshdの設定
#### 公開鍵を設定
公開鍵認証を使いましょう。デフォルトで有効です。
公開鍵を設定します。ホームディレクトリで

```
mkdir .ssh
vi .ssh/authorized_keys
```

好きな公開鍵を書き込みます。

#### パスワード認証を無効化
パスワード認証は無効にします。
`/etc/ssh/sshd_config`の

```
PasswordAuthentication yes
```

を`no`に変えます。

sshdを再起動して

```
sudo systemctl restart sshd
```

ログインしなおしてみてみます。
失敗したらOSを再インストールすればいいです。

#### 参考
[» sshd_configの設定項目の理解を目指す](http://unskilled.site/sshd_config%E3%81%AE%E8%A8%AD%E5%AE%9A%E9%A0%85%E7%9B%AE%E3%81%AE%E7%90%86%E8%A7%A3%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99/)

```
#AuthorizedKeysFile    %h/.ssh/authorized_keys
```
の%hは
[What does %h mean in SSHD configuration? - Ask Ubuntu](https://askubuntu.com/questions/605479/what-does-h-mean-in-sshd-configuration)

> %h is replaced by the home directory of the user being authenticated

だ、そうです。
このコメントアウトは外さなくても、authorized_keysファイルは認識されます。

systemctlでのサービス再起動方法をぐぐると`.service`がついた例とついていない例が出てくるのは

[CentOS7でサービスの管理方法が変わった！ - Qiita](http://qiita.com/haisaihiroki/items/c38cb3c0a331db9b6f69#comment-d1ba8fc9f6235173ea7f)

> systemctlのmanページのParameter Syntaxによるとパターンのサフィックスを省略すると .service が補われるので、systemctl restart sshd は systemctl restart sshd.service と同じとのことです

だそうです。

## SSL証明書の取得
### ファイアウォールの設定

Ubuntuのファイアーウォールは[ufw](https://help.ubuntu.com/community/UFW)コマンドで設定します。
さくらVPSのUbuntu 16.04にはコマンド自体はすでに入っています。どういうわけか`ufw`でファイアウォールの設定を変更することはできません。
iptablesを直接設定します。

#### iptablesでhttpsを有効にする
`/etc/iptables/iptables.rules`を編集して

```
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
```

の下に

```
-A INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT
```

を追加します。
変更の反映

```
sudo iptables-restore < /etc/iptables/iptables.rules
```

現在適用されているルールの確認

```
sudo iptables -L -n -v
```

#### もしもufwが使えたなら
ファイアウォールを有効にする前にssh接続を許可します。

```
sudo ufw allow 443
```

ファイアウォールを起動します。

```
sudo ufw enable
```

現在の設定はstatusで見れます。
ファイアウォール起動中しか見れません。

```
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
443                        ALLOW       Anywhere
443 (v6)                   ALLOW       Anywhere (v6)
```

##### 参考情報
- [ufwを使って簡単にファイアウォールを設定する - Qiita](http://qiita.com/yoh-nak/items/46935af3c5c4036e93b3) 一通りのコマンドの説明
- [ufwの基本操作 - Qiita](http://qiita.com/RyoMa_0923/items/681f86196997bea236f0)
親切な説明、設定しているルールは厳しめ
- [Ubuntu で ufw を利用して ping を拒否する設定 | 技術的生存報告記](http://www.sakito.com/2012/10/ubuntu-ufw-ping.html) 設定ファイルの話が参考になる
- [ufw@Ubuntu でRuleを削除する | ryuzi.wordpress.com](https://ryuzi.wordpress.com/2012/05/28/ufwubuntu-%E3%81%A7rule%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B/) 間違えて設定したルールを消す方法

### Let's Encrypt から SSL 証明書を取得

#### DNSを設定
事前にドメイン名を取得してDNS設定が必要です。
さくらVPSでは`tk2-238-28564.vs.sakura.ne.jp`のようなドメイン名が割り振られます。

https://letsencrypt.org/docs/rate-limits/
> The main limit is Certificates per Registered Domain (20 per week). 

とあるようにLet's Encryptは、１つのドメインを週に20回しか登録できません。
試しに`tk2-238-28564.vs.sakura.ne.jp`でSSL証明書を取得しようとすると

```
There were too many requests of a given type :: Error creating new cert :: too many certificates already issued for: sakura.ne.jp
Please see the logfiles in /var/log/letsencrypt for more details.
```

と、エラーがでます。

#### gitインストール

```
sudo apt install git -y
```

#### SSL証明書を取得

```
cd
git clone https://github.com/certbot/certbot
cd certbot
```

```
sudo ./certbot-auto certonly --standalone -d mstdn.mangabon.fun
```

で証明書が作れます。
`-d`以下のドメイン名は好きなものに変えてください。
必要なパッケージがインストールされたりメールアドレスを登録したりMLの登録を受諾・拒否したりしたのち
成功すると次のメッセージが表示されます。

```
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for mstdn.mangabon.fun
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0002_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0002_csr-certbot.pem

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/mstdn.mangabon.fun/fullchain.pem. Your cert
   will expire on 2017-07-31. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot-auto again. To
   non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
```

## ミドルウェアの設定

- docker
- docker-compose


### docker
#### `add-apt-repository`を入れる

```
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common -y
```

#### リポジトリ情報を追加

```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt-get update
```

#### dockerをインストール

```
sudo apt-get install docker-ce -y
```

```
sudo docker run hello-world
```

が成功すれば、インストール成功です。

#### root権なしで動かす
```
sudo usermod -aG docker $USER
```

ログインしなおすと

```
docker run hello-world
```

が成功します。


### docker-compose

```
sudo sh -c 'curl -L https://github.com/docker/compose/releases/download/1.12.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose'
sudo chmod +x /usr/local/bin/docker-compose
```

### 参考
- [Ubuntu 14.04 で add-apt-repository が無いと言われた | Lonely Mobiler](http://loumo.jp/wp/archive/20150626000042/)
- [Get Docker for Ubuntu - Docker Documentation](https://docs.docker.com/engine/installation/linux/ubuntu/#install-using-the-repository)
- [Post-installation steps for Linux - Docker Documentation](https://docs.docker.com/engine/installation/linux/linux-postinstall/)
- [CentOS7で使われているsystemctlについて少しまとめた - Qiita](http://qiita.com/tukiyo3/items/092fc32318bd3d1a0846)


## mastodonの設定
### チェックアウト

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

[tootsuite/documentation: Full documentation repository for Mastodon](https://github.com/tootsuite/documentation#running-mastodon)に
> It is highly recommended to run a tagged release of Mastodon and not run off the current master branch.

とあるように、masterブランチは動かないことがあります。
最新のタグをチェックアウトします。

```
git checkout v1.3.2
```

### docker-composeで起動

とりあえず設定ファイルを用意します。

```
cp .env.production.sample .env.production
```

秘密鍵を生成するのにdockerで実行する必要があるので、とりあえず

```
docker-compose build
```

します。

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

を3回実行して秘密鍵を３つ作ります。

### 秘密鍵を設定

```
vi .env.production
```

- `PAPERCLIP_SECRET=`
- `SECRET_KEY_BASE=`
- `OTP_SECRET=`

に秘密鍵を設定します。

### 起動確認

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

```
curl localhost:3000
<html><body>You are being <a href="http://localhost:3000/about">redirected</a>.</body></html>
```

aboutページにリダイレクトされれば動いています。

## 公開設定

### nginxインストール
```
curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
sudo sh -c "echo 'deb http://nginx.org/packages/ubuntu/ xenial nginx' >> /etc/apt/sources.list"
sudo sh -c "echo 'deb-src http://nginx.org/packages/ubuntu/ xenial nginx' >> /etc/apt/sources.list"
sudo apt-get update
sudo apt-get install nginx
```

起動

```
sudo systemctl start nginx
sudo systemctl enable nginx
```

curlでそれらしいページが開ければ成功です。

```
curl http://localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```


- [Ubuntuに最新のnginxをインストールする - Qiita](http://qiita.com/hiroq/items/420424bc500d89fd1cc8)


### nginxの設定

#### dhparam.pemを作成

```
sudo openssl dhparam 2048 -out /etc/ssl/certs/dhparam.pem
```

参考: [mastodon(Docker） v1.2.2 -> v1.3.2 に伴うassets表示などの障害経験共有 - Qiita](http://qiita.com/motiakoron/items/5ef7662fd7b2e03838a6#dh%E9%8D%B5%E4%BA%A4%E6%8F%9B%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E9%85%8D%E7%BD%AE)

> 新たな設定文が追加されたことにより、/etc/ssl/certs/dhparam.pem階層にTLS暗号通信で利用するファイルを配置する必要があります。
openssl dhparam 2048 -out dhparam.pemで生成したファイルをその階層に配置しましょう。


#### 設定ファイル
Mastodon用の設定ファイルをつくります。

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

[公式サンプル](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Production-guide.md#nginx)をコピペします。
ドメインを置換します。

```
:%s/example.com/mstdn.mangabon.fun/
```

4行置換されます。

```
4 substitutions on 4 lines
```

nginxを再起動すれば

```
sudo systemctl start nginx
```

外部からhttpsで接続できます。

```
curl https://mstdn.mangabon.fun
<html><body>You are being <a href="https://mstdn.mangabon.fun/about">redirected</a>.</body></html>
```


参考: [vim置換 - Qiita](http://qiita.com/waoooon/items/8d982e49692c8145ca4b)

> :%s/"置換前"/"置換後"/


### メールサーバの設定


### S3の設定

### mastodonが再起動しなくなった場合
`docker-compose up web`してみると

```
web_1        | A server is already running. Check /mastodon/tmp/pids/server.pid.
web_1        | => Booting Puma
web_1        | => Rails 5.0.2 application starting in production on http://0.0.0.0:3000
web_1        | => Run `rails server -h` for more startup options
web_1        | Exiting
```

が出ています。
コンテナ内の`/mastodon/tmp/pids/server.pid.`を消します。
なんならコンテナを消します。

例えば

```
docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                              NAMES
6ce4da687806        gargron/mastodon    "bundle exec rails..."   3 minutes ago       Up 3 minutes        0.0.0.0:3000->3000/tcp, 4000/tcp   mastodon_web_1
b95c3b08edc5        gargron/mastodon    "npm run start"          37 minutes ago      Up 5 minutes        3000/tcp, 0.0.0.0:4000->4000/tcp   mastodon_streaming_1
f4dfe8425e34        gargron/mastodon    "bundle exec sidek..."   37 minutes ago      Up 5 minutes        3000/tcp, 4000/tcp                 mastodon_sidekiq_1
7e052149ed80        redis:alpine        "docker-entrypoint..."   44 minutes ago      Up 6 minutes        6379/tcp                           mastodon_redis_1
5f869520beaa        postgres:alpine     "docker-entrypoint..."   44 minutes ago      Up 6 minutes        5432/tcp                           mastodon_db_1
```

のとき

```
docker rm 6ce4da687806 -f
```

としてから

`docker-compose up -d`します。

参考: https://mstdn.jp/users/Remilia/updates/746939