趣味エンジニアリングで久々に WordPress を触ったのでメモです。
AWS EC2 の WordPress を大きくアップグレードする手順を、スピード重視で雑気味にやったので、参考になったりならなかったりすると思います:-)
更新理由
ちょうど6年前、自宅サーバーをAWSに移行しました。物理サーバーDebian4 から EC2 CentOS7 にサービスを爆速で移行するというゲームに成功した
— 外道父 | Noko (@GedowFather) July 25, 2017
この時は、鉄拳SNS『zexi』(参考:Zexiサーバー管理で取り組んだこと | Noko Tekken Memories)の都合を中心に移行しましたが、今回 zexi は閉鎖済みのため完全に自分都合で適当に作業することができました。
キッカケとしては、はてなブックマークのブクマ数に異変が起きたこと。具体的理由としては完全HTTPS化、インスタンスタイプ更新による費用削減と性能向上、あたりです。
今は数値が正常になっていますが、はてブ数が一時的に変になり、140台あった記事が 80台 2つに分割されたんですね。
ブログはサードパーティコンテンツ表示のために基本HTTPのままなんだけど、HTTPSも開けてはあるから、それのせいで突然ブクマ数が分割されたっぽい。HTTPSへのリダイレクトとかリンクはしてないけど、まぁチェックされてもおかしくはないわな
— 外道父 | Noko (@GedowFather) July 13, 2023
自分のブログの被ブクマリストを見ると、HTTP と HTTPS の2つに分かれたことがわかりました。元々 http 主体で公開していたけど、一応リダイレクト無しで https も開けていたことで、なんかチェックされて変になったんだろうということで、今は HTTPS にするのが基本だし、この際やるべきことを一気にやり切ることにしました。
このあたりについて、記録しておきます。
旧環境と新環境の差分
まず基本的な作業方針として、せっかくAWSにいるので、既存環境での更新作業は一切せず、新環境で全てを新しく用意してから丸っとアクセス先を切り替えるつもりでした。しかしこれは、一部が諸事情により破綻したため、そのへんについても記述していきます。また、その方法だと移行作業中の既存環境における更新内容を全て捨てることになりますが、せいぜいアクセスログとほぼつかないコメントくらいしかなく、自分が記事を更新しない限りは READ 専用のようなブログなので、その辺を気にする必要はありませんでした。
インスタンスタイプ
旧環境は t2.small でしたが、新サーバーを作って移行するので、t4g.small に変更しました。差分としてはこんな感じでいいことづくめです。Type | Cost | vCPU | Memory | Storage | Network |
t4g.small | $0.0216/h | 2 | 2 GiB | EBSのみ | 最大 5 ギガビット |
t2.small | $0.0304/h | 1 | 2 GiB | EBSのみ | 低~中 |
EBS
ついでに EBS を gp2 から gp3 に変更しました。たいしたシステムではないとはいえ、性能も費用もお得なので変えない理由がないです。
OS
CentOS 7 だったのを、Rocky Linux 9 にしました。Debian も好きなんですけどね、業務でも選択されやすいってのと、今をゴタゴタときめくRHEL系にするってのもまたおかしってヤツです。ていうか、ぶっちゃけ最新かつ Stable な選択なら、なんでも動かせると思っているので、ってところはあります。
WordPress
元は 3.2.2 とかだったかな?から、最新の 6.2.2 へ3段階アップ。業務なら怒られそうな放置っぷりでしたが、個人ブログなんてどうなってもいいやって姿勢もあり、その適当さから急激なアップグレードとなります。
WordPress のバックアップ
Wordpress ってWEBサーバーの DocumentRoot 丸ごとと、MySQL の DB 丸っと mysqldump があれば完全なリストアができるので、なにより最初にバックアップを確保し、S3 に転送しておきました。
1 2 3 4 5 |
tar cjf wordpress-app.tar.bz2 /var/www/wordpress mysqldump -u root -p wordpress | bzip2 > wordpress-mysql.sql.bz2 aws s3 cp wordpress-app.tar.bz2 s3://example-backup/wordpress/ aws s3 cp wordpress-mysql.sql.bz2 s3://example-backup/wordpress/ |
実際、各種更新の途中で気に入らないヤラカシをして何回か戻したので、スピード重視で雑にアップグレードする度合いが強いほど、ここをキチッとして恩恵を受けます。
WordPress のバージョンアップ
新しい OS になると、当然通常のパッケージのバージョンも上がることになります。MySQL は選択可能とはいえ勢いで 5.x から 8.0.x にしても全く問題がありませんでしたが、PHP 5 → 8 では流石に問題が発生しました。PHP は 7.x から急激に変わると認識してよいところですが、古い WordPress が必要とする mysql モジュールが新しいPHPには存在しなく、mysqli などに切り替わっていたため、ここで新環境のみでの準備を断念しました(※多分、ドキュメント通りに丁寧にコードを直接更新したらイケる)。
採用した手段としては、旧環境での WordPress を先に更新してしまうことです。
Wordpress 3.x の管理画面における自動更新には、PHP 5.6.x が必要であり、CentOS 7 では 5.4.x であったため自動更新の利用が不可能でした。そこで頼ったのは Remi 先生の Repository です。PHP を削除して、必要最低限のバージョンをインストールします。
1 2 3 4 5 6 7 8 9 |
systemctl stop httpd yum remove php-* yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm yum install --enablerepo=remi,remi-php56 \ php php-cli php-common php-devel php-gd php-mbstring php-mysqlnd \ php-pdo php-pear php-process php-xml systemctl start httpd |
ここで引っかかると面倒でしたが、PHP 5.6 にした程度では何もエラーは出なく、また WordPress の更新自体は全く何も問題なく WordPress 6 にすることができました。
この時点で再度バックアップ一式を採り、新環境でリストアして、PHP 8 でも動作することを確認できたので、この先の更新作業は新環境で行うことになります。
WordPress の更新で気をつけること
テーマの更新
更新ページではテーマの更新もできますが、私の場合は CSS をだいぶイジっていたので、テーマを更新するとかなりデザインが崩れることがわかりました。自分の変更部だけを新しいCSSに移しても元通りにはならなく、その流れで治すのは非常に面倒であったため、テーマは古いバージョンで続行することにしました。
プラグイン
テーマと違ってプラグインは PHP で書かれているので、PHP 5.x から 7.x 以上 への変更に耐えられるプラグインは半分前後になると思われます。かなりエラーが出て最初はログイン画面や管理画面すら出せなかったので、PHPのエラーログ(/var/log/php-fpm/www-error.log)を見て片っ端からプラグインを削除していきました。削除は直に rm -rf wp-content/plugins/**** をする感じです。ついでに、あまり利用しないプラグインも削除整理しました。
どうしても利用継続したいけどエラーが出るプラグインは、エラーログで調べれば結構解決策を見つけることができるので、PHPをあまり理解していなくても少々プラグインのコードを切り貼りできれば直せるものも多かったです。さすが利用者が多い?Wordpress + PHP です。
新環境の準備
全ては記述しませんが、こんな感じだよって雰囲気メモを載せておきます。基本
時間とかコマンドとか。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ cat /etc/rocky-release Rocky Linux release 9.2 (Blue Onyx) hostnamectl set-hostname gedow-home-01 timedatectl set-timezone Asia/Tokyo vim /etc/selinux/config -- SELINUX=disabled -- setenforce 0 getenforce dnf install \ epel-release \ vim lsof tcpdump git telnet dnsutils \ bzip2 cronolog dnf install python3-pip pip3 install awscli |
Apache + PHP
変えるのが面倒だから Apache のまま続行しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
dnf install httpd httpd-devel httpd-tools cronolog mod_ssl certbot python-certbot-apache dnf install php php-cli php-common php-devel php-gd php-mbstring php-mysqlnd \ php-pdo php-pear php-process php-xml vim /etc/httpd/conf/httpd.conf -- ServerName www.gedow.net:443 <Directory "/var/www"> AllowOverride All Require all granted </Directory> SetEnvIf Request_URI "\.(gif|jpg|png|ico)$" no_log IncludeOptional sites-enabled/* -- vim /etc/httpd/site-enabled/wordpress |
SSL
Let’s Encrypt なので、好きな方のコマンドを叩いて
1 2 3 4 5 |
# 単発 certbot certonly --webroot --webroot-path /var/www/wordpress/ --domain blog.father.gedow.net # 複数ドメインをまとめる場合 certbot --apache -d blog.father.gedow.net |
VirtualHost の設定に追加します(※–apache の場合は勝手に追加される)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<VirtualHost *:80> DocumentRoot "/var/www/wordpress/" ServerName blog.father.gedow.net ... RewriteEngine On RewriteCond %{HTTPS} off RewriteCond %{REQUEST_URI} !(^/.well-known/) RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L] </VirtualHost> <VirtualHost *:443> DocumentRoot "/var/www/wordpress/" ServerName blog.father.gedow.net ... SSLEngine on SSLCertificateFile /etc/letsencrypt/live/blog.father.gedow.net/cert.pem SSLCertificateKeyFile /etc/letsencrypt/live/blog.father.gedow.net/privkey.pem SSLCertificateChainFile /etc/letsencrypt/live/blog.father.gedow.net/chain.pem </VirtualHost> |
そしてチェックして反映して終わり。
1 2 |
apachectl configtest systemctl reload httpd |
のあとに定期更新を仕込んでおくと。
1 2 3 4 |
vim /etc/cron.d/letsencrypt -- 0 0 1 * * root certbot renew -q --no-self-upgrade --post-hook "systemctl reload httpd" -- |
MySQL
MySQL はもう仕事でも 8.x を触っているので最新でOK
1 2 3 |
dnf localinstall -y https://dev.mysql.com/get/mysql80-community-release-el9-2.noarch.rpm dnf install -y mysql-community-server mysql-community-devel mysqld --version |
個人用なので怒られそうな設定も入れちゃう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
vim /etc/my.cnf -- !includedir /etc/my.cnf.d -- vim /etc/my.cnf.d/overwrite.cnf -- [mysqld] validate_password.length = 4 validate_password.mixed_case_count = 0 validate_password.number_count = 0 validate_password.policy = 0 validate_password.special_char_count = 0 log-error = /var/log/mysql/error.log slow_query_log slow_query_log_file = /var/log/mysql/slowquery.log long_query_time = 0.2 -- mkdir /var/log/mysql && chown mysql:mysql /var/log/mysql systemctl restart mysqld |
ユーザーを作って wp-config.php に書いて
1 2 3 4 5 6 |
sudo less /var/log/mysqld.log # 初期rootパスワードが書いてある mysql -u root -p mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '**********'; CREATE USER 'wordpress'@'localhost' IDENTIFIED BY '**********'; GRANT ALL ON *.* TO 'wordpress'@'localhost'; |
ログローテーションも仕込むと。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
vim /etc/logrotate.d/mysql -- /var/log/mysql/*.log { create 640 mysql mysql notifempty monthly rotate 5 missingok compress postrotate # just if mysqld is really running if test -x /usr/bin/mysqladmin && \ /usr/bin/mysqladmin ping &>/dev/null then /usr/bin/mysqladmin flush-logs fi endscript } -- |
プラグイン
エラーが出たのは削除するとして、個人的に好きで入れたり直したのを書いておきます。Classic Editor
新しい WordPress はエディタが完全に変わっていて、古い記述では編集したら改行などの内容が強制変更されたりするので、慣れた旧式で継続することにしました。『Classic Editor』を入れるだけで、完全に旧式に戻ってくれるので助かりました。
brBrbr300
旧式で改行は多用していたので、そのまま使うためにコードを変更してエラー回避しました。
1 2 3 4 5 6 7 8 9 |
/* // e が使えなくなったので callback に変更 $brbr = preg_replace('/(<pre.*?>)(.*?)<\/pre>/is', "clr_br('$0')", $brbr); $brbr = preg_replace('/(<script.*?>)(.*?)<\/script>/is', "clr_br('$0')", $brbr); $brbr = preg_replace('/(<form.*?>)(.*?)<\/form>/is', "clr_br('$0')", $brbr); */ $brbr = preg_replace_callback('/(<pre.*?>)(.*?)<\/pre>/is', function($m) {return clr_br($m[0]);}, $brbr); $brbr = preg_replace_callback('/(<script.*?>)(.*?)<\/script>/is', function($m) {return clr_br($m[0]);}, $brbr); $brbr = preg_replace_callback('/(<form.*?>)(.*?)<\/form>/is', function($m) {return clr_br($m[0]);}, $brbr); |
GA Google Analytics
Google Analytics の GA4 のコードを埋めるだけなら、これが良かったです。でも前に使ってたのはログイン者の閲覧では埋め込み回避する仕様だったので、そこだけ不足ですね。Pro にしたらカスタマイズできるかもだけど。
WP Social Bookmarking Light
Twitter, Facebook, はてブ のボタン表示ですが、バージョンが変わってコード構成が結構変わっていました。PHPエラーを解決するのと、Twitter < 検索ボタン の検索部分を表示させるために、以下のような変更をしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
* wp-social-bookmarking-light を治す https://wordpress.org/support/topic/quick-fix-for-deprecated-warning-of-unparenthesized/ wp-content/plugins/wp-social-bookmarking-light/vendor/twig/twig/lib/Twig/Node.php 42行目 @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, \get_class($this)), E_USER_DEPRECATED); 198行目 @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, \get_class($this)), E_USER_DEPRECATED); * wp-social-bookmarking-light にTwitter検索を追加する /var/www/wordpress/wp-content/plugins/wp-social-bookmarking-light/src/WpSocialBookmarkingLight/Service.php -- public function twitterSearch() { $options = $this->option->getAll();; $data_url = $this->url; return $this->linkRaw( '<span class="social-balloon">' . '<a href="https://twitter.com/search?f=tweets&q='.$data_url.'" target="_blank">検索</a>' . '</span>' ); } -- /var/www/wordpress/wp-content/plugins/wp-social-bookmarking-light/src/WpSocialBookmarkingLight/Option.php -- "twitter_search" => array( ), -- |
既存のtwitter部の出力改造では、自分の力では改行を免れず難しかったので、コードの雰囲気を見て勝手に自前のパーツを作成し、管理画面で追加した感じです。
他のお好みプラグインは、代替品を探したりして対応しました。
新旧環境の切り替え
書き忘れましたが、新環境の準備をする際は手元OS の hosts 情報を書き換えて、URL は同一でテストしています。一通り新環境の準備が整ったら、アクセスを新環境に切り替えます。切り替え方はシンプルで、ElasticIP を旧環境からデタッチし、新環境にアタッチしただけです。多少はサービスダウンしますが、これならDNSレコードの編集の必要すらなく即座にアクセスが切り替わります。
また、追加EBS もあったので、umount とデタッチしてから、新環境にアタッチと mount をしています。
んで旧環境EC2 を停止して、数日後に削除して完了です。
終わりに
こういう作業は仕事で慣れている俺でも、これだけのバージョン変更を伴う更新と環境移行をすると、さすがに半日以上かかりました。でもたまには、こういうガンガン止めたりエラー出したりしても構わない環境で、更新作業自体を1つのゲームとして楽しむ感じでやるのは気分転換になってよろしいです。
Wordpress の UI が変わって少し楽しかったのと、特に不要な性能向上とか、EC2 + EBS の所が 2~3割 安くなったとか、ぼちぼちな成果だったと思います。やったね:-)