WordPress 本体のアップデートプロセスチャート

WordPress 本体のアップデートプロセスチャートを作ってみました。

WordPress 3.7 から実装された自動更新で WordPress がアップデートされると、WordPress 本体が自動でアップデートできます。

自動更新は、いくつかのアップデート方式 (マイナーバージョンだけ、メジャーバージョン・マイナーバージョン両方) があり、それぞれが WordPress 本体がどのようにアップデートするか図解してみました。

加えて、開発したプラグイン「WP Auto Updater」で実装したアップデート方式

  • Minor Only Version Update
  • Previous Generation Version Update

を追加してみました。

安定的な WordPress サイトの運用に参考にどうぞ。

WordPress Update Process Chart
WordPress Update Process Chart

参考

次世代 WordPress テーマスターターキット「WP Theme Boilerplate」をリリースしました

WordPressスターターテーマ「WP Theme Boilerplate」を開発しました。

去年2018年11月頃。WordPress 5.0 から新しいブロックエディタ (Gutenberg) が出ることだし、それにフィットする WordPressテーマを作りたいなぁと。公式に掲載してみたいなぁと。
もともと定番スターターテーマである「_s (Underscores)」をベースにテーマを作っていましたが。
気づいたらいつのまにか方針転換をしちゃって、テーマ作りより独自のオリジナルテーマがスムーズに作れる環境を作ったほうが広がりがあって面白いなぁと思い、取り組んでみました。

WordPressテーマスターターキット「WP Theme Boilerplate」 8 つの特徴

特徴は 8 つほど。

  • テンプレート階層とディレクトリレイアウトを改善
  • WordPress Theme Autoloader を実装
  • テーマの機能をクラスベースで実装
  • Theme hooks を実装
  • Block Editorに最適化した WordPressテーマを目指して Block Editor (Gutenberg) をサポート
  • Theme Starter script で独自テーマのスターターテーマを生成
  • npm scripts でテーマ開発環境を整備
  • composer scripts でテーマテスト環境を整備

スターターキットとしてテーマ開発環境を整備

  • フロントエンド開発環境
  • WordPressテーマ開発環境
  • テスト環境 (ユニットテストや静的コード解析、CI/CDまで)

この辺がサクッと整備されたらいいなぁと。

ただ効率的にテーマがつくれることだけを追求してもだめで。(単にテーマを作れるだけでは価値はだんだんなくなってくる)
一番価値が生まれるところである、デザインやコンテンツにきちっと時間を割きたい。
ビジネスにスピードと柔軟性が求められている中でプロトタイプ的な、アジャイル的なアプローチで開発ができるようにしたい。
常に改善されるテーマになるよう機動性を手に入れたい。
新しい価値を生み出す今の開発環境にマッチできるような設計思想をいくつか組み入れてみました。

結果、ただテンプレートが揃っただけのスターターテーマではなく、開発環境やテスト環境など周辺環境を整えた「スターターキット」にしてみました。

テーマ設計で感じたこと

WordPressテーマは、ディレクトリ直下にテンプレートファイルが置かれる (WordPress 全体から見るとテーマフォルダ自体が View って感じな、テーマ開発者にとって View がディレクトリ直下にある感じな) ので、
ディレクトリ構成上フラットになりやすく、いろんな種類や役割がファイルが混ざってくる。
シンプルなテーマなら気にならないが、開発しているとファイルが散らばり複雑になってくる。
のちのち開発効率や開発意欲の低下がボディブローのように効いてくるので手を入れて整理してみた。

シンプルにテンプレートファイルを一つ下のディレクトリにまとめるアプローチで解決する。
テンプレート階層にも関わってくるので、複雑なことはしないようにする。
WordPressは、テンプレートの選ばれ方を把握していないとそう簡単に動かすことはできないけど。
これでディレクトリレイアウトが少しばかり整理される。

次にテーマの機能を関数からクラスベースに変える。
従来だと、関数名がWordPressコアの関数や他のテーマ・プラグインの関数とかぶらないように
関数名を「テーマ名のプリフィックス_関数名」みたいに先頭に namespace をつける。ので関数が必然的に長くなる。
また開発を続けていると、どの機能に関係している関数か、この関数はどこに影響や副作用を及ぼすのか、
functions.php が肥大したり、次第にまとまりがわからなくなってくる。
方向性としてテーマの機能は、クラスベース (クラスファイル) で namespace をつかってそれぞれの機能が分離するように再設計した。

