Mastodonサーバ移行手順（非Docker）

# 前提条件

* Fedora 28 Server にて検証作業を実施した
* すでに動作しているインスタンスを、別のサーバに移行したい
* 移行元・先は、物理的に別物（パブリックIPアドレス、ストレージ、DBが独立している）


# 事前準備

## サーバの準備

* 利用者にサービス一時停止をアナウンスする
* 移行先サーバを調達して、初期設定を済ましておく

## サーバ以外の準備

* DNSのTTLを短くする
1日以下、数時間、数十分とかまで縮める。
これにより、規模(アクセス数)によっては、一時的にDNSサーバの負荷が高まる。
現在のTTLから逆算すれば、だいたいいつ頃作業すればいいか分かる。かも。



# 実作業

## (事前作業) 移行先サーバにMastodonを通常通り構築する

[Mastodon構築手順・非Docker版](https://qiita.com/kumasun/items/543c62eedeb0f00e5afd) 等を参考にして、構築する。

**安全のため、移行元と同じバージョンで構築を行う。**
DNS切り替えを行っていない関係上、SSL証明書の取得が出来ないので、その手前で止めておく。
（SSL証明書が無いと、Nginxの起動そのものができないはず）

Mastodonの`.env.production`、およびNginxの `mastodon.conf`は流用可能。

Mastodonのサービス3点セット（web/streaming/sidekiq）のサービス登録まで行っておく。
（`systemctl status mastodon-web` 等を発行して確認できる）
テスト等でサービスを起動した場合は、確実に止めておく。


## 切り替え作業

### 移行元サーバ停止

Mastodon周りの3点セットを停止する。
これでエラー画面が表示されるはず。

```bash
$ sudo systemctl stop mastodon-{web,sidekiq,streaming}
```

### DNS切り替え

DNSのAレコードを、新しいサーバに切り替える。
念のため、DNSのTTLは短いままにしておく。


### バックアップを取得

バックアップファイルの容量を減らす必要がある場合は、「古い投稿」「リモートメディア」「プレビューカード」「孤立メディア」を削除すると多少削減できるかもしれない。

```bash
# どのファイルが容量を食っているのか算出
RAILS_ENV=production bundle exec bin/tootctl media usage

# 過去の投稿を削除。日数は適宜調整
RAILS_ENV=production bundle exec bin/tootctl status remove --days=90

# プレビューカードを削除。日数は適宜調整
RAILS_ENV=production bundle exec bin/tootctl preview_cards remove --days=180

# リモートメディアを削除
RAILS_ENV=production bundle exec bin/tootctl media remove --days=0

# 孤立メディアを削除
RAILS_ENV=production bundle exec bin/tootctl media remove-orphans
```


[Mastodonアップデート手順（基本）・非Docker版](https://qiita.com/kumasun/items/f17754e57120f7b13a06) 等を参考に、データベースとPublicディレクトリのバックアップを取得し、作業用ローカル端末に転送する。

テーマカラーのカスタマイズを行っている場合は、下記ファイルもバックアップする。

```text
app/javascript/styles/*.scss
config/themes.yml
```

### バックアップを復元

public/system ディレクトリとデータベースのバックアップを移行先サーバに転送し、展開する。
SFTP等で、 `/tmp/` に転送すると便利。 

↓ 一般ユーザ作業

```bash
# Mastodon3点セットを確実に止める
$ sudo systemctl stop mastodon-{web,sidekiq,streaming}

$ sudo su - mastodon
```

↓ Mastodonユーザ作業

```bash
$ cp /tmp/public.20171130_181413.tar.gz .
$ cp /tmp/mstdn.20171130_181327.pgdump .
$ ls -l
合計 58000
drwxrwxr-x 19 mastodon mastodon     4096 11月 30 17:52 live
-rw-rw-r--  1 mastodon mastodon   467908 11月 30 18:15 mstdn.20171130_181327.pgdump
-rw-rw-r--  1 mastodon mastodon 58913299 11月 30 18:15 public.20171130_181413.tar.gz
$ mv live/public live/public_org
$ tar xfz public.20171130_181413.tar.gz
```
※ 既存のPublicディレクトリを上書きしちゃうので、念のためバックアップ取る

↓ Mastodonユーザ作業（つづき）

```bash
# 新しく作ったデータベースを削除して、空のDBを作りなおす
$ dropdb --interactive mstdn
データベース"mstdn"は永久に削除されます。
実行しますか？ (y/n)y
パスワード: 
$ createdb mstdn
パスワード: 

# ダンプファイルを復元する
$ psql mstdn < mstdn.20171130_181327.pgdump 
ユーザ mstdn のパスワード: 
SET
SET
SET
・
・
・
ALTER TABLE
ALTER TABLE
ALTER TABLE
$ exit
```

↓ 一般ユーザ作業

```bash
# 転送用の一時ファイルを消す
$ rm /tmp/public.20171130_181413.tar.gz
$ rm /tmp/mstdn.20171130_181327.pgdump
```


#### `uninitialized constant ActiveRecordQueryTrace (NameError)` が出て止まっちゃった時は

依存パッケージが不足しているかもしれないので、もう一度 `mastodon` ユーザで `bundle install` を試す。

```bash
$ bundle install
```

### ホームタイムラインの再構築

タイムラインの情報が消えているので、下記タスクにて再構築を行う。
（Redisのバックアップ・リストアを行った場合は不要？）

```bash
$ RAILS_ENV=production bundle exec bin/tootctl feeds build --all
```



### DNS情報反映まで待つ

DNSレコードが反映されるまで待つ。



### 忘れ物チェック（雑多な移行項目）

* タスクスケジューラ（crontab）の設定はしましたか？
* PostgreSQLのチューニングはしましたか？
* PostgreSQL、Redisの接続方法は確認しましたか？(TCP/IP or Socket)
* jemalloc、PgBouncer等の設定忘れはありませんか？
* 全文検索エンジンの設定忘れはありませんか？


### Let's Encrypt SSL証明書の再発行

移行先サーバにて、 Let's Encrypt SSL証明書の再発行を行う。

```bash
$ sudo certbot certonly --standalone -d yourdomain.tld
```

(SSL証明書そのものをコピーしてこればいい説もあるが。。。)


### Nginx の起動

↓ 一般ユーザ作業

```bash
# SSL証明書が正しく取得・インストールされていれば、問題なく立ち上がる
$ sudo systemctl start nginx
$ sudo systemctl start mastodon-{web,sidekiq,streaming}
```



### 動作確認

* コマンドプロンプト/ターミナルより、nslookup/dig等でDNS名前解決ができるかを確認する。
（新しいIPアドレスに変わっているかどうか）
* 実際にウェブブラウザからアクセスし、正常にログイン画面等が表示されることを確認する。
（象バンバンでないこと）
* ログインし、正常にトゥートができることを確認する。
* 連合タイムライン等に、他インスタンスからのトゥートが届いているか確認する。
* 他インスタンス宛のアクション（トゥート、お気に入り、ブースト）が正常に反映されるか確認する。


### DNSのTTLを元に戻す

ここまで来れたなら問題ないはずです。
DNSのTTLを長めに設定し直し、通常運用を開始できます。


## トラブルシューティング

### 「既に存在する」と言われ、データベースの復元ができない

初期構築時に作成したデータベースを消して、まっさらのデータベースを再作成しておく必要があります。

### Let's Encryptの証明書が取得できない

* ファイアウォールで、`80/TCP (HTTP)` および `443/TCP (HTTPS)` をのインバウンドを許可していますか？
業者によっては、Web設定画面からファイアウォールの設定が出来ることがあります。(Microsoft Azure/ GMO ConoHa 等)
また、それとは別に、サーバ側のソフトウェアファイアウォールの設定が必要なことがあります。（iptables / firewalld 等）

* DNSレコードの変更の反映(浸透)が終わってないもしれません
これは待つしかありません。
おおむね、事前設定したTTLと同じくらい待てばよいはずです。
十分待っても失敗するようであれば、DNSの設定が誤っているかもしれません。


# あとがき

* 自分用にメモした手順です。必要に応じて読み替えてください。
* こうしたほうがいいよ的なアドバイスを頂けると大変助かります

以上