このブログをホスティングしているVPSマシンを移行したのでその記録。
2019/6/22の時点でこのブログはConoHaのVPS(512MB)で運用していた。
当時はお金の関係で一番安いプランを選んでいたが、やっぱり1GBはあった方が嬉しいので変更することにした。
ただConohaのプランでは
- 512MB … SSD20GB
- 1GB以上 … SSD50GB
となっており、同じサーバのままアップグレードはできない。
したがって新たに1GBサーバを立てて移行、その後に512MBサーバを破棄する流れにした。
どうせなので、今まで使用していたCentOS 7からUbuntu 18.04にOS変更することにした。
理由は↓のあたりである。
- CentOSはある程度触ったから
- よっぽど堅牢なものを組まない限りyumの基本パッケージでの構築をしないことがわかった
- rpm入れまくってパッケージマネージャがごちゃごちゃになってた
移行するもの
移行前スペック
- CentOS 7
- CPU 1core
- Mem 512MB
- SSD 20GB
移行後スペック
- Ubuntu 18.04
- CPU 2core
- Mem 1GB
- SSD 50GB
移行サービス
- このブログ(https://ryotosaito.com/blog)
- CTFサイト(http://ctf.ryotosaito.com)
- SQL injectionチュートリアル(http://beginner-sqli.m1z0r3.ctf.ryotosaito.com)
- など
- 上記サービスのmysql(インスタンスを分けてドメインソケット通信で管理していた)
- VPN(個人的なWi-Fiの盗聴回避用)
これ512MBでよく回してたな…
方針
- home directoryをtar.gzで固めて移す
- web directoryをtar.gzで固めて移す
- 必要なconfig fileを適切な場所に移す
- mysqlをdockerにする(後述)
移行
なるべくWebサービスを止めないように意識しながら移行したつもりである。
ちなみに今後出てくる敗北数は予期せぬサービス停止が発生したことを意味する(不穏)。
ConoHaのプライベートネットワーク
- サブネット: 172.16.0.0/21
- CentOS: 172.16.0.1
- Ubuntu: 172.16.0.2
プライベートネットワークに繋ぐと1Gbpsの回線をゲットできる。
ただ繋ぐためには一度マシンを落とさなければならない。
また、マニュアルの通り、プライベートネットワークの接続で提供されるのはインタフェースのみなので、IPアドレスなどの設定は自身で行う必要がある(ConoHaのコントロールパネルでIPアドレスを入れたのは意味がなかったのでは…?)。
$ diff -u /etc/netplan/10-gmovps.yaml{.save,}
...
+ eth1:
+ addresses: [172.16.0.2/21]
+ dhcp4: false
+ dhcp6: false
+ accept-ra: false
+ optional: true
...
はじめに
Webコンソールで鍵を入れる
$ mkdir .ssh
$ curl -o .ssh/known_hosts https://github.com/ryotosaito.keys
以降は手元からsshで処理ができる
$ ssh xxx.xxx.xxx.xxx
iptables → ufw
CentOSではiptablesを使っていた(firewalldでは?という質問はNG)
Ubuntuではそれ(ら)の代わりに標準でufwを採用している。
Uncomplicated Firewallの名前通り、設定はめっちゃ簡単だった。
$ ufw enable
$ ufw accept ssh
$ ufw accept http
$ ufw accept https
# VPN ports
$ ufw accept isakmp
$ ufw accept ipsec-nat-t
mysql → docker
これまで通りmysqlのインスタンスをわけて管理するのでもよかったのだが、取り回しが楽そうなdocker管理に切り替えることにした。
そうでもしないとdockerを実運用しなさそうだったというのもある。
Ubuntuでのdockerのインストールは公式ドキュメントを参考に、gpg鍵とリポジトリを加えてから行う。
まずは移行元マシンでsqlファイルを書き出し、転送をする
# 書き出し
$ mysqldump -S /path/to/mysql.sock --databases ctf -p > ~/ctf.sql
# 転送
$ scp ~/ctf.sql 172.16.0.2:.
続いて移行先マシンでdocker mysqlを起動、リストアをする。
ポイントはボリューム(-v)でデータをローカルに永続化することと、 --restart unless-stopped
オプションで自動(再)起動にすること。
# 初期化、ランダムパスワードを有効化
$ docker run -itv "$PWD/ctf:/var/lib/mysql" --name=ctf-mysql -e "MYSQL_RANDOM_ROOT_PASSWORD=yes" mysql
# パスワードを取得したらC-p, C-qで抜けて一度コンテナを止める
$ docker stop ctf-mysql
# 自動(再)起動オプションをつけて再度走らせる
$ docker run -ditv "$PWD/ctf:/var/lib/mysql" -p 3306:3306 --name=ctf-mysql --restart unless-stopped mysql
# リストア
$ docker exec -i ctf-mysql sh -c 'exec mysql -uroot -p"password"' < ~/ctf.sql
v8.0以降のmysqlは従来(v7.x以前)とデフォルトのパスワードハッシュ方式が違う。
デフォルトでcaching_sha2_password
になっているが、mysql_native_password
でないとPHPのPDOからアクセスできないのであらかじめ解決する(1敗)。
mysql> ALTER USER 'username'@'%' IDENTIFIED WITH mysql_native_password BY 'password'
ちなみにWordpressでこんなエラーが出て気づいた。
Warning: mysqli_real_connect(): (HY000/2002): No such file or directory in /.../wp-includes/wp-db.php on line 1612

後で追加で調べたところ、DB初期化のコマンドを以下のようにすればもっと良いみたい。
$ docker run -itv "$PWD/ctf:/var/lib/mysql" --name=ctf-mysql -e "MYSQL_RANDOM_ROOT_PASSWORD=yes" mysql --default-auth=mysql_native_password
今回は複数のDBを走らせるために、ホストポートの割り当てを3306から順番に行った。
IANAのサイト(https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml)にサービスと予約ポート番号の割り当てが書いてあったので、自分が使いそうなものと競合していなければバンバン使うことにした。
DNS
移行先でサービスを走らせたものから順にAレコードのIPアドレスを書き換えることで両方のマシンで受け付けられるようにした。
TTLは3600だったので、全レコードを切り替えてから1時間以上経てば旧マシンを停止しても問題ない計算になる。
Nginx
CentOSの時に入れていたphp-fpmはlocalhost:9000(PHP7)とlocalhost:9001(PHP5)で通信を受け付けていた(PHP5しか対応していなかったものは移行をきっかけに一度閉鎖することにした)。
aptでインストールしたphp-fpmは初期設定がドメインソケットだったのでこれをそのまま使うことにした。
よってnginx.confにある全てのモジュール設定を書き換える必要がある(3敗)。
$ diff -u /etc/nginx/conf.d/www.conf{.old,}
...
location ~ \.php$ {
root /path/to/webroot;
- fastcgi_pass 127.0.0.1:9000;
+ fastcgi_pass unix:/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
...
また、sslの証明書や鍵をちゃんと移して、configの更新もしておく。
ちなみにこれを機にnginx.confにひとまとめに書いていたものを細かく分割してconf.dディレクトリに入れた。
PHP
旧マシンの各webrootをそれぞれtar.gzでまとめ、scpで移して展開する。
$ tar cvzf web.tar.gz webroot/
$ scp web.tar.gz 172.16.0.2:/path/to/webroot
新マシンで動かす際はサービスに必要なPHP拡張をあらかじめ入れておく(1敗)。
$ apt -y install php-mysql php-mbstring ...
また、document rootのownerをちゃんと正しておく(1敗)。
$ chown -R www-data: /path/to/webroot
また、PDOのdsnに書いていたhostが今までlocalhostでも動いたにも関わらず、127.0.0.1と書かないと接続できなかった(1敗)。
これの原因はわかっていない。
VPN
strongswanをインストールして、configとかsecretを移すだけ。systemctl restart strongswan
を打ち忘れて「設定が反映されない!」と焦った人がいるらしい。
最後に
全部rootでやっていたので一般ユーザを加えるのを忘れていた(usermod
の後reboot
が必要だったので計2敗)
$ useradd -m user
$ passwd user
# Ubuntuの標準sudoグループはwheelではなくadminだった
$ usermod -aG admin user
# dockerグループを追加しないとdockerが叩けない(dockerのドメインソケットにアクセスできない)
$ usermod -aG docker user
自分のローカルマシン上で、旧マシンドメインのssh鍵と新マシンIPのssh鍵を破棄する。
$ ssh-keygen -R ryotosaito.com
$ ssh-keygen -R xxx.xxx.xxx.xxx
$ ssh ryotosaito.com
まとめ
ちょっと負けすぎやしませんかね…
本気で透過的な移行をするのであれば一時的なサブドメインを登録して試せばよかったなと後悔。
コメント