そのクラスファイルは、composer autoloader のように自動的に読み込んでくれるように
WordPressのファイル命名規則に基づいて WordPress Theme Autoloader を実装してみた。
必要ならば composer autoloader を使って外部のライブラリにある機能を取り込めることもできるし。
大掛かりにならない程度の実装で機能を取り込めるように、開発が楽しくなるように目指してみた。

メインテンプレートには、複雑なロジックを入れないようにベースとなるレイアウトだけ定義する形がよさそう。
そしてパーツとして切り分けたファイルをメインテンプレートに読み込むのが基本線。
また wp_head, wp_footer などテンプレートタグにフックする。(最近 v5.2 だと wp_body_open が出てさらに便利になったね)

フックは WordPressの大きな特徴で醍醐味な部分なので。(フックを覚えたらWordPressの開発が楽しくなると思うなぁ)
テーマ専用のフックがあってもいいのではなかろうか。(将来共通化したものが出てくれたらうれしい)
ということで Theme hooks を実装してみた。
メインテンプレートのレイアウトの所々にいくつか設けた Theme hooks に引っ掛けることでメインテンプレートには手を入れずに追加要素を差し込んだり、フックした関数 (アクション) 側で複雑なロジックを組み入れることを目指してみたい。

あなただけのオリジナルWordPressテーマをつくろう

独自テーマが作れるように Theme Starter script を用意してみました。
テーマ名を引数に Theme Starter script を走らせるだけでオリジナルテーマの雛形がすぐに生成されます。
そこからあなただけのオリジナルWordPressテーマをつくっていける開発環境ができあがる。
WordPressテーマを作れる環境はすでに目の前にあります。
WordPressテーマ作りを楽しく過ごしてみてね。

素敵な、便利な、魅力的な WordPressテーマがたくさん生まれたり、
面白い、読み応えのあるコンテンツがある WordPressサイトがいっぱい出来上がったり、
テーマ開発やWordPress構築プロジェクトを成功に導いたりと。
WP Theme Boilerplate が縁の下の力持ちとして
少しでも力になれば幸いです。

リソース

今後すること・したいこと

今後やることをメモ。

  • テストを書く
  • ドキュメントをつくる
  • WP Theme Boilerplate をベースに公式テーマを (やっと) つくる

WordPress保守運用チェックリスト

WordPressでウェブサイトやブログを立ち上げるのは、手軽でツールとして便利な一方。
WordPressサイトを運用しつづけるには、メンテナンスをする手間やセキュリティ上のリスクを自分で対応する必要があります。

保守管理をするレベルで対応できる範囲はそれぞれですが。
個人でWordPressサイトを運営する方から、ビジネスでWordPressを使ってウェブサイトを開設している方、ウェブ制作会社などクライアントのウェブサイトをサポートしている方に参考になるようできるだけ幅広い視点から「WordPress保守運用チェックリスト」を作成してみました。

WordPress保守運用の底上げに繋がれば幸いです。

WordPress保守運用チェックリスト

2020.10.05更新

WordPress保守・保全

  • WordPress本体・テーマ・プラグインがアップデートできる環境になっている
  • 自動アップデートが機能している環境になっている
  • WordPress本体はこまめにアップデートしている
    1. 手動
    2. 自動
  • テーマ・プラグイン・翻訳はこまめにアップデートしている
    1. 手動
    2. 自動
  • データのバックアップを定期的にしている (ファイルとデータベース両方)
    1. 手動
    2. 自動
  • バックアップのスケジュール・頻度
    1. 毎日
    2. 毎週
    3. 毎月
  • バックアップデータの格納先
    1. サイトと同一サーバー上
    2. 別のサーバー・ストレージサービスなど遠隔スペース
  • バックアップ先は、セキュリティを施してアクセスは制限されている
  • データベースの肥大化を防いでいる
    • 投稿履歴の件数を制限している
    • データベースの​​最適化を定期的に行っている
  • リストアなど復旧作業のシミュレーションを検証環境上で行っている

WordPressセキュリティ

