序
今まで運用していたMisskeyインスタンスを、64GBメモリのベアメタルに引っ越した。
これまでこのインスタンスはConoHa VPS, Vultr, XServerと移転しており、3回目の引っ越しになる。
ので軽く考えていたのだが、公式ドキュメントに移転に関する記述はなさそうであった。
……あれ、なかったっけ?
あったような気がしたけど。
で、ドキュメントを探したけれど「自分はこうしたので備忘録」みたいなのしか見つからなかったので、ある程度整理する方向で今回の記事を書くことにした。
ただし、基本的には私の構成を想定した話にしている。
以下がその構成
- サーバーディストリビューションはArchlinux
- 移転元サーバーは生でのインストール
- 移転先サーバーはsystemd-nspawnでのコンテナにする
- プライベートネットワークを使用せず ホストのPostgreSQLを使う
- コンテナは
/var/lib/machines以下に置いてmachinectlでコントロールする
前置き
各プロンプトは次を表している:
@pc% <- 手元の作業PCの一般ユーザー
@old# <- 移行元サーバーのroot
# <- 移行先サーバーのホストのroot
## <- 移行先サーバーのコンテナのroot (misskey)
%% <- 移行先サーバーのコンテナの一般ユーザー (misskey)
ホストの一般ユーザーはjrhであるとしている。
SSHのホスト名は以下を表している。
old-root <- Hostが移行元サーバー, Userがroot
new-jrh <- Hostが移行先サーバー, Userがjrh
SSHを用いてrootで安全にログインする方法についてはサーバーでsudoなんかやめてSSHでrootログインしようぜ!参照のこと。
全部がシーケンシャルなわけではなく、いくつかの作業は並列でできる。
とくにバックアップとアップロードの間に下準備は可能である。
が、話がややこしくなるので、本記事ではシーケンシャルに効率的にできる手順にしている。
手順
下準備
新サーバー自体のセットアップが終わっているのは前提。
そこはどんなインスタンスでどういう使い方をするかによるので、具体的手順は省略。
少なくとも
pacman -S base base-devel nginx certbot postgresql vim zsh grml-zsh-config less git rsync
くらいはしておきたい。
また、PostgerSQLの初期化は必要。
あらかじめ新サーバーでNginxを設定を反映させておく。
今回のサーバーマイグレーションは全体で見るとMisskeyを格納しているサーバー以外も含めていくつかのサイトを統合したが、少なくともMisskeyをホストしているサイトにあるものはすべて移行する計画だった。
このため、Misskeyをホストしているサーバーの/etc/nginxと/etc/letsencryptはそのままコピーして問題ない。
DNSの向きを変えるだけでコントロールできるからだ。
ただ重要な点として、/etc/letsencryptはコピーする前にrenewしておき、自動更新を切って期限内にマイグレーションし、すべて移行してから移行先サーバーで自動更新を有効する必要がある。
また重要なこととして、/etc/nginxがデフォルトサーバーとして適切なもの(ほとんどの場合404)を返す必要がある。
でなければDNS切り替えのタイミングがちゃんと稼働してからに縛られてしまい、作業がしづらい。
入れ物の用意
nspawnコンテナをあらかじめ用意しておく。
もしコンテナをbtrfs subvolumeにしたい場合なども、あらかじめやっておく。
# cd /var/lib/machines
# mkdir misskey
# pacstrap -K -c misskey base base-devel nvm pnpm ffmpeg valkey zsh grml-zsh-config moor vim vim-plugins bat
# systemd-nspawn -D misskeypasswd
## systemctl enable valkey
## useradd -r -m -U misskey
## su - misskey
%% nvm install 24
%% nvm alias default 24
%% exit
## exit
最後にexitしているのは、この作業はsystemd -D misskeyで入っていてSystemdが起動しておらず、続きの作業ができないので一旦このシェルは終了してしまう必要があるため。
btrfsサブボリュームにする場合の例。
(難易度が高いので、これで分からない人は触れないほうが良い)
# mkdir /var/lib/machines/misskey
# mount $path_to_btrfs_disk -o subvol=/ /mnt
# cd /mnt
# btrfs subvolume @misskey
# vim /etc/fstab
UUID=xxxxxxxxxxxx /var/lib/machines/misskey btrfs defaults,subvol=@misskey 0 0
# systemctl daemon-reload
# mount /var/lib/machines/misskey
サーバー停止とDNS更新
Misskeyを停止し、メンテナンスに入る。
@old# systemctl disable --now misskey
このタイミングでDNSを更新して新サーバーに向けておくと良い。
なお、DNSのTTLを長くしている場合は、事前にTTLを詰めておくこと。
でないとユーザー環境で反映されるのに時間がかかる。
バックアップとアップロード
ここでは/home/misskey/misskeyにインストールする方式を採用している。
バックアップする対象は
/home/misskey- PostgreSQLの
misskeyデータベース - PostgreSQLの
misskeyロール
今回の場合別に全部もってきても問題はないので、globalsは全部持ってくることにする。
@pc% ssh old-root "sudo -Hu postgres pg_dump -U misskey -Fc -C misskey | zstd" >| misskey.pgdump.zst
@pc% ssh old-root "sudo -Hu postgres pg_dumpall -U postgres --globals-only | zstd" > globals.sql.zst
@pc% ssh old-root "tar --zstd -C /home/misskey -cvf - --exclude .cache ." > misskey.home.tar.zst
@pc% rsync --progress misskey.* globals.* new-jrh:
コンテナに展開
コンテナのmisskeyユーザーのホームディレクトリをマイグレーションする。
# cd /var/lib/machines/misskey/home/misskey
# tar xvf ~jrh/misskey.home.tar.zst
# chown -R misskey:misskey .
データベースの復元
あらかじめデータベースの初期化はしている想定。
postgresユーザーでアクセス可能なディレクトリを用意してそこに伸長して読ませるという流れ。
# mkdir /pub
# chmod 777 /pub
# cd /pub
# zstd -d ~jrh/globals.sql.zst -o globals.sql
# zstd -d ~jrh/misskey.pgdump.zst -o misskey.pgdump
# sudo -Hu postgres psql -U postgres -f globals.sql
# sudo -Hu postgres pg_restore -U postgres -d postgres --create -v /pub/misskey.pgdump
# cd
# rm -r /pub
Systemdユニットの復元
Misskeyはコンテナ内で動作させるので、Misskeyの起動をコントロールするSystemdユニットはMisskeyコンテナの中に必要である。
certの更新はホスト側、NginxとPostgreSQLはホスト側。ValKeyはコンテナ側。
軽い注意点だが、シェアネットワークしているので他にValKeyを起動しているコンテナがあるとポートが競合する。
なのでその場合はポートを変更する必要がある。
# cp ~jrh/misskey.service /var/lib/machines/misskey/etc/systemd/system/
# cd /var/lib/machines
# systemd-nspawn -b -D misskey
## systemctl enable --now misskey.service
## ^]^]^] # shutdown container
machinectlでの起動
machinectlで起動するのはsystemd-nspawnで起動するのと一部のデフォルト値が異なる。
プライベートユーザーは使いたいけどプライベートネットワークは使わないので、設定しておく。
# vim /etc/systemd/nspawn/misskey.nspawn
[Network]
VirtualEthernet=no
matchinectlで自動起動を設定&起動。
既にコンテナ内でSystemdがmisskeyを自動起動するようになっているのでコンテナを起動すればアプリにつながる。
# machinectl enable --now misskey
プチ解説
/var/lib/postgres をコピるのはナシ?
基本的にはナシ。
まずオンラインでやると中途半端な状態をコピってしまう可能性があるため、これをやるためにはオフラインでやる必要がある。
そうなるとバックアップのために他のPostgreSQLを使うサーバーも止めることになるし、移設も一気にやるしかない。
そもそもバックアップの時間は伸びがちになる。
もうひとつはクリーンアップの問題。
PostgreSQLは使っているとかなり汚れる。dumpしてrestoreするとまっさらなところにデータだけが入るのでクリーンアップできる。
これをやる機会はかなり少ないので、それが自然にできるマイグレーションの機会にやったほうがいい。
ホストのPostgreSQLを共有すると何が嬉しいのか
リソースを分割せず、PostgreSQLに潤沢に割くことができるから。
PostgreSQLはメモリオーバーヘッドも大きいし、メモリをかなり使う。
だからできるだけ大きくメモリを与えておきたいのだけど、個別に立てると予め分割して割り当てる必要が出てくる。
特にHugePagesでたっぷりメモリを割り当てたいならひとつにまとめておくほうがいい。
それに個別のアプリの利用状況に対しても融通が効くようになる。
これはブロックデバイスの「あんまり細かくパーティション切らない」というトレンドと同じようなもの。
nvm使って起動
ArchlinuxのNode.jsは先を行き過ぎるので、nvmを使っている。
#!/bin/zsh
source /usr/share/nvm/init-nvm.sh
nvm use 24
npm start
ただ現在はパッケージでバージョンが固定できるようになっているので、コンテナ内でnodejs-lts-kryptonとかをインストールしてそのまま呼ぶとかもアリ。