MastodonサーバーをUbuntuとLXDとDockerを使って構築する

# MastodonサーバーをUbuntuとLXDとDockerを使って構築する

この記事は、今流行りの[Mastodon](https://github.com/tootsuite/mastodon)の自前サーバーを、以下の組み合わせで構築する手順です。

  - Ubuntu 16.04 LTS
  - LXD 2.0.x
  - Docker 1.12.6（Ubuntuリポジトリ版）
  - docker-compose 1.12.0
  - Let's encrypt
  - Gmail（SMTPサーバー）

docker-composeはLXDコンテナの上で実行します。LXDコンテナに閉じ込めておくと、なんらかの理由でインスタンスを別サーバーに移行したくなったとき、LXDコンテナ単位でデータベースなども含めて簡単にマイグレーションできるからです。

またLXDコンテナの中でDockerを使うために、LXDパッチの当たったUbuntuリポジトリのdocker.ioパッケージを使うことにします。Docker公式の独自パッケージだとおそらく動きません。


## LXDコンテナ環境の準備

Ubuntu 16.04 LTS上にLXDコンテナを使用するための環境を準備します。すでにLXDコンテナの使用環境が整っているのであれば、次の項目まで飛ばしましょう。

まずLXDをインストールします。サーバー版のUbuntu 16.04 LTSであれば、最初からインストールされているはずです。明示的にインストールする場合は、次のコマンドを実行してください。

```
$ sudo apt install lxd
```

インストールと同時にlxdグループが作成され、`sudo`を実行できるユーザーは自動的にlxdグループに所属します。グループの変更を反映するために、一度ログインしなおしましょう。lxdグループに所属すると、`sudo`なしに`lxc`コマンドを実行できるようになります。

次にLXDの初期設定を行います。LXDは「`sudo lxd init`」によって、全体的な初期設定を行えます。設定するのはストレージのバックエンド（コンテナのルートファイルシステムをどのように保存するのか）とコンテナのネットワーク設定です。というわけで、インストール直後に一回だけ実行します。

```
$ sudo lxd init
```

基本的に既定の設定をそのままOKしていくだけです。詳しいことは[Ubuntu Weekly Recipeの第459回の2ページ目](http://gihyo.jp/admin/serial/01/ubuntu-recipe/0459?page=2)を参照してください。


## LXD上にmastodonコンテナを作成する

LXD上にmastodonをインストールするためのコンテナを作成します。ポイントはDockerをLXD上で利用できるようにするために「`-p`」オプションで「dockerプロファイル」を指定することです。

```
$ lxc init ubuntu:16.04 mastodon -p default -p docker
```

ルートファイルシステムをダウンロードするため、完了するまでに若干時間がかかります。

このあとコンテナを起動してからログインし必要なDockerなどをインストールします。ただし、このあたりは定型的な作業ですのでcloud-initで自動化してしまいましょう。LXDはコンテナのプロパティにcloud-initのファイルを指定できるのです。またcloud-initのファイルは他のクラウドプラットフォームでもそのまま流用できるというメリットもあります。

最初に、次の作業を行うcloud-initファイルを「`mastodon.cfg`」という名前で作成します。

```cloud-init
#cloud-config

apt:
  primary:
    - arches: [default]
      uri: http://jp.archive.ubuntu.com/ubuntu

package_upgrade: true

packages:
  - language-pack-ja
  - docker.io
  - git

locale: ja_JP.UTF-8

timezone: Asia/Tokyo

runcmd:
  - [ dpkg, --add-architecture, i386 ]
  - [ curl, -L, "https://github.com/docker/compose/releases/download/1.12.0/docker-compose-Linux-x86_64", -o, /usr/local/bin/docker-compose ]
  - [ chmod, +x, /usr/local/bin/docker-compose ]
```

上記の設定ファイルをmastodonコンテナにセットした上で、コンテナを起動します。

```
$ lxc config set mastodon user.user-data - < mastodon.cfg
$ lxc start mastodon
```

次のコマンドで、Dockerやdocker-composeが期待通り動作していることを確認しておきましょう。

```
$ lxc exec mastodon docker info
$ lxc exec mastodon -- docker-compose --version
```

ついでに「ubuntu」ユーザーで、`docker`コマンドを実行できるようにしておきます。「ubuntu」はUbuntu 16.04 LTSコンテナの初期ユーザーです。
もちろん別のユーザーを作っても問題ありません。

```
$ lxc exec mastodon -- usermod -aG docker ubuntu
```

ちなみにmastodonコンテナの中にログインするためにはSSH鍵を登録する必要があります。cloud-initの`ssh_import_id`を使うという手もありますが、次のように直接`authorized_keys`を書いてもかまいません。

```
$ lxc file push ~/.ssh/id_rsa.pub mastodon/home/ubuntu/.ssh/authorized_keys
$ lxc exec mastodon chown ubuntu: /home/ubuntu/.ssh/authorized_keys
```

もしGitHubにすでに公開鍵を登録済みであれば，`ssh-import-id`を使ってGitHubからインストールする方法もあります。

```
$ lxc exec mastodon -- sudo -u ubuntu ssh-import-id -o /home/ubuntu/.ssh/authorized_keys gh:（GitHubのアカウント名）
```


あとは`lxc list`でIPアドレスなどを確認すれば、SSHログインできるはずです。

```
$ lxc list mastodon
+----------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
|   NAME   |  STATE  |              IPV4              |                     IPV6                      |    TYPE    | SNAPSHOTS |
+----------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
| mastodon | RUNNING | 172.17.0.1 (docker0)           | fd3b:f724:c6b0:f8f8:216:3eff:fea8:9a74 (eth0) | PERSISTENT | 0         |
|          |         | 10.241.13.168 (eth0)           |                                               |            |           |
+----------+---------+--------------------------------+-----------------------------------------------+------------+-----------+
```

本記事では「`mastodon$`」と記述している場合、上記で作ったコンテナの中で操作しているものとします。
原則としてコンテナの外から`lxc exec`を使って操作しても問題ありません。
もちろん将来的には自動化すると良いでしょう。


## Mastodonのインストール

ソースコードを取得し、docker-composeで環境を構築します。

```
mastodon$ cd ~ubuntu/ && mkdir mastodon && cd $_
mastodon$ wget https://github.com/tootsuite/mastodon/archive/v1.1.2.tar.gz
mastodon$ tar xvf v1.1.2.tar.gz
mastodon$ cd mastodon-1.1.2
```

## Mastodonの設定

ここから先は`README.md`にあわせて作業を行います。ただし[手順そのままだとダメ](https://github.com/tootsuite/mastodon/issues/1736)だったので、いくつか変更を加えています。

```
mastodon$ cp .env.production.sample .env.production
mastodon$ docker-compose build
```

しばらく経過したらビルドが完了します。次は秘密鍵を3つ生成しましょう。

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

出力された結果をもとに`.env.production`を編集します。

```
LOCAL_DOMAIN=mastodon.example.com
LOCAL_HTTPS=true

秘密鍵（web rake secretの最後の文字列をそれぞれ指定する）
PAPERCLIP_SECRET=
SECRET_KEY_BASE=
OTP_SECRET=

標準の言語
DEFAULT_LOCALE=ja

メール通知用
SMTP_SERVER=smtp.mailgun.org
SMTP_PORT=587
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=notifications@example.com
```

`SMTP_*`はいくつかの選択肢がありますが、一番簡単なのは[Gmailを使う方法](https://github.com/tootsuite/mastodon/issues/934)かもしれません。なおGmailで2段階認証を有効にしている場合は、[アプリパスワード](https://support.google.com/accounts/answer/185833)を生成し、それを設定する必要があります。

設定が終わったら`db:migrate`と`assets:precompile`を実行します。

```
mastodon$ docker-compose run --rm web rails db:migrate
mastodon$ docker-compose run --rm web rails assets:precompile
```

ここまでの作業でインストールは完了です。


## Mastodonテストサーバーの起動

`docker-compose.yml`を見るとわかりますが、実はデータベースなどもDockerの中で作るため、Dockerコンテナを再起動するとデータが初期化されます。
よってまずは、そのままで起動した上で、動作を確認しましょう。

```
mastodon$ docker-compose up -d
```

## Nginxの設定

テストサーバーのURLはmastodonコンテナの中の「`http://localhost:3000/`」です。そこでホストにNginxプロキシを用意して、外部からプロキシ経由でアクセスすることにしましょう。

ホストにNginxとSSL証明書のためのLet's encryptをインストールし、証明書を生成します。

```
$ sudo apt install nginx letsencrypt
$ sudo letsencrypt certonly --standalone --standalone-supported-challenges tls-sni-01 -d mastodon.example.com
```

あとは[Mastodonのドキュメント](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Production-guide.md)にしたがって、Nginxの設定を追加するだけです。

  - `example.com`は自分のドメイン名にしましょう
  - `127.0.0.1`と`localhost`は`lxc list`で表示されるmastodonコンテナの`eth0`のアドレスに設定しましょう

上記以外は特に変更する必要はありません。

では、良いMastodonライフを！