アプリケーションレイヤー

  • テーマ・プラグインは出所 (開発元) を確認して適切に管理している
    • 公式ディレクトリ掲載テーマ・プラグイン (審査レビューチェック済み)
    • 有料テーマ・プラグイン
    • 野良テーマ・プラグイン (配布先ダウンロードが特定サイトのみ、GitHubなどレポジトリのみ)
    • 独自開発テーマ・プラグイン
  • 使っていないテーマは、デフォルトテーマ一つだけ残して削除している
  • 使っていないプラグインは削除している
  • セキュリティ系のプラグインを少なくとも一つは導入している
    • ログイン・パスワード試行攻撃防御 (総当たり攻撃・ブルートフォースアタック、パスワードリスト攻撃)
    • DDoS 攻撃防御
    • メールフォームスパム対策
    • コメントスパム対策
    • セキュリティ監視
  • wp-config.php の salt を wordpress.org salt generator で生成して設定している
  • wp-config.php をアクセスできないルートディレクトリ外に配置している
  • WordPress 本体を専用ディレクトリにインストールしている
  • テーマ・プラグインのファイル編集機能を停止している
  • 独自に開発したテーマ・プラグインは適切に管理している
    • ソースコードの変更履歴を管理している
    • PHPやWordPress本体の最新バージョンにアップデートできるように設計している、または都度対応できるようにしている
    • 自動アップデートできるように設計している
      • WordPressの自動アップデートの仕組みを組み込んでいる
      • GitHubなどレポジトリを分けて管理をしている
    • 独自テーマ・プラグインをいつでも修正をして不具合対応・改修ができる
    • 継続的に改善を行ってテーマ・プラグインの性能・品質を向上し続けている

ミドルウエアレイヤー

  • ファイルパーミッションを適切に設定している
  • PHPの実行を拒否、ファイルアクセス拒否制御を行っている
    • wp-config.php
    • /wp-admin/includes/
    • /wp-includes
    • /wp-includes/js/tinymce/langs/
    • /wp-includes/theme-compat/
    • /wp-content/themes/
    • /wp-content/plugins/
    • /wp-content/uploads/
  • 管理画面ログインアクセスのセキュリティを強化している
    • reCAPTCHAを導入している
    • Basic認証を導入している
    • 管理画面のアクセスをIPアドレスホワイトリストで限定している
    • 2段階認証・2ファクタ認証を導入している
    • ログイン画面をデフォルトのURLアドレスから変更して、アドレスを知っている限られた人にのみに制限
  • XML-RPCへのログインアクセスのセキュリティを強化している
    • アクセスをIPアドレスホワイトリストで限定している
    • XML-RPCの機能を無効化している
  • サイトへの特定のアクセスをIPアドレスブラックリストで制限している
  • 国外IPアドレスフィルタを有効にしている
  • WAFを導入している、またはWAF機能を有効にしている
  • マルウェア混入チェックを定期的に行っている
  • 脆弱性診断を定期的に行っている

ヒューマンファクター

  • ユーザ名 admin は削除している、または存在していない
  • ユーザ名 admin のログインを即時禁止している
  • ユーザアカウントのパスワードを適切なパスワード強度で設定している
    • 8文字以上
    • 小文字・大文字・数字が最低1つずつ含まれている
    • できれば記号も含める
    • パスワード自動生成なら尚よし (Password Generator)
  • ユーザアカウントの使い回しをしていない
  • 複数のユーザアカウントには、適切な操作権限を付与している
  • 使われていないユーザアカウントは定期的に削除している
  • ログインアクセスを履歴記録している

サーバ・システムインフラ基盤

  • サーバーの保守管理担当者がいる
  • レンタルサーバーまたはVPS・クラウドサーバーで運用している
  • 独自ドメインで運用している
  • 接続元IPアドレスが取得できる (リバースプロキシサーバ構成ではX-Forwarded-ForでIPアドレスを送出)
  • 接続元IPアドレスを対象としてアクセス制限ができる
  • ファイル (URL) を対象としてアクセス制限ができる
  • SSL/TLS (サーバ証明書) を導入して暗号化通信している
    1. http と https 両方でサーバー接続している
    2. 常時SSL (https のみに限定してサーバー接続、http はリダイレクト処理)
    3. 常時SSL (https のみに限定してサーバー接続、http は80番ポート閉鎖)
  • 通信プロトコル HTTP/2 で通信している
  • サーバー・データベースやPHPなどミドルウエアを定期的にアップデートしている
  • 定期的にサービスプランを変更してサーバーを刷新している、またはサーバ・システム基盤をリプレイスしている
  • サーバーパフォーマンスを定期的に計測している、またはモニタリングしている
  • ネットワークパフォーマンスを定期的に計測している、またはモニタリングしている

運用体制・障害対応

  • WordPressの保守担当者がいる
  • 死活監視を導入している
    1. 人的監視
    2. リモート自動監視
  • アラート通知など障害発生にすぐに気づく体制がある
  • 24時間以内に一次対応 (応急処置) で障害の復旧ができる
  • 障害の原因調査ができる体制がある
  • WordPressサイトの再現検証、テスト環境がある
  • 再発防止策の実施など根本的な解決を行える体制がある
  • 障害報告・対応作業報告・作業予定など情報を共有している
  • 保守運用体制を定期的にチェックして改善している

その他

  • WordPressに関連しないファイルを削除、または適切に整理管理している (WordPressの管理下にないファイルや以前のホームページデータなど不要なファイルなど)
  • 移行作業をした際に使ったバックアップデータを残していない
  • 移行作業をした際に使った phpMyAdmin、phpinfo.php を残していない

参考

Vagrant 共有フォルダが同期できないときの対処法 /sbin/mount.vboxsf: mounting failed with the error: No such device

最近各 Linux ディストリビューションがリリースしている Vagrant Box を使うようになりました。
以前は、Bento project など良さそうな Vagrant Box を採用していましたが、
Linux ディストリビューションの Vagrant Box が整備されつつあるので、もっぱら使っています。

ただ Virtualbox Guest Additions がインスールされていない状態の Vagrant Box なので、
プロビジョニングの時にプラグイン vagrant-vbguest で入れるようにしています。
Vagrant では、いくつかフォルダ共有のタイプがあるのですが、
VirtualBox の共有フォルダ機能を使う場合は、Virtualbox Guest Additions が必須になります。

今回その時に遭遇した不具合対処メモ。

環境

  • Vagrant
  • VirtualBox
  • Vagrant Box は、centos/7 (virtualbox, 1803.01)
  • プラグイン vagrant-vbguest で Virtualbox Guest Additions をインストール
  • Provisioner は、ansible_local、Ansible でプロビジョニング

不具合現象

vagrant up すると、共有フォルダが同期できない現象。

==> default: Mounting shared folders...
    default: /vagrant => /Users/thingsym/vaw
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

mount -t vboxsf -o uid=1000,gid=1000 vagrant /vagrant

The error output from the command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device

遡って調べて診てみる。
Virtualbox Guest Additions はインストール完了したが、
vboxadd.service が立ち上がっていない。
結果、共有フォルダがマウンドできない。

Installing Virtualbox Guest Additions 5.2.12

Redirecting to /bin/systemctl start vboxadd.service
Job for vboxadd.service failed because the control process exited with error code. See "systemctl status vboxadd.service" and "journalctl -xe" for details.

カーネルのバージョンが不一致になっている。

Please install the Linux kernel "header" files matching the current kernel
for adding new hardware support to the system.

原因

Virtualbox Guest Additions をインストールするときに
必要なパッケージをインストールするのですが、
そのなかに kernel-headers が含まれていて
kernelのアップデートのタイミングの問題? なのか
アップデートしてしまう。

ゲスト側でカーネルを調べると、
カーネルのバージョンが不一致になっている。
今回は、パッチ番号 (693と862) が不一致に。

rpm -qa kernel\* | sort

kernel-3.10.0-693.21.1.el7.x86_64
kernel-headers-3.10.0-862.2.3.el7.x86_64
kernel-tools-3.10.0-693.21.1.el7.x86_64
kernel-tools-libs-3.10.0-693.21.1.el7.x86_64

kernel-headers が kernel のバージョンに対応していない状態。

解決

vagrant ssh

ゲスト側に入り、kernelをアップデート

sudo yum -y update kernel
sudo yum -y install kernel-devel kernel-headers kernel-tools kernel-tools-libs

カーネルのバージョン (パッチ番号862) を揃える

rpm -qa kernel\* | sort

kernel-3.10.0-693.21.1.el7.x86_64
kernel-3.10.0-862.2.3.el7.x86_64
kernel-devel-3.10.0-862.2.3.el7.x86_64
kernel-headers-3.10.0-862.2.3.el7.x86_64
kernel-tools-3.10.0-862.2.3.el7.x86_64
kernel-tools-libs-3.10.0-862.2.3.el7.x86_64

再度プロビジョニング

vagrant reload

BashテストフレームワークBatsのヘルパースクリプト「Bats Assertion」をつくりました

Bash のシェルスクリプトは、エンジニアが片手間に書いて使う DIY 的な使い捨てスクリプトになりがちぎみだけれども。
Bash のシェルスクリプトを作ってオープンソースとして公開している手前、
「きちっとテストを入れたいなぁ」と思っていろいろ Bash のテストどうやるの? というところから始まって
どんなアプローチがあるのだろうといろいろ調べたり試したり。
結果、Bashテストフレームワークとして「Bats」がシンプルすぎるぐらいに良かったので採用してみました。

Bashテストフレームワーク「Bats」とは

Bats の正式名称は、Bash Automated Testing System。

ドキュメントには、

Bats is a TAP-compliant testing framework for Bash.
(訳: BatsはBash用のTAP準拠のテストフレームワークです。)

とある。

使い方は、.bats 拡張子を付けたファイルにテストケースを書いていくだけ。
例えば、example.bats に以下を書いて

#!/usr/bin/env bats

@test "status - return 0 exit code" {
  run bash -c 'exit 0'
  [ "$status" -eq 0 ]
}

@test "output" {
  run bash -c 'echo -e "abc"'
  [ "$output" = "abc" ]
}

@test "lines" {
  run bash -c 'echo -e "abc\ndef\nghi"'
  [ "${lines[0]}" = "abc" ]
  [ "${lines[1]}" = "def" ]
  [ "${lines[2]}" = "ghi" ]
}

テストを走らせると、

bats --tap example.bats

テスト結果が得られます。

1..3
ok 1 status - return 0 exit code
ok 2 output
ok 3 lines

テストケースのプロセスは、
run でコマンドを実行し、
その結果が 3つの変数に保存されます。

  • $status - exit status を保存
  • $output - 標準出力またはエラー出力を保存
  • $lines - 標準出力またはエラー出力を行単位で配列で保存

それら変数を確かめたり、アサーションしたりする。

setup, teardown もあるので、
いろんな設定を想定したテストケースが作れると思います。

Bash だけでなくいろんな言語のコマンドラインツールで使えて
シンプルなテストには、もってこいのテストフレームワークです。

ヘルパースクリプト「Bats Assertion」

今回、その Bats のヘルパースクリプト「Bats Assertion」をつくりました。

Assertion 系のヘルパースクリプトは、ほかにもありましたが、
テストを書くこと自体がテストドキュメントになる。
もっとシンプルに書けて、テストを書くことが億劫にならず、
テストを育てていく感じにならないかなぁと思って設計してみました。

使い方は、ヘルパースクリプト「Bats Assertion」をダウンロードして
テストファイル内で Bats の load コマンドで読み込むだけ。

load bats-assertion/bats-assertion

読み込むと、以下の assertion 系のコマンドが使えるようになります。

  • assert_success
  • assert_failure
  • assert_status
  • assert_equal
  • assert_fail_equal
  • assert_match
  • assert_fail_match
  • assert_lines_equal
  • assert_fail_lines_equal
  • assert_lines_match
  • assert_fail_lines_match

それぞれのコマンドの詳細は Assertion Reference を参照してみてください。

ヘルパースクリプト「Bats Assertion」で書き換えると

先の example.bats をヘルパースクリプト「Bats Assertion」で書き換えると、
こんな感じになります。

#!/usr/bin/env bats

load bats-assertion/bats-assertion

@test "status - return 0 exit code" {
  run bash -c 'exit 0'
  assert_success
}

@test "output" {
  run bash -c 'echo -e "abc"'
  assert_equal "abc"
}

@test "lines" {
  run bash -c 'echo -e "abc\ndef\nghi"'
  assert_lines_equal "abc" 0
  assert_lines_equal "def" 1
  assert_lines_equal "ghi" 2
}

assertion 系のコマンドを体系化することでテストが書きやすく、
一目見ただけで分かりやすいテストケースになって
そのままテストドキュメントにもなればなぁと思います。

ドキュメント

リソース

最近の投稿

カテゴリー

アーカイブ