はじめに
五回目となったこのシリーズですが、今回はWordPressとMariaDBの導入および高速化するための設定について紹介します。
現在、当サイトでは静的サイトジェネレータのZolaでウェブサイトを構築しているため、既にどちらも使用していません。
しかし、Zolaを使う以前の旧サイトではWPおよびMariaDBを長い間使っていたこともあるため、自身のメモ代わりとしても残しておこうと思います。
これまでのシリーズ一覧は以下のとおりです。
- Ubuntu20.04のInstallおよびSSH、FTP設定【第一回】
- Nginxの導入および設定&セキュアなHTTPS化【第二回】
- Rust製SSG、Zolaの導入および各種設定【第三回】
- Nginxリバースプロキシで静的コンテンツ専用サーバを作成【第四回】
- WordPress&MariaDBの導入および高速化設定【第五回】
- https://www.pr1sm.com/web/wordpress-and-mariadb-fast-settings/
- サイトの安全性を更に高めるWordPressセキュリティ設定【第六回】
なお、このシリーズではホスティングにVultrを使っています。
Vultr
サーバのスペックおよび構成は以下の通りです。
$ cat /etc/lsb-release
- DISTRIB_ID=Ubuntu
- DISTRIB_RELEASE=20.04
- DISTRIB_CODENAME=focal
- DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
Vultr : High Frequency Server
- 32GB MVMe
- 1CPU
- 1GB Memory
- Additional Features
- Virtual Private Clouds: ON
ウェブサーバにはNginxを用い、HTTPS化に必要な証明書の取得にはLet'sEncryptを使いますが、この記事ではこれらは既に導入済みとして扱います。
PHP8のインストール
まずはWordPressの実行に必要となるPHP(執筆時点ではPHP8.1)をインストールします。
ただし、Ubuntu20.04のリポジトリにあるPHPはPHP7であることから、バージョンが古いです(22.04からはPHP8をサポート)。
そのため、最新版であるPHP8を手軽にインストールするには、Ondrej Sury氏による非公式(しかし有名です)の個人用リポジトリ(Personal Package Archive PPA)を追加する必要があります(Ubuntu22.04からは不要)。
The main PPA for supported PHP versions with many PECL extensions
DEB.SURY.ORG APT Repository Issue Tracker
Ondrej Sury
Ondrej Sury氏はチェコ出身のエンジニアで、BINDとDHCPの保守開発などを行うISC(The Internet Systems Consortium)にて、DNSエンジニアリングのディレクターを務めています。
$ sudo add-apt-repository ppa:ondrej/php
でリポジトリを登録しようとすると、以下の文章が出てきます。
Co-installable PHP versions: PHP 5.6, PHP 7.x and most requested extensions are included. Only Supported Versions of PHP (http://php.net/supported-versions.php) for Supported Ubuntu Releases (https://wiki.ubuntu.com/Releases) are provided. Don't ask for end-of-life PHP versions or Ubuntu release, they won't be provided.
Debian oldstable and stable packages are provided as well: https://deb.sury.org/#debian-dpa
You can get more information about the packages at https://deb.sury.org
IMPORTANT: The <foo>-backports is now required on older Ubuntu releases.
BUGS&FEATURES: This PPA now has a issue tracker:
https://deb.sury.org/#bug-reporting
CAVEATS:
1. If you are using php-gearman, you need to add ppa:ondrej/pkg-gearman
2. If you are using apache2, you are advised to add ppa:ondrej/apache2
3. If you are using nginx, you are advised to add ppa:ondrej/nginx-mainline
???or ppa:ondrej/nginx
PLEASE READ: If you like my work and want to give me a little motivation, please consider donating regularly: https://donate.sury.org/
WARNING: add-apt-repository is broken with non-UTF-8 locales, see
https://github.com/oerdnj/deb.sury.org/issues/56 for workaround:
# LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
More info: https://launchpad.net/~ondrej/+archive/ubuntu/php
Press [ENTER] to continue or Ctrl-c to cancel adding it.
これは
ppa:ondrej/php
の処理に関する注意書きですが、基本的には特に問題無いため、そのままEnterで処理を続行します。するとリポジトリが追加されるので、
$ sudo apt update
でリポジトリのアップデートをチェックします。$ apt search php8.1
でphp8.1関連のパッケージ(モジュール)一覧と説明を見ることができます。
WordPress使用時には複数のモジュールが必要となってくるため、
$ sudo apt install php8.1 php8.1-cgi php8.1-common php8.1-curl php8.1-dev php8.1-fpm php8.1-gd php8.1-intl php8.1-mbstring php8.1-mysql php8.1-xml php8.1-zip
で各種インストールします。- 順にphp8(PHP本体)、cgi(Common Gateway Interface)、common(Common module)、curl(cURL)、dev(Development)、fpm(FastCGI Process Manager)、gd(Graphics library)、intl(The Internationalization)、mbstring(Multibyte string)、mysql(MySQL)、xml(Extensible Markup Language)、zip(ZipArchive)となっています。
- インストール後、
$ php -v
でバージョンをチェックできます(執筆時点ではPHP8.1.2)。
MariaDBの導入
次にWordPressのデータベースとして使うMariaDBをインストールします。 その前にMariaDBについてですが、MySQLのオリジナルコードの作者であるMichael Widenius氏によって2009年に制作された、オープンソースソフトウェアであるMariaDBは、数々の最適化によってパフォーマンスが高いと言われています。 例えばデータベースのViewの場合、MySQLは接続されているテーブルすべてを照会しますが、MariaDBではクエリによって必要とされるテーブルのみが照会されるため、大きくパフォーマンスを向上することができます。 基本的にWordPressではMySQLを用いることが多いですが、MariaDBはその高い性能によって人気を獲得し、多くの人々に愛用されています。 ではインストール方法ですが、執筆時点でのMariaDBのバージョン そのため、MariaDBの公式からリポジトリを登録してインストールします。 よく紹介される方法として 同リンクの すると まず 次に []内は先程インポートした署名鍵検証に使われる鍵を指定しており、これによりリポジトリごとに鍵が参照されます。 そして MariaDBをインストールする準備が整いましたので これでMariaDBのインストールが完了しました。 インストールしたバージョンと同じであれば正しくインストールできています。 MariaDBから接続を抜けるには MariaDBが使えるようになったので、WordPress用のデータベースを作成します。 例ではドメイン名(example.comなど)でデータベースとユーザ(rootユーザは使わない)を作ります。 次にユーザ作成ですが、 作成が確認できれば、MariaDBについて
MariaDBのインストール
10.6.5
なのに対し、Ubuntu20.04に搭載されているMariaDBでは10.3
とバージョンが古くなっています。apt-key
がありますが、このコマンドは廃止予定となっているため、当記事ではGNU Privacy Guard(GPG)を用いてリポジトリの登録を行います。Choose a distribution
にて自身のOSを選択し、Choose a MariaDB Server version
で執筆時点の最新安定版である10.6
を選びます。Mirror
およびコマンドの例が自動的に表示される(日本であれば山形大学, 米沢市 - Yamagata University, Yonezawa
)ので、それを元にリポジトリの登録を行います。$ curl -fsSL https://mariadb.org/mariadb_release_signing_key.asc | sudo gpg --dearmor -o /usr/share/keyrings/mariadb-archive-keyring.gpg
によって署名鍵を格納します。/usr/share/keyrings/mariadb-archive-keyring.gpg
に格納されました。$ sudo vim /etc/apt/sources.list.d/mariadb.list
でMariaDB用のリポジトリリストを作成します。mariadb.list
deb [arch=amd64,arm64,ppc64el,s390x signed-by=/usr/share/keyrings/mariadb-archive-keyring.gpg] https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/repo/10.6/ubuntu focal main
$ sudo apt update
でアップデートをチェックします。$ sudo apt info mariadb-server
でチェックすると10.3
から10.6
に変更されています。$ sudo apt install mariadb-server
でMariaDBをインストールします。MariaDBセキュリティ初期設定
$ sudo mysql_secure_installation
を実行することで対話型の初期設定が行えます。NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.
## MariaDBのrootパスワードが既に存在していれば入力(enterで無し)
Enter current password for root (enter for none):
Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.
You already have your root account protected, so you can safely answer 'n'.
## rootログイン時にパスワード認証ではなくUNIX Socket認証を使うかどうか
## つまり、MariaDBのrootにログインできるのはrootユーザのみ(sudoかsuコマンド)
## 他にもユーザ作成時に"VIA unix_socket"を付けることで同じ認証をそのユーザに適用する
## ただし、TCP接続が必要なアプリケーションを経由するときはこの認証が使えない
## 複数ユーザが単一のアカウントを使い回す場合は"no"
## 例ではUnixSocket認証を使うので"Yes"
Switch to unix_socket authentication [Y/n]
Enabled successfully!
Reloading privilege tables..
... Success!
You already have your root account protected, so you can safely answer 'n'.
## rootのパスワードを変更するかどうか
## UnixSocket認証を使っているので"no"。パスワード認証を使う場合は"Yes"で変更する
## ただし、ブラウザでphpMyAdminにrootログインする予定がある際はパスワードが必要
Change the root password? [Y/n]
... skipping.
By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
## 匿名ユーザを削除するかどうか。匿名ログインは必要ないので"Yes"
Remove anonymous users? [Y/n]
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
## リモートでのrootログインを無効にするかどうか。ローカルしか使わないなら"Yes"
Disallow root login remotely? [Y/n]
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
## testという名前のテスト用データベースを削除するかどうか。不要なので"Yes"
Remove test database and access to it? [Y/n]
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
## 特権テーブルをリロードするかどうか。すぐに設定を反映させたいなら"Yes"
Reload privilege tables now? [Y/n]
... Success!
Cleaning up...
## これでMariaDBの設定が完了しました。
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
$ sudo mysql -u root
でパスワード無し(UniXSocket認証)のままMariaDBにroot接続することができます。 $ sudo mysql -u root -p
でrootログインできます。$ sudo mysql_secure_installation
を実行します。MariaDB [(none)]> use mysql
でデータベースをmysql
に変更し、MariaDB [(mysql)]> ALTER USER 'root'@'localhost' IDENTIFIED BY "ここにパスワードを入力";
を実行することで、rootに対する新しいパスワードを設定できます。MariaDB動作確認
$ sudo mysql -u root
でMariaDBに接続します。MariaDB [(none)]> select version();
を実行し、バージョンをチェックします。$ madiadb --version
でチェックできます。MariaDB [none]> exit
を入力します。ctrl+c
でも可能。WordPress用のデータベースを作成
$ sudo mysql -u root -p
でMariaDBに接続します。MariaDB [(none)]> CREATE DATABASE `DB-NAME`;
で新たにデータベースを作成します。DB-NAME
の箇所はWordPressのDBとして使う名前を入れます(例ではexample.com
などのドメイン名)。MariaDB [(none)]> GRANT ALL PRIVILEGES ON `DB-NAME`.* TO "USER-NAME"@localhost IDENTIFIED BY "DB-PASS";
を実行します。DB-NAME
には先程作ったばかりのWP用データベース名を入れます。USER-NAME
はそれに対応するユーザ名(例ではここもドメイン名)を記入します。DB-PASS
にはそのユーザに対するデータベース用のパスワードを新規に入力します。MariaDB [(phpmyadmin)]> show databases;
でデータベースが追加されたか確認します。MariaDB [(phpmyadmin)]> select user, host from mysql.user;
で作成したユーザも確認します。MariaDB [(none)]> exit
でMariaDBから離脱します。
WordPress導入前の設定
WordPressを導入する前に簡単な設定を行います。 実行するウェブサーバが PHPの設定はこれで完了です。 NginxもWordPress用に設定を行います。 今シリーズの方法に倣い、 今回の公開ディレクトリとなるrootは ただし、WordPressをインストールするディレクトリは 理由として、WordPressのインストールディレクトリをずらすことにより、わずかながらセキュリティ対策となるためです(公開ディレクトリ直下だとWP関連のファイルが機械的にアクセスされやすいため)。 そのため、PHP設定
nginx
、SFTPユーザ(ログインユーザ名)をtest
として進めていきます。$ sudo vim /etc/php/8.1/fpm/php-fpm.conf
でFPMの設定を行います。php-fpm.conf
;; 省略 ;;
; FPM が利用するイベントメカニズム
; コメントアウトを外す
events.mechanism = epoll
;; 省略 ;;
$ sudo vim /etc/php/8.1/fpm/php.ini
でタイムゾーンを設定します。[Date]
; Defines the default timezone used by the date functions
; https://php.net/date.timezone
; 日付の元となるロケーションを指定(基本的に住んでいるエリア)
date.timezone = "Asia/Tokyo"
$ sudo vim /etc/php/8.1/fpm/pool.d/www.conf
ではuser
、listen.owner
とlisten.group
に属するユーザをnginx
に変更し、group
のみSFTPユーザ名(例ではtest
)を記述します。これにより、PHP実行の際に生成されるファイルの所有権はnginx:test
となります。www.conf
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
; will be used.
user = nginx
group = test
;; 省略 ;;
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions. The owner
; and group can be specified either by name or by their numeric IDs.
; Default Values: user and group are set as the running user
; mode is set to 0660
; www-dataからnginxに変更
listen.owner = nginx
listen.group = nginx
Nginx設定
$ sudo vim /etc/nginx/conf.d/ドメイン名.conf
でドメイン名.conf(例えばexample.com.conf)
の設定を行います。/var/www/ドメイン名
に設定します。/var/www/ドメイン名/apps
です(apps
の名前は自由)。$ sudo mkdir -p /var/www/ドメイン名/apps
でディレクトリを作成しておきます。ドメイン名.conf
## 省略 ##
server {
# 接続するポート番号を指定
listen 443 ssl http2;
listen [::]:443 ssl http2;
# URLに表示されるドメインまたはIPアドレス
server_name ドメイン名;
# ウェブサイト表示時に参照されるディレクトリ
root /var/www/ドメイン名;
# indexページとして読み込むファイル(indexは各locationにも継承される)
index index.php index.html index.htm;
location / {
# 左から順に参照し、該当が無ければ最後のuri(もしくはcode)に内部転送される
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
# 左から順に参照し、該当が無ければ最後のuri(もしくはcode)に内部転送される
try_files $uri $uri/ /index.php?$args /?access=404;
# PHPに渡すパラメータファイルを指定
include fastcgi_params;
# FASTCGIサーバーへのキープアライブ接続をON
fastcgi_keep_conn on;
# スラッシュで終わるURIの後にFASTCGIが要求するファイル名
fastcgi_index index.php;
# fastcgi_path_info変数の値をキャプチャする正規表現の定義
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# FastCGIサーバーに渡すパラメータを指定
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# コード300以上のレスポンスをerror_pageディレクティブで処理
fastcgi_intercept_errors on;
# FastCGIサーバーのアドレスをUnixドメインソケットのパスに指定
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
$ sudo service nginx restart
でNginxを再起動します。
WordPressの導入
ここでようやくWordPressの導入です。 WordPress公式サイトのリリースから最新版を確認します(執筆時点では 次に ダウンロードが終われば、 解凍後は そして、 まず、 その次に ディレクトリもパーミッションを変更する必要があるため、 そして ここでは WordPressはセキュリティが脆弱だとよく言われていますが、対策すれば一定の安全性は確保できます。セキュリティを高める方法については後述します。 これにより最初の設定は完了したため、 この際にエラーが発生していなければ、ウェブサイト( 説明は省きますが、一応ここでユーザ名とパスワード、メールアドレスを先に設定しておきましょう。 また、ログイン後は 更に現在の設定ではWordPressが表示されるのは 編集が終わったら そしてシンボリックリンクを反映させるために この状態でドメイン名のみでアクセスした際、WordPressサイトが表示されていれば最初の構築は完了です。 WordPressが動作するようになりましたが、現状データベースはコンソール上でしか編集できないため少々不便です。 そのため、ブラウザでデータベースを管理するためのツールであるphpMyAdminをインストールします。 Ubuntu上のリポジトリでもインストールできますが、バージョンが古いので(Ubuntu20.04では まず 執筆時点でのphpMyAdminの最新版は ダウンロードが終われば 解凍後、ディレクトリが生成されていますが、その名前を 次に、ウェブサーバで公開するために 現在のパーミッションではエラーが発生する可能があるため、 同時に phpMyAdminにログインした際、 これを解決するには特定のデータベースを作り、その管理権限を持ったユーザーを作成する必要があります。 まず 次に それが終われば、 完了したら 最後に その後、phpMyAdminにログインした際に 上記の他に、暗号化用公開パスフレーズの設定が必要という文章がphpMyAdminに表示される場合があります。 これはphpMyadminの まず最初に、パスフレーズを生成するために そして コピーできれば これまでの設定では、phpMyAdminはそのままウェブで公開されているため、誰もがログイン画面を閲覧できます。 これはセキュリティ上、非常に危険なことを意味しており、セキュリティ対策を行っておく必要があります。 現在、ウェブで公開されているphpMyAdminは これは その方法は 変更された名前は これにより、名前を直接狙った攻撃を避けることが可能です。しかしこれだけでは当然不十分です。 ディレクトリの名前を変更したとしても、アクセスできれば普通にログイン画面が表示されてしまいます。 たとえphpMyAdminでパスワードを設定していても、それを突破されてはお終いなので、Basic認証を追加することで二重で防御を行います。 ただ、Basic認証はBase64でIDおよびパスワードをエンコードするだけであり、ハッシュ化も暗号化もしていないので、現代のセキュリティにとって十分な強度を保っていません。 しかし、TLS化すると通信の暗号化が提供されるため、この問題は解消されます。 そのため、HTTPS(TLS)では無く、HTTPでの使用は完全に筒抜けとなってしまうため推奨できません。 仮にHTTPで認証を行う場合は、Basic認証ではなく、MD5を用いてハッシュ化を行うDigest認証が推奨されます(今の時代ではHTTPで使う方が珍しいとは思いますが)。 ではまず、 次に 編集が完了すれば、今度は 設定が完了したら エラーが発生していなければ、次にphpmyadminにアクセスしてみましょう。正しく設定されていれば、この時点でBasic認証によってユーザIDとパスワードが要求されています。そして、正しいIDとパスワードを入力できたらphpMyAdminのログイン画面へと移動します。 これら設定により、phpMyAdminは無対策時と比べてある程度の安全性を確保することができます。 前回の記事ではプライベートネットワークを用い、静的コンテンツを配信する専用サーバを作成しました。 これを応用すると、WordPressを実行表示するサーバ(NginxとPHP)と、MariaDB(MySQL)を実行するデータベースサーバに分けて稼働させることができます。 サーバが2台必要となりますが、この方法を用いることでサーバの負荷を分散するだけでなく、ウェブサイトに問題が発生した際、それぞれが分離していることで発生原因を特定しやすいというメリットがあります。 このセクションでは、プライベートネットワークに存在する役割の異なる2台のサーバを使い、WordPressが利用可能となるまでの手順を紹介します。 なお、DBサーバ側はデータベースのみ実行するため、MariaDB(MySQL)とphpMyAdmin(必要であれば)のインストールを行うだけであり、NginxもPHPも必要ありません。 逆にウェブ(+アプリケーション)サーバ側はNginxとPHPおよびMariaDB(MySQL)が必要です。 また、既存のWordPressデータベースを使用する場合は、WordPressのDBをphpMyAdminからSQLファイルをエクスポートしておきましょう。 その際、 ファイルのサイズが気になる場合は これは前回の記事と全く同じなので、そちらを参照してください。 この設定は ウェブサーバ側がDBサーバに接続するための設定を行う必要があります。 『DBサーバ』側で ログインしたら 追加できたら 次に『DBサーバ』側で それに加えて、同じく『DBサーバ』側で 編集が完了したら 次に『ウェブサーバ』側で もしphpMyAdminを使う場合で環境保管領域に対応するには、『DBサーバ』側で 次に 作成後は そしてこれが最後の作業であり、『ウェブサーバ』側で WordPressは便利なツールですが、PHPというアプリケーションを使って動的にページを生成することから、動作が重いとよく言われています。 単純にサーバを強化することである程度は解消しますが、様々なチューニングを行うことでもWordPressを高速化させることができます。 このセクションでは、その方法をいくつか紹介します。 FastCGI CacheはNginx特有のキャッシュシステムです。 WordPressはPHPを用いていますが、動的にページを生成する(アクセスごとに生成)ため、その生成にかかる時間がネックとなります。 ここでFastCGI Cacheが活躍します。 このキャッシュシステムを利用すると、一度生成された内容をNginxがサーバ側でキャッシュし、その内容をクライアントにそのまま返すことから、デメリットとなる時間が大幅に短縮され、ページの表示が大変高速になります。 サーバでキャッシュを保存するという性質から、これはクライアントだけでなく、サーバ側の負担も軽減されるため、非常に大きなメリットがあります。 今回の設定ではモバイルとPC別にキャッシュを分けるようにしています。 これにより、モバイルとPCでウェブサイトの表示を変更している場合でも、正しくキャッシュを表示できます(不要な場合は該当箇所をコメントアウトしてください)。 ※FastCGI Cacheでのキャッシュを消去するWordPressのプラグインを使う場合、今回設定しているモバイルキャッシュも消す設定を加える必要があります。 エラーが発生していなければ、ウェブサイトアクセス時にFastCGI Cacheが動作してキャッシュを構築します。 キャッシュを無効化していない限り、明らかに動作が早くなったことを確認できるはずです(設定ではログイン中だと無効化しているので注意)。 ただし、これはPHPで動的に生成されたページのみをキャッシュするため、静的ページやCSSや画像などの静的ファイル、そしてNginxとPHPを経由しないページではFastCGI Cacheは使うことができません。 また、FastCGI Cacheは個人情報が含まれるページ(ログインページなどの専用ページ等)もキャッシュすることができるため、そのような情報が入っているページは基本的にキャッシュしてはいけません。 FastCGI Cacheの命名規則は 例えば このときのキャッシュキーは つまり、 そして生成されたキーはMD5を通してハッシュ化されます。 続いて、 今回の例では そして第2階層では第1階層の文字を除いた、MD5ハッシュの最後2文字で命名されています。 最終的なキャッシュディレクトリの全体構造は以下のとおりです。 これを上手く利用することで、一見複雑に見える構造でも、思ったより簡単にキャッシュ制御を行うことができます。 便利なFastCGI Cacheですが、現在の設定では時間経過でしかキャッシュが消去されません。 つまり、基本的にキャッシュが残っている限りは記事を更新してもそれが反映されません。 これはこれで不便なので、FastCGI Cacheが消去される条件を追加で設定します。 方法は大きく分けて3つあり、一つはWordPressテーマ内の なお、サーバによる別のキャッシュが効いている時や負荷状況によっては、キャッシュの削除が即座に反映されない場合があります。 また、Nginxの作成したキャッシュディレクトリにPHPがアクセスできることを前提としています(同じ実行ユーザ)。 まずは これはプラグインを使いたくない人におすすめで、記事編集後にトップページと編集した記事のキャッシュを削除します。 以上の設定により、新規投稿や記事の更新等を行うと同時に、トップページと編集した記事のキャッシュが自動で削除されます。 2つ目のPHPファイルを作成実行する方法ですが、上記の条件によらずキャッシュを一括削除したい場合には、 これに加えて もしNginxでFastCGI Cacheを有効にしている場合は正しい表示ができなくなるため、キャッシュ削除用ファイルをキャッシュしない設定が必要です。 編集が完了したら 他にもコマンドラインを使いつつ個別に削除したい場合は、以下のPHPファイルを作成して任意の場所に配置します。 配置後、 また、 最後に3つ目の方法であるWordPressプラグインの ただし、プラグインを使う前に少し設定が必要となります。 まずNginx Helperプラグインの すると複数の項目が出てきますが、その中の 次に 編集後、 これにより、Nginx Helperを使用できるようになりましたが、これまでのFastCGI Cache設定ではモバイル版のキャッシュも取得しているため、追加の記述が必要となってきます。 Nginx Helperプラグイン自体を変更しなければならないため、Nginx Helperのプラグインを停止させてから、プラグインファイルエディターで編集画面に移動します。 編集を行うファイルは WordPressを動作させるために不可欠であるPHPは、表示速度に関してダイレクトに影響します。 PHP8となった現在のように、バージョンが上がるにつれてPHPはますますパフォーマンスが向上するようになりましたが、チューニングを行うことで更に高速化できます。 サーバ上でPHPを実行するアプリケーションの一つとして、PHP-FPM(FastCGI Process Manager)と呼ばれるPHPのFastCGI実装があります。 今回はこのPHP-FPMに関してチューニングを行います。 このチューニングは適当にやっていては良いパフォーマンスが得られないため、サーバにあった設定を探す必要があります。 また、PHPが使用するメモリを増減させたい場合には 初期状態でもパフォーマンスの高いMariaDBですが、いくつかの設定を行うことで更にその性能を向上させることが可能です。 チューニングを行う際には 執筆時点での最新版は ダウンロードが完了したら 解凍後、 そして 調整する必要のある項目は以下の通りです。 これら情報を参考にしつつ、 なおチューニングを行う際のPCスペックは最初に掲示した(32GB MVMe,1CPU,1GB Memory)とおりであり、やや厳しい構成です。 そのため、実際にチューニングを行う時は各々のスペックごとに調整してください。 設定が終われば そしてもう一度 まだ調整が必要な箇所はありますが、最初に診断を行った時と比べて状態が良くなりました。 特にメモリの負荷が非常に高かったので、診断結果ではそれが解消されています。 OPcache(オペコード・キャッシュ - Opcode cache)はPHPが動作する際のコードを共有メモリにキャッシュすることで、パフォーマンスを向上させるPHPアクセラレータの一つです。 PHP8ではJIT(Just-In-Time)と呼ばれる、プログラムのソースコードをネイティブコードにコンパイルする機能があります。 それをOPcacheによってキャッシュすることにより、従来のPHPよりも非常に高速に動作することが可能となります。 なお、PHP8のインストール時にOPcacheも一緒にインストールされているため、設定ファイルを編集するだけですぐに使用出来ます。 設定後、 これによりOPcacheが有効化されました。 なお、OPcacheが動作しているかをブラウザで確認するにはOCP(Opcache Control Panel)を使うと、とても簡単にチェックすることが可能です。 導入にはocp.phpをドメイン以下に設置し、ブラウザでパスを指定するだけで使用出来ます。 しかし、公開ディレクトリに配置するということは、誰でもその情報を見ることが出来てしまいます。 そのため、IPによる制限かパスワードを設定、WordPressであれば APCu(APC User Cache)はOPcacheと同じくPHPに働きかける、PHPアクセラレータの一つです。 OPcacheが実行コードをキャッシュするのに対し、APCuはユーザデータを共有メモリにキャッシュすることによってパフォーマンスを向上させます。 APCuの旧バージョンとしてOPcache機能も備えたAPC(Alternative PHP Cache)が存在していましたが、セキュリティ上の問題により現在はAPCは廃止され、ユーザデータキャッシュのみ(OPcache機能は廃止)を備えたAPCuが後継バージョンとなっています。 APCuはOPcacheと異なり、PHP8のインストール直後ではパッケージが同梱されていないため、新しくインストールを行う必要があります。 なお、以前は過去のPHPと下位互換性を持ったAPCu-bc(APCu Backwards Compatibility Module)というパッケージがよく利用されていましたが、PHP8からはbc版はサポートされなくなりました。 PHP8をインストールする際にOndrej Sury氏のppaを登録していれば、 インストールが完了したら 設定が完了したら APCuもOPcacheと同様にモニタリングツールを使うことで動作確認を行うことができます。 一覧にある こちらのファイルも、IPによる制限かパスワードを設定し、WordPressであればWordPressのダウンロード
5.9
)。$ sudo wget https://ja.wordpress.org/wordpress-5.9-ja.tar.gz
で最新のWordPressを圧縮ファイルの状態でダウンロードします。$ tar zxvf wordpress-5.9-ja.tar.gz
でファイルを解凍します。$ cd wordpress
に移動します。$ sudo cp -rp * /var/www/ドメイン名/apps
でwordpress
ディレクトリ内の全てのファイル(ディレクトリ含む)をvar/www/ドメイン名/apps
にパーミッションや所有権(およびタイムスタンプ)をそのままにコピーします。権限の作成
$ sudo chown -R nginx:test /var/www/ドメイン名
により、公開ディレクトリである/var/www/ドメイン名
以降の全ファイルの所有者をnginx
、グループをtest
に変更します。$ sudo find /var/www/ドメイン名 -type f -exec chmod 664 {} \;
を実行することで、/var/www/ドメイン名
内にある全ファイルのパーミッションを664
に変更します。$ sudo find /var/www/ドメイン名 -type f -print | xargs chmod 664
を実行します。664
の代わりに604
を使います。604では所有者(Read,Write)、グループ(none)、その他(Read)となっています。ただし、この場合はFTPユーザが一切何もできなくなります(FTP経由で閲覧も編集できない)。644
を設定するとSFTPユーザでもファイルの閲覧だけは可能となります。604
に設定した方がいい場合もあります。$ sudo find /var/www/ドメイン名 -type d -exec chmod 2775 {} \;
により/var/www/ドメイン名
内の全ディレクトリのパーミッションを2775
に変更します(2775
では以降の新規ディレクトリにグループが継承されます)。$ sudo find /var/www/ドメイン名 -type d -print | xargs chmod 2775
を実行します。775
の代わりに705
を使います。705
では、所有者(Read,Write)、グループ(none)、その他(Read,Write)となっています。この場合もFTPユーザが一切何もできなくなります(FTP経由で閲覧も編集できない)。755
を設定するとSFTPユーザでもファイルの閲覧だけは可能となります。705
に設定した方がいい場合もあります。wp-config設定
$ sudo mv /var/www/ドメイン名/apps/wp-config-sample.php /var/www/ドメイン名/apps/wp-config.php
によりWordPressの設定ファイルを作成します。$ sudo vim /var/www/ドメイン名/apps/wp-config.php
で編集します。wp-config.php
/** 省略 **/
wp-config.conf
/** WordPress のためのデータベース名 */
define('DB_NAME', 'MariaDBで設定したWordPress用のデータベース名');
/** MySQL データベースのユーザー名 */
define('DB_USER', '上記DBに対応するユーザ名');
/** MySQL データベースのパスワード */
define('DB_PASSWORD', '上記ユーザ名に対応するパスワード');
/** MySQL のホスト名 */
define( 'DB_HOST', 'localhost' );
/** データベースのテーブルを作成する際のデータベースの文字セット */
define( 'DB_CHARSET', 'utf8mb4' );
/** 省略 **/
/**#@+
* 認証用ユニークキー
*
* それぞれを異なるユニーク (一意) な文字列に変更してください。
* {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org の秘密鍵サービス} で自動生成すること
もできます。
* 後でいつでも変更して、既存のすべての cookie を無効にできます。これにより、すべてのユーザーを強制的に再ロ
グインさせることになります。
*
* @since 2.6.0
*/
/* 以下は https://api.wordpress.org/secret-key/1.1/salt/ で表示されたフレーズを設定する */
/* 一つ一つ行うのは手間なので、これらはコメントアウトして新規に貼り付けると楽 */
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
/**#@-*/
/**
* WordPress データベーステーブルの接頭辞
*
* それぞれにユニーク (一意) な接頭辞を与えることで一つのデータベースに複数の WordPress を
* インストールすることができます。半角英数字と下線のみを使用してください。
*/
/* デフォルトのwp_ではセキュリティ上よくないので変更する */
/* 記号が交じるとエラーが発生するので注意 */
$table_prefix = '適当な半角英数字を入力_';
/** 省略 **/
wp-config.php
はコア設定であることから、非常に大切なファイルです。そのため、セキュリティを高めておく必要があります。$ sudo chmod 600 /var/www/ドメイン名/apps/wp-config.php
を実行することで所有者以外は読み書きできないようにします(今後編集する予定もない場合は400
に設定)。$ sudo service nginx restart
、$ sudo service mysql restart
、$ sudo service php8.1-fpm restart
でそれぞれのサービスを再起動します。ドメイン名/apps
)にアクセスした時にWordPressの初期設定が表示されます。設定
、パーマリンク
からパーマリンク設定の共通設定
にて基本
『以外』を選択しましょう(404ページが機能しないため)。ドメイン名/apps
限定であることから、 ドメイン名のみで表示を行う設定を行います。$ sudo vim /var/www/ドメイン名/apps/wp-config.php
でもう一度設定ファイルを編集します。wp-config.php
/** 省略 **/
/* カスタム値は、この行と「編集が必要なのはここまでです」の行の間に追加してください。 */
define( 'WP_SITEURL', "https://{$_SERVER['HTTP_HOST']}/apps" );
define( 'WP_HOME', "https://{$_SERVER['HTTP_HOST']}" );
/* 編集が必要なのはここまでです ! WordPress でのパブリッシングをお楽しみください。 */
/** 省略 **/
$ ln -s /var/www/ドメイン名/apps/index.php /var/www/ドメイン名/index.php
を実行することによりapps
ディレクトリ内にあるindex.php
を公開ディレクトリ直下にシンボリックリンクを配置します。$ sudo service nginx restart
でNginxを再起動します。phpMyAdminのインストール
4.9.5
)公式サイトから直接ダウンロードを行います。$ cd /usr/share
に移動します。5.1.2
です。これを/usr/share$ sudo wget https://files.phpmyadmin.net/phpMyAdmin/5.1.2/phpMyAdmin-5.1.2-all-languages.tar.gz
によってダウンロードします。/usr/share$ sudo tar zxvf phpMyAdmin-5.1.2-all-languages.tar.gz
で圧縮ファイルを解凍します。phpmyadmin
に変更するため/usr/share$ sudo mv phpMyAdmin-5.1.2-all-languages phpmyadmin
を実行します。/usr/share$ sudo rm /usr/share/phpMyAdmin-5.1.2-all-languages.tar.gz
で削除します。$ sudo ln -s /usr/share/phpmyadmin /var/www/ドメイン名/apps
でシンボリックリンクを作成します。NginxのlocationでphpMyAdminへのroot(/usr/share/phpmyadmin
)を指定しても良いですが、シンボリックリンクの方が楽に設置できます。http(s)://ドメイン名/apps/phpmyadmin
というURLでアクセスすることができます(WPのデータベースに対するユーザ名とそのパスワード)が、完全に利用可能となったわけではないので、追加の設定を行います。$ sudo chmod -R 775 /usr/share/phpmyadmin
で変更しておきます。$ sudo chown nginx:SFTPユーザ名 -R /usr/share/phpmyadmin/
で所有権も変更します。環境保管領域が完全に設定されていないを解決する
phpMyAdmin 環境保管領域が完全に設定されていないため、いくつかの拡張機能が無効になっています。理由についてはこちらをご覧ください。代わりにデータベースの操作タブを使って設定することもできます。
という文章が表示されている場合があります。$ sudo mysql -u root
でMariaDB(MySQL)にログインします。$ sudo mysql -u root -p
を使います。MariaDB [(none)]> source /usr/share/phpmyadmin/sql/create_tables.sql
を実行してデータベースの作成を行います。MariaDB [(none)]> show databases;
でphpmyadmin
が存在していれば正常です。MariaDB [(none)]> GRANT SELECT, INSERT, UPDATE, DELETE ON phpmyadmin.* TO "DB-NAME"@localhost;
で、DB-NAME
の部分にはWordPressのデータベースに使っているユーザ名を記入します。MariaDB [(none)]> use phpmyadmin
で先程作ったデータベースに切り替えます。MariaDB [(phpmyadmin)]> show tables;
でpma_
という名前のテーブル群が存在することを確認できます。MariaDB [(phpmyadmin)]> select host,user,password from mysql.user;
をそのまま実行してアクセス可能なホストおよびユーザとパスワードをチェックします。MariaDB [(phpmyadmin)]> exit
でMariaDBから離脱します。flush privileges
はINSERT
、UPDATE
、DELETE
の時に必要になるため、その他のコマンドでは不要です。環境保管領域が完全に設定されていない
の文章が消えていれば解決です。暗号化 (blowfish_secret) 用の非公開パスフレーズの設定
config.inc.php
を編集する必要があります。$ openssl rand -hex 32
で32文字(もしくはそれ以上)のランダムな文字列を生成します。$ sudo cp /usr/share/phpmyadmin/config.sample.inc.php /usr/share/phpmyadmin/config.inc.php
でconfig.sample.inc.php
をconfig.inc.php
としてコピーします。$ sudo vim /usr/share/phpmyadmin/config.inc.php
で編集を行います。config.inc.php
/** 省略 **/
/**
* This is needed for cookie based authentication to encrypt password in
* cookie. Needs to be 32 chars long.
**/
$cfg['blowfish_secret'] = 'ここに作成した32文字以上のパスフレーズを入れる'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
/** 省略 **/
phpMyAdminのセキュア設定
ディレクトリ名を変更する
ドメイン名/apps/phpmyadmin
でアクセスすることができます。phpmyadmin
という名前を直接狙った攻撃を受けてしまいます。そのため、名前を変更しなければなりません。$ sudo mv /var/www/ドメイン名/apps/phpMyAdmin /var/www/ドメイン名/apps/$(openssl rand -hex 16)
でphpmyadmin
というディレクトリ名を16文字のランダムな文字列に変更するというものです。$ ls /var/www/ドメイン名/apps
でチェックできます。Basic認証とIP制限を追加する
$ openssl passwd
でBasic認証に使うパスワードを入力します。Verifying - Password:
が出てくるので、同じパスワードを入力します。$ sudo vim /etc/nginx/pma_pass
でBasic認証に使うユーザ名と先程のパスワードの『暗号化された文字列』を入力します。pma_pass
Basic認証に使うユーザ名(自由):暗号化後のパスフレーズ
$ sudo vim /etc/nginx/conf.d/ドメイン名.conf
でNginxの設定を行います。allow
およびdeny all
でのIP制限も行うことができます。接続の許可するIPをallow
し、その他のIPはdeny all
で全て排除します。これによりセキュリティが更に向上します。ドメイン名.conf
## 省略 ##
# "/名前"もしくは"/名前/"を含んだURL
location ~ /名前を変更したphpMyAdminの名前(?:$|/) {
# 閲覧許可するIPを入力する
# allow 許可するIPアドレスを入力;
# 許可していないIPはすべて排除
# deny all;
# 左から順に参照し、該当が無ければ最後のuri(もしくはcode)に内部転送される
try_files $uri $uri/ /index.php?$args;
# Basic認証を設定
auth_basic "login";
# Basic認証のユーザファイルを指定
auth_basic_user_file /etc/nginx/pma_pass;
location ~ \.php$ {
# 左から順に参照し、該当が無ければ最後のuri(もしくはcode)に内部転送される
try_files $uri $uri/ /index.php?$args;
# PHPに渡すパラメータファイルを指定
include fastcgi_params;
# FASTCGIサーバーへのキープアライブ接続をON
fastcgi_keep_conn on;
# スラッシュで終わるURIの後にFASTCGIが要求するファイル名
fastcgi_index index.php;
# fastcgi_path_info変数の値をキャプチャする正規表現の定義
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# FastCGIサーバーに渡すパラメータを指定
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# コード300以上のレスポンスをerror_pageディレクティブで処理
fastcgi_intercept_errors on;
# FastCGIサーバーのアドレスをUnixドメインソケットのパスに指定
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
}
## 省略 ##
$ sudo service nginx restart
でNginxを再起動します。WEBサーバとDBサーバに分ける(予備)
エクスポート方法
は詳細
を選び、生成オプション
にはDROP TABLE / VIEW / PROCEDURE / FUNCTION / EVENT / TRIGGER コマンドを追加する
にチェックを入れます。圧縮
でgzip方式
を選べばサイズを縮小して保存できます。プライベートネットワークで接続する
$ ping 相手サーバのプライベートIPアドレス
をお互いに行い、どちらも0% packetloss
となるポイントまで進めます。データベース接続設定
$ sudo mysql -u root
を実行してデータベースにログインします。$ sudo mysql -u root -p
を実行します。MariaDB [(none)]> GRANT ALL PRIVILEGES ON `DB-NAME`.* TO "USER-NAME"@"WEB-SERVER-PRIVATE-IP" IDENTIFIED BY "DB-PASS";
でデータベースを作成します。DB-NAME
の部分は使用するWordPressのデータベース名を入力します(例ではexample.com
などのドメイン名)。USER-NAME
の箇所には新規ユーザ名を記入します(例ではここもドメイン名)。WEB-SERVER-PRIVATE-IP
の部分はウェブサーバのプライベートIPアドレスに変更します。DB-PASS
にはUSER-NAME
に対応するDBログイン用パスワードを新規に設定します。WITH GRANT OPTION
(アクセス権の継承)を追加しているケースがよく見られますが、権限管理を簡潔にするため、ここでは付与していません。MariaDB [(none)]> select user, host from mysql.user;
でアクセス可能なホストおよびユーザをチェックします。MariaDB [(none)]> exit
でデータベースから離脱します。flush privileges
は必要ありません。$ sudo ufw allow in proto tcp from ウェブサーバのプライベートIPアドレス to any port 3306
を実行し、ウェブサーバがDBサーバのデータベースに接続できるように、UFW(ファイアウォール)の設定を行います。$ sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf
を編集します。50-server.cnf
## 省略 ##
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
# bind-addressをコメントアウトする
# bind-address = 127.0.0.1
## 省略 ##
$ sudo service mysql restart
でMariaDBを再起動します。$ sudo mysql -u 作成したDBに対応するユーザ名 -h DBサーバプライベートIPアドレス -p
を実行してDBサーバのデータベースにアクセスします。$ sudo mysql -u root
でMariaDBにログインしたあと、MariaDB [(none)]> source /usr/share/phpmyadmin/sql/create_tables.sql
を使ってphpmyadminのテーブルを作成します。MariaDB [(none)]> GRANT SELECT, INSERT, UPDATE, DELETE ON phpmyadmin.* TO `USER-NAME`@'WEB-SERVER-PRIVATE-IP';
で、USER-NAME
はWPのデータベースを使用しているユーザ名、WEB-SERVER-PRIVATE-IP
にはウェブサーバのプライベートIPアドレスを入力します。MariaDB [(none)]> exit
で離脱し、$ sudo vim /usr/share/phpmyadmin/config.inc.php
でconfig.inc.php
を編集します。config.inc.php
が存在しない場合は$ sudo cp /usr/share/phpmyadmin/config.sample.inc.php /usr/share/phpmyadmin/config.inc.php
でconfig.sample.inc.php
をconfig.inc.php
としてコピーします。config.inc.php
/** 省略 **/
/**
* First server
*/
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'ウェブサーバのプライベートIPアドレス;
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
/** 省略 **/
host
をウェブサーバのプライベートIPアドレスに変更することで、ウェブサーバからphpMyAdminを編集することができます。$ sudo vim /var/www/ドメイン名/wp-config.php
によって、wp-config.php
を編集します。wp-config.php
// ** MySQL 設定 - この情報はホスティング先から入手してください。 ** //
/** WordPress のためのデータベース名 */
define('DB_NAME', 'MariaDBで設定したWordPress用のデータベース名');
/** MySQL データベースのユーザー名 */
define('DB_USER', '上記DBに対応するユーザ名');
/** MySQL データベースのパスワード */
define('DB_PASSWORD', '上記ユーザ名に対応するパスワード');
/** MySQL のホスト名 */
define( 'DB_HOST', 'DBサーバのプライベートIPアドレス' );
/** データベースのテーブルを作成する際のデータベースの文字セット */
define( 'DB_CHARSET', 'utf8mb4' );
/** 省略 **/
/**#@+
* 認証用ユニークキー
*
* それぞれを異なるユニーク (一意) な文字列に変更してください。
* {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org の秘密鍵サービス} で自動生成すること
もできます。
* 後でいつでも変更して、既存のすべての cookie を無効にできます。これにより、すべてのユーザーを強制的に再ロ
グインさせることになります。
*
* @since 2.6.0
*/
/* 以下は https://api.wordpress.org/secret-key/1.1/salt/ で表示されたフレーズを設定する */
/* 一つ一つ行うのは手間なので、これらはコメントアウトして新規に貼り付けると楽 */
define( 'AUTH_KEY', 'put your unique phrase here' );
define( 'SECURE_AUTH_KEY', 'put your unique phrase here' );
define( 'LOGGED_IN_KEY', 'put your unique phrase here' );
define( 'NONCE_KEY', 'put your unique phrase here' );
define( 'AUTH_SALT', 'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT', 'put your unique phrase here' );
define( 'NONCE_SALT', 'put your unique phrase here' );
/**#@-*/
/**
* WordPress データベーステーブルの接頭辞
*
* それぞれにユニーク (一意) な接頭辞を与えることで一つのデータベースに複数の WordPress を
* インストールすることができます。半角英数字と下線のみを使用してください。
*/
/* デフォルトのwp_ではセキュリティ上よくないので変更する */
/* 記号が交じるとエラーが発生するので注意 */
$table_prefix = '適当な半角英数字を入力_';
/** 省略 **/
WordPress高速化設定
FastCGI Cacheの導入
$ sudo vim /etc/nginx/nginx.conf
でNginxのコア設定を編集します。内容はリバースプロキシの時とやや類似しています。nginx.conf
## 省略 ##
### httpディレクティブ内に記述する ###
# FastCGI Cache Settings
# プロキシキャッシュのパスを指定し、階層レベルを1:2
# キャッシュゾーン名をwp_cache、そのゾーンのメモリ使用を1MB、全キャッシュの最大量を1GB
# アクセスが1日無ければ該当キャッシュを削除
fastcgi_cache_path /var/cache/nginx/fastcgi-cache levels=1:2 keys_zone=wp_cache:1m max_size=1g inactive=1d;
# キャッシュ時に使用するキーを設定
# 今回の例ではモバイルとPCでキャッシュを分けるための設定を加えている($mobile_)
fastcgi_cache_key "$mobile_$scheme$request_method$host$request_uri";
# キャッシュを効かせるために特定のリクエストヘッダを無効にする
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
# /FastCGI Cache Settings
## 省略 ##
$ sudo vim /etc/nginx/conf.d/ドメイン名.conf
でも編集します。## 省略 ##
### メインのServerディレクティブ内に記述する ###
# FASTCGI CACHE SETTINGS
# レスポンスを読み取るために使用されるバッファの数とサイズ
fastcgi_buffers 4 256k;
# 受信したレスポンスの最初の部分を読み取るために使用されるバッファサイズ
fastcgi_buffer_size 128k;
# レスポンスがビジー(応答待ち)時の最大バッファサイズ
fastcgi_busy_buffers_size 256k;
# バッファリング時の一時ファイル書き込み最大サイズ
fastcgi_temp_file_write_size 256k;
# キャッシュを返送しないパラメータを指定
fastcgi_cache_bypass $skip_cache;
# キャッシュしないパラメータを指定
fastcgi_no_cache $skip_cache;
# キャッシュのゾーン名を指定
fastcgi_cache wp_cache;
# ステータスごとの最大キャッシュ時間(1日、1時間、5分)
fastcgi_cache_valid 200 302 1d;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 5m;
# 同一のリクエストが同時に要求された場合、各リクエストを一つにまとめる
fastcgi_cache_lock on;
# fastcgi_cache_lockのタイムアウト時間。指定した時間以上経過でキャッシュせずに返却
fastcgi_cache_lock_timeout 5s;
# 指定したパラメータが発生した際に古いキャッシュを使用
fastcgi_cache_use_stale error timeout invalid_header updating http_500;
# 設定したリクエストヘッダを付与(X-Cache)
# $upstream_cache_statusはキャッシュの状態を表している
# MISS(キャッシュ無し)、HIT(キャッシュ使用)、BYPASS(キャッシュを返送しない)
add_header X-Cache $upstream_cache_status;
# ユーザーエージェント(利用者の使用プログラム)によって変化するVaryヘッダを付与
# PCとモバイルで分けている場合に使用する
add_header Vary "User-Agent";
# $skip_cacheの初期値を"0"に設定し、初期状態でFastCGI Cacheを有効化
set $skip_cache 0;
# モバイルでアクセスした際のキャッシュ設定を追加する
set $mobile_ "";
if ($http_x_wap_profile ~ "^[a-z0-9\"]+") {
set $mobile_ "mobile.";
}
if ($http_profile ~ "^[a-z0-9\"]+") {
set $mobile_ "mobile.";
}
if ($http_user_agent ~ "^.*(?:2\.0\ MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3\.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2\.0|MMEF20|MOT-V|NetFront|Newt|Nintendo\ Wii|Nitro|Nokia|Opera\ Mini|Palm|PlayStation\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\ OS|SymbianOS|TS21i-10|UP\.Browser|UP\.Link|webOS|Windows\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\ Obigo|LGE\ VX|webOS|Nokia5800).*") {
set $mobile_ "mobile.";
}
if ($http_user_agent ~ "^(?:w3c\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\ |xda-).*") {
set $mobile_ "mobile.";
}
if ($http_user_agent ~ "^(?:DoCoMo/|J-PHONE/|J-EMULATOR/|Vodafone/|MOT(EMULATOR)?-|SoftBank/|[VS]emulator/|KDDI-|UP\.Browser/|emobile/|Huawei/|IAC/|Nokia|mixi-mobile-converter/)") {
set $mobile_ "mobile.";
}
if ($http_user_agent ~ "DDIPOCKET\;|WILLCOM\;|Opera\ Mini|Opera\ Mobi|PalmOS|Windows\ CE\;|PDA\;\ SL-|PlayStation\ Portable\;|SONY/COM|Nitro|Nintendo") {
set $mobile_ "mobile.";
}
# GETリクエスト以外はFastCGI Cacheを使わない
if ($request_method != "GET") {
set $skip_cache 1;
}
# クエリ文字列を含む場合はFastCGI Cacheを使わない
if ($query_string != "") {
set $skip_cache 1;
}
# WordPressでのログイン中やコメント直後、投稿がパスワード保護されている場合にはFastCGI Cacheを使わない
if ($http_cookie ~ "wordpress_logged_in_|comment_author_|wp-postpass") {
set $skip_cache 1;
}
# WordPress関連のファイルではFastCGI Cacheを使わない
if ($request_uri ~ "/(?:wp-json(?:$|/)|wp-admin(?:$|/)|xmlrpc\.php|wp-(?:app|cron|login|register|mail)\.php|wp-.*\.php|(?:feed|rss2?|rdf|atom)(?:$|/)|index\.php|wp-comments-popup\.php|wp-links-opml\.php|wp-locations\.php|sitemap(_index)?\.xml|[a-z0-9_-]+-sitemap([0-9]+)?\.xml)") {
set $skip_cache 1;
}
## 省略 ##
$ sudo service nginx restart
でNginxを再起動します。FastCGI Cacheの命名規則
fastcgi_cache_key
の設定に基づいています。fastcgi_cache_key "$scheme$request_method$host$request_uri";
に設定している場合、https://example.com/test.php
というURLをキャッシュした場合にはfastcgi_cache_key "httpsGETexample.com/test.php";
といった形になります。httpsGETexample.com/test.php
です。$scheme
はhttp
やhttps
、ftp
などを出力し、$request_method
はGET
やPOST
等のリクエストを表し、$host
はIPやドメイン名、そして$request_uri
はホスト名以降のパスやクエリを意味します。httpsGETexample.com/test.php
であれば、MD5ハッシュとして3783e700451e905dba61c1fb80a74a65
が表示されます。fastcgi_cache_path /var/cache/nginx/fastcgi-cache levels=1:2
という設定ではlevels=1:2
が指定されており、これは最大2階層のディレクトリにそれぞれキャッシュのMD5ハッシュの一部が付与されます。1:2
であることから、ディレクトリの第1階層にはキャッシュに対応するMD5ハッシュのうち、最後の1文字が付与されます。/var/cache/nginx/fastcgi-cache/5/a6/3783e700451e905dba61c1fb80a74a65
FastCGI Cacheの削除設定
function.php
内に書き込む方法、もう1つが外部PHPファイルを新規に作成し、それを直接実行する方法、そして3つ目がプラグインのNginx Helper
を使う方法です。functions.phpを用いたキャッシュ削除
functions.php
での方法を紹介します。functions.php
// 記事編集時、自動でFastCGIキャッシュを削除
// How to Setup FastCGI Caching with Nginx on your VPS
// https://www.digitalocean.com/community/tutorials/how-to-setup-fastcgi-caching-with-nginx-on-your-vps
// 28日目:nginx+FastCGIでRCCのサイトを高速化!
// http://www.rcc.ritsumei.ac.jp/2019/1228_10813/
function nginx_cache_purge($post_id){
// 更新した記事のURLを取得
$post_link = get_permalink($post_id);
// FastCGI Cacheのpathを指定
// pathの最後に"/"を付けること
$cache_path = "/var/cache/nginx/fastcgi-cache/";
// ウェブサイトがhttpかhttpsか
$scheme = "https";
// ウェブサイトのホスト名
$host = "example.com";
// 置換でパーマリンクのみを残す
$replace = str_replace($scheme . "://" . $host, '', $post_link);
// MD5でハッシュ化(トップページ用)
$hash_top = md5($scheme . "GET" . $host . "/");
// MD5でハッシュ化(トップページモバイル用)
$hash_top_m = md5("mobile." . $scheme . "GET" . $host . "/");
// MD5でハッシュ化(記事ページ用)
$hash_page = md5($scheme . "GET" . $host . $replace);
// MD5でハッシュ化(記事ページモバイル用)
$hash_page_m = md5("mobile." . $scheme . "GET" . $host . $replace);
// トップページのキャッシュを削除
array_map('unlink', glob($cache_path . substr($hash_top, -1) ."/". substr($hash_top,-3,2) ."/". $hash_top));
// トップページのキャッシュを削除(モバイル版のキャッシュ)
array_map('unlink', glob($cache_path . substr($hash_top_m, -1) ."/". substr($hash_top_m,-3,2) ."/". $hash_top_m));
// 更新した記事のキャッシュを削除
array_map('unlink', glob($cache_path . substr($hash_page, -1) ."/". substr($hash_page,-3,2) ."/". $hash_page));
// 更新した記事のキャッシュを削除(モバイル版のキャッシュ)
array_map('unlink', glob($cache_path . substr($hash_page_m, -1) ."/". substr($hash_page_m,-3,2) ."/". $hash_page_m));
}
/* 新規投稿、更新等のステータス変更で削除処理が発動 */
add_action( 'new_to_publish', 'nginx_cache_purge' );
add_action( 'publish_to_publish', 'nginx_cache_purge' );
add_action( 'pending_to_publish', 'nginx_cache_purge' );
add_action( 'draft_to_publish', 'nginx_cache_purge' );
add_action( 'auto-draft_to_publish', 'nginx_cache_purge' );
add_action( 'future_to_publish', 'nginx_cache_purge' );
add_action( 'publish_to_trash', 'nginx_cache_purge' );
add_action( 'post_updated' , 'nginx_cache_purge');
add_action( 'edit_post' , 'nginx_cache_purge');
外部PHPファイルでキャッシュ削除
purge-cache.php
(名前は自由)という以下のような内容のファイルを作成し、/purge-cache.php
にアクセスすればすべてのFastCGI Cacheを手動で全削除することができます。purge-cache.php
<?php
$allow_ips = [
// ログイン画面にアクセスを許可するIPアドレスを定義(未定義の場合は全ての接続元を許可する)
// cf. '123.123.123.123', ...
];
// WordPressの機能を使うために"wp-load.php"を読み込む
require_once dirname( __FILE__ ) . '/wp-load.php';
// IP制限していない、もしくは許可されたIPの場合
if ( empty( $allow_ips ) || ( ! empty( $allow_ips ) && in_array( $_SERVER['REMOTE_ADDR'], $allow_ips, true ) ) ) {
// キャッシュをディレクトリ含め全削除する
array_map('unlink', glob("/var/cache/nginx/fastcgi-cache/*/*/*"));
array_map('rmdir', glob("/var/cache/nginx/fastcgi-cache/*/*"));
array_map('rmdir', glob("/var/cache/nginx/fastcgi-cache/*"));
// WordPress管理ページのURLを取得
$url = get_admin_url();
// WordPress管理ページへリダイレクトする
header('Location: ' . $url, true, 302);
} else {
// アクセスを拒否された場合
// ステータスコードを404に変更する
status_header( '404' );
// テンプレート内の404ページにリダイレクトする
include( get_query_template( '404' ) );
// 処理を停止する
exit();
}
functions.php
にキャッシュ削除用のAdminBarMenuボタンを追加することで、ワンクリックで全削除が可能になります。functions.php
// 上部AdminBarMenuにキャッシュ削除用ボタンを追加
function add_admin_bar_menu($wp_admin_bar){
// ユーザ削除権限を持ったユーザのみ、キャッシュ削除ボタンを表示
if (current_user_can('delete_users')){
$wp_admin_bar->add_node( array(
'id' => 'delete_cache',
'title' => 'FastCGI Cacheを全削除する',
'href' => '/apps/purge-cache.php',
));
}
}
// "99"と多めに設定することでAdminBarリストの後半にボタンを表示させる
add_action( 'admin_bar_menu', 'add_admin_bar_menu', 99 );
$ sudo vim /etc/nginx/conf.d/ドメイン名.conf
で編集を行います。ドメイン名.conf
## 省略 ##
# 設置する位置によっては"$skip_cache"が上書きされてしまうので注意
# キャッシュ削除用ファイルにはFastCGI Cacheを使わない
if ($request_uri ~ "/purge-cache\.php$") {
set $skip_cache 1;
}
## 省略 ##
$ sudo service nginx restart
で再起動します。cli-purge-cache.php
<?php
$allow_ips = [
// ログイン画面にアクセスを許可するIPアドレスを定義(未定義の場合は全ての接続元を許可する)
// cf. '123.123.123.123', ...
];
// IP制限していない、もしくは許可されたIPの場合
if ( empty( $allow_ips ) || ( ! empty( $allow_ips ) && in_array( $_SERVER['REMOTE_ADDR'], $allow_ips, true ) ) ) {
// FastCGI Cacheの保管場所を指定
$cache_path = '/var/cache/nginx/fastcgi-cache/';
// URLの解析
$url = parse_url($_POST['url']);
// URLではない場合
if(!$url)
{
echo 'Invalid URL entered';
die();
}
// 解析したURLのschemeを取得
$scheme = $url['scheme'];
// 解析したURLのホスト名を取得
$host = $url['host'];
// 解析したしたURLのリクエストURIを取得
$requesturi = $url['path'];
// 取得した情報を使い、MD5でハッシュ化する
$hash = md5($scheme.'GET'.$host.$requesturi);
// 指定したURLのキャッシュを削除する
var_dump(unlink($cache_path . substr($hash, -1) . '/' . substr($hash,-3,2) . '/' . $hash));
} else {
// アクセスを拒否された場合
// ステータスコードを404に変更する
status_header( '404' );
// テンプレート内の404ページにリダイレクトする
include( get_query_template( '404' ) );
// 処理を停止する
exit();
}
$ curl -d 'url=http://www.example.com/test.php' https://ホスト名/cli-purge-cache.php
のようにキャッシュ削除したいURLと削除用PHPファイル(cli-purge-cache.php
)を含んだコマンドを実行することで、個別にキャッシュを削除することができます。cli-purge-cache.php
はキャッシュの削除有無でtrue
(削除完了)またはfalse
(削除不可)を出力します。Nginx Helper
Nginx Helper
では、比較的簡単にFastCGI Cacheの管理を行うことができます。Settings
で管理ページに移動し、Purging Options
でEnable Purge
を選択します。Caching Method
ではnginx Fastcgi cache (requires external settings for nginx)
を選択します。Purge Method
ではDelete local server cache files
を選びます。ngx_cache_purge
モジュールを導入している場合はUsing a GET request to PURGE/url (Default option)
を選んでください。ngx_cache_purge
モジュールを使用していない場合はwp-config.php
にFastCGI Cacheを保存している場所を指定しなければなりません。wp-config.php
/** 省略 **/
/** NGINX HELPER **/
define( 'RT_WP_NGINX_HELPER_CACHE_PATH', '/var/cache/nginx/fastcgi-cache');
/** 省略 **/
$ sudo service php8.1-fpm restart
でPHP-FPMを再起動させます。nginx-helper/admin/class-fastcgi-purger.php
です。この中に一行だけコード($this->delete_cache_file_for( 'mobile.' . $_url_purge );
)を追記します。ctrl+f
を使って$this->delete_cache_file_for( $_url_purge );
を検索するとヒットします。class-fastcgi-purger.php
/** 省略 **/
// モバイルキャッシュの削除を追加
$this->delete_cache_file_for( 'mobile.' . $_url_purge );
$this->delete_cache_file_for( $_url_purge );
if ( $feed ) {
$feed_url = rtrim( $_url_purge_base, '/' ) . '/feed/';
$this->delete_cache_file_for( $feed_url );
$this->delete_cache_file_for( $feed_url . 'atom/' );
$this->delete_cache_file_for( $feed_url . 'rdf/' );
}
break;
/** 省略 **/
PHP-FPMのチューニング
$ sudo vim /etc/php/8.1/fpm/pool.d/www.conf
で複数の項目を編集します。www.conf
[www]
;; 省略 ;;
; プロセスマネージャが子プロセスの数を制御する方法(static,dynamic,ondemand)
; "static"では"pm.max_children"に指定したプロセス数のみが起動する
; "dynamic"では、"pm.max_children"で最大プロセス数を指定しつつ、関連する他の設定でも制御される
; "ondemand"は必要に応じてプロセスが起動。リクエスト時に"pm.start_servers"設定数のプロセスが起動する
; プロセス起動のオーバーヘッドを最小限に抑える場合は"static"(CPU性能が低い場合に向いている)
; 通常時のメモリ消費量を抑えつつ柔軟に処理を行いたい場合は"dynamic"(高スペック向け)
;
pm = static
; 子プロセスの(最大)数。サーバに対して割り当てが大きすぎるとメモリが枯渇して実行が遅延する
; 割り当ての算出には サーバの使用可能メモリ量 / プロセスの平均メモリ使用量 を使う
; もしくは サーバの使用可能メモリ量 / PHPのmemory_limit(php.ini内)
; 例:使用可能メモリ量が1GB、Memory limitが128MBの場合、"1000/128 = 3.90625" 四捨五入して4を採用
; 使用可能メモリ量の確認は"$ free -h"コマンドを使い、"available"をチェックする
; ただし、CPUの論理コア数が少ない場合はCPUがボトルネックになるため、その場合はCPUコア数を指定する
pm.max_children = 4
; PHP-FPM開始時に起動する子プロセスの数
; pm = dynamic にのみ使用される
; 割り当ての算出には"pm.max_children"設定数の25%を使う
; 例:pm.max_childrenが4の場合、"4 * 0.25 = 1"
pm.start_servers = 1
; アイドル状態の子プロセス最小起動数
; pm = dynamic にのみ使用される
; 割り当ての算出には"pm.max_children"設定数の25%を使う
; 例:pm.max_childrenが4の場合、"4 * 0.25 = 1"
pm.min_spare_servers = 1
; アイドル状態の子プロセス最大起動数
; pm = dynamic にのみ使用される
; アイドル状態になると指定した数のプロセスになるまで減少する
; 割り当ての算出には"pm.max_children"設定数の75%を使う
; 例:pm.max_childrenが4の場合、"4 * 0.75 = 3"
pm.max_spare_servers = 3
; それぞれの子プロセスが再起動を行うリクエスト数
; 設定すると子プロセスのメモリが肥大化することを回避する
; 再起動させない場合は0を指定
; 1日に1回再起動させる場合、"1日の平均リクエスト数 / pm.max_children" で算出する(static)
; 1日の平均リクエスト数 / pm.max_spare_servers(dynamic)
; 例:pm=staticで1日1000pv、pm.max.childrenが4の場合、"1000 / 4 = 250"
pm.max_requests = 250
;; 省略 ;;
$ sudo vim /etc/php/8.1/fpm/php.ini
でmemory_limit
を編集する必要があります。php.ini
; Maximum amount of memory a script may consume
; https://php.net/memory-limit
; PHPのスクリプトが確保できる全体の最大メモリ量
; とにかく大きくすれば良いものではなく(最大制限をかける理由はメモリを食いつぶすことの防止)
; 少なすぎても多すぎても良くないため、必要に応じて調整することが重要
memory_limit = 128M
MariaDBのチューニング
MySQLTuner
という非常に便利な補助ツールが存在しているため、ありがたく使わせていただきましょう。Version 1.8.3
です。$ sudo wget https://github.com/major/MySQLTuner-perl/archive/refs/tags/1.8.3.tar.gz
最新版のMySQLTuner-perlをダウンロードします。$ tar zxvf 1.8.3.tar.gz
でファイルを解凍します。$ cd MySQLTuner-perl-1.8.3
でMySQLTunerのディレクトリに移動します。~/MySQLTuner-perl-1.8.3$ perl ./mysqltuner.pl
を実行すると、管理者権限のユーザ名とパスワードを要求されるため、それを入力すればMariaDB(MySQL)の診断が開始されます。 >> MySQLTuner 1.8.3 - Major Hayden <major@mhtx.net>
>> Bug reports, feature requests, and downloads at http://mysqltuner.pl/
>> Run with '--help' for additional options and output filtering
[--] Skipped version check for MySQLTuner script
## MariaDB(MySQL)の管理者権限ユーザ名を入力(例ではroot)
Please enter your MySQL administrative login:root
## 上記にユーザに対応するパスワードを入力
Please enter your MySQL administrative password:パスワード
[OK] Operating on 64-bit architecture
-------- Log file Recommendations ------------------------------------------------------------------
[!!] Log file doesn't exist
-------- Storage Engine Statistics -----------------------------------------------------------------
[--] Status: +Aria +CSV +InnoDB +MEMORY +MRG_MyISAM +MyISAM +PERFORMANCE_SCHEMA +SEQUENCE
[--] Data in Aria tables: 32.0K (Tables: 1)
[--] Data in InnoDB tables: 2.1M (Tables: 31)
[OK] Total fragmented tables: 0
-------- Analysis Performance Metrics --------------------------------------------------------------
[--] innodb_stats_on_metadata: OFF
[OK] No stat updates during querying INFORMATION_SCHEMA.
-------- Security Recommendations ------------------------------------------------------------------
[OK] There are no anonymous accounts for any database users
[OK] All database users have passwords assigned
[--] There are 620 basic passwords in the list.
-------- CVE Security Recommendations --------------------------------------------------------------
[OK] NO SECURITY CVE FOUND FOR YOUR VERSION
-------- Performance Metrics -----------------------------------------------------------------------
[--] Up for: 2d 0h 1m 14s (70K q [0.407 qps], 4K conn, TX: 166M, RX: 10M)
[--] Reads / Writes: 92% / 8%
[--] Binary logging is disabled
[--] Physical Memory : 976.8M
[--] Max MySQL memory : 3.2G
[--] Other process memory: 0B
[--] Total buffers: 417.0M global + 18.9M per thread (151 max threads)
[--] P_S Max memory usage: 0B
[--] Galera GCache Max memory usage: 0B
[OK] Maximum reached memory usage: 473.7M (48.50% of installed RAM)
[!!] Maximum possible memory usage: 3.2G (335.02% of installed RAM)
[!!] Overall possible memory usage with other process exceeded memory
[OK] Slow queries: 0% (0/70K)
[OK] Highest usage of available connections: 1% (3/151)
[OK] Aborted connections: 0.31% (14/4482)
[OK] Query cache is disabled by default due to mutex contention on multiprocessor machines.
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 5K sorts)
[OK] No joins without indexes
[!!] Temporary tables created on disk: 64% (2K on disk / 3K total)
[OK] Thread cache hit rate: 99% (33 created / 4K connections)
[OK] Table cache hit rate: 95% (59K hits / 62K requests)
[OK] table_definition_cache(400) is upper than number of tables(323)
[OK] Open file limit used: 0% (59/32K)
[OK] Table locks acquired immediately: 100% (1K immediate / 1K locks)
-------- Performance schema ------------------------------------------------------------------------
[--] Performance schema is disabled.
[--] Memory used by P_S: 0B
[--] Sys schema is installed.
-------- ThreadPool Metrics ------------------------------------------------------------------------
[--] ThreadPool stat is enabled.
[--] Thread Pool Size: 1 thread(s).
[--] Using default value is good enough for your version (10.6.5-MariaDB-1:10.6.5+maria~focal)
-------- MyISAM Metrics ----------------------------------------------------------------------------
[!!] Key buffer used: 18.2% (24M used / 134M cache)
[OK] Key buffer size / total MyISAM indexes: 128.0M/0B
-------- InnoDB Metrics ----------------------------------------------------------------------------
[--] InnoDB is enabled.
[OK] InnoDB File per table is activated
[OK] InnoDB buffer pool / data size: 128.0M/2.1M
[!!] Ratio InnoDB log file size / InnoDB Buffer pool size (75 %): 96.0M * 1/128.0M should be equal to 25%
[--] Number of InnoDB Buffer Pool Chunk : 1 for 1 Buffer Pool Instance(s)
[OK] Innodb_buffer_pool_size aligned with Innodb_buffer_pool_chunk_size & Innodb_buffer_pool_instances
[OK] InnoDB Read buffer efficiency: 99.96% (1040206 hits/ 1040673 total)
[!!] InnoDB Write Log efficiency: 872.5% (4441 hits/ 509 total)
[OK] InnoDB log waits: 0.00% (0 waits / 4950 writes)
-------- Aria Metrics ------------------------------------------------------------------------------
[--] Aria Storage Engine is enabled.
[OK] Aria pagecache size / total Aria indexes: 128.0M/352.0K
[!!] Aria pagecache hit rate: 87.7% (15K cached / 1K reads)
-------- TokuDB Metrics ----------------------------------------------------------------------------
[--] TokuDB is disabled.
-------- XtraDB Metrics ----------------------------------------------------------------------------
[--] XtraDB is disabled.
-------- Galera Metrics ----------------------------------------------------------------------------
[--] Galera is disabled.
-------- Replication Metrics -----------------------------------------------------------------------
[--] Galera Synchronous replication: NO
[--] No replication slave(s) for this server.
[--] Binlog format: MIXED
[--] XA support enabled: ON
[--] Semi synchronous replication Master: OFF
[--] Semi synchronous replication Slave: OFF
[--] This is a standalone server
-------- Recommendations ---------------------------------------------------------------------------
General recommendations:
Reduce your overall MySQL memory footprint for system stability
Dedicate this server to your database for highest performance.
Configure your accounts with ip or subnets only, then update your configuration with skip-name-resolve=1
When making adjustments, make tmp_table_size/max_heap_table_size equal
Reduce your SELECT DISTINCT queries which have no LIMIT clause
Performance schema should be activated for better diagnostics
Before changing innodb_log_file_size and/or innodb_log_files_in_group read this: https://bit.ly/2TcGgtU
Variables to adjust:
*** MySQL's maximum memory usage is dangerously high ***
*** Add RAM before increasing MySQL buffer variables ***
tmp_table_size (> 16M)
max_heap_table_size (> 16M)
performance_schema = ON enable PFS
innodb_log_file_size should be (=32M) if possible, so InnoDB total log files size equals to 25% of buffer pool size.
innodb_log_file_size
はinnodb_buffer_pool_size
の25%くらいに割り当てる$ sudo vim /etc/mysql/my.cnf
でMariaDBの設定ファイルを編集します。my.cnf
[mysqld]
#
# * Log
#
# エラーログの場所を指定
log_error = /var/log/mysql/error.log
# ログ出力に中止した接続等を含めない
log_warnings = 1
# バイナリログの場所を指定
log_bin = /var/log/mysql/mysql-bin
# バイナリログの基準となるサイズ
max_binlog_size = 100M
# バイナリログの保存日数
expire_logs_days = 10
# バイナリログにSTATEMENTとROWを混在させる
binlog_format = MIXED
# slow_queryの出力設定("1"で出力する)
slow_query_log = 1
# slow_queryと判定する秒数
long_query_time = 3
# slow_queryログの場所
slow_query_log_file = /var/log/mysql/slow-queries.log
#
# * Fine Tuning
#
# MariaDBが受け付けるクライアントの最大接続数
# 数値が高いほど潜在的に消費するメモリが多くなる(1000だと潜在的にメモリが3GBほど必要)
max_connections = 30
# スレッドをコネクションの切断後にもキャッシュしておく数
# "max_connections / 3"で算出する
thread_cache_size = 10
# ソートを実行する各セッションに対して指定した数値を割り当て
sort_buffer_size = 1M
# 挿入の際に使用される各スレッドのキャッシュツリーのサイズ
bulk_insert_buffer_size = 32M
# 全てのスレッドでオープンするテーブルの数
# max_connectionsの2倍程度で開始、数時間経過後に"Open_tables"と"Opened_tables"の実行結果で調整する
# MariaDB [(none)]> show global status like 'Open_tables';
# MariaDB [(none)]> show global status like 'Opened_tables';
# Open_tablesの数が"table_open_cache"に届かない数値の場合は減らすことを検討できる
# また、Opened_tablesの数が急速に増加している場合は"table_open_cache"を増やすことを検討できる
table_open_cache = 1000
#
# * MyISAM
#
# キーをキャッシュする際に使用されるバッファのサイズ
# MyISAM自体ほとんど使わないので少なめに
key_buffer_size = 512K
#
# * Query Cache Configuration
#
# クエリキャッシュは更新頻度の高いサイトでは恩恵が少ない
# つまり読み取りが多く書き込みが少ないサイトでは効果が高い
# 時間経過によるキャッシュヒット率を確認しつつ細かい調整が必要
# なお、MySQLではバージョン8.0から廃止されており、使用は推奨されていない
# クエリキャッシュに使用する最大値
query_cache_size = 0
# 指定したサイズを超えたものはキャッシュを行わない
query_cache_limit = 0
# クエリキャッシュのタイプ(0:off, 1:ONでSELECT SQL_NO_CACHE以外, 2:DEMAND SELECT SQL_CACHEのみ)
query_cache_type = 0
#
# * InnoDB
#
# InnoDBのバッファプールサイズ
# ここの数値がデータベースの速度に大きく影響するので重要
# 基本的に全メモリの50%~80%程を割り当てる
innodb_buffer_pool_size = 512M
# InnoDBの更新ログのサイズ
# "innodb_buffer_pool_size"の25%を割り当てる
innodb_log_file_size = 128M
# InnoDBの更新ログに使用するバッファサイズ
innodb_log_buffer_size = 32M
# InnoDBのバッククラウンド作業時に使用するI/Oサイズ
innodb_io_capacity = 1000
# innodb_io_capacityの最大サイズ
innodb_io_capacity_max = 2000
# データファイルの二重書き込み(耐障害性のため)有無
# 無効(0)にするとわずかにパフォーマンスが向上するが、障害時に該当データを修復できない
innodb_doublewrite = 0
# バッファプールをフラッシュ(ディスク書き込み)後、同グループのdirtyページ
# (ログ等には存在するがテーブルに存在しないデータ)もフラッシュする
# 作業にはメモリの増加やI/Oアクセスが増大することから、無効(0)にする
innodb_flush_neighbors = 0
# ログバッファの書き込み制御
# ログバッファはコミットするたびにInnoDB REDOログに書き込まれる
# "0"ではコミット時に何も行わないのでパフォーマンスが向上する
# "2"ではフラッシュは1秒に1回なのでわずかにパフォーマンスが増加する
# "0"と"2"はサーバ全体がクラッシュするとデータ損失の可能性あり
innodb_flush_log_at_trx_commit = 2
# InnoDBテーブルのAUTO_INCREMENT値を生成するときに使用されるロックモード
# "2"ではinterleavedロックモードが使用され、もっとも高速に動作する
innodb_autoinc_lock_mode = 2
#
# * ETC
#
# MySQLでのDNS逆引き機能を無効化
skip-name-resolve = 1
# DNS解決を回避するためにキャッシュされるホスト名の数
# DNS逆引き機能を無効化しない場合、この数を増やしてパフォーマンスを上げる
# host_cache_size = 10
# MEMORYテーブルの最大サイズ。このサイズを超えたMEMORYテーブルはディスク上に作成
max_heap_table_size = 32M
# スレッド毎に作成される一時的なテーブルの最大サイズ
tmp_table_size = 32M
# Galera書き込みセットを並列に適用するために使用されるレプリカスレッドの数
wsrep_slave_threads = 8
# MySQLサーバーが実行出来るSQL文の最大長
# クライアントとサーバ間の不正なパケットを捕捉したり、メモリ不足要因となる大きなパケットの誤用防止策
# 数値を増やすほど潜在的に使用するメモリ使用量が大きくなるが、メモリに余裕があればデフォルトの16Mまで上げる
max_allowed_packet = 1M
# パフォーマンスモニタリングを行うストレージエンジンの設定
performance_schema = ON
$ sudo service mysql restart
で再起動させます。~/MySQLTuner-perl-1.8.3$ ./mysqltuner.pl
で診断を行います。-------- Log file Recommendations ------------------------------------------------------------------
[OK] Log file /var/log/mysql/error.log exists
[--] Log file: /var/log/mysql/error.log(0B)
[--] Log file /var/log/mysql/error.log is empty. Assuming log-rotation. Use --server-log={file} for explicit file
-------- Storage Engine Statistics -----------------------------------------------------------------
[--] Status: +Aria +CSV +InnoDB +MEMORY +MRG_MyISAM +MyISAM +PERFORMANCE_SCHEMA +SEQUENCE
[--] Data in Aria tables: 32.0K (Tables: 1)
[--] Data in InnoDB tables: 2.1M (Tables: 31)
[OK] Total fragmented tables: 0
-------- Analysis Performance Metrics --------------------------------------------------------------
[--] innodb_stats_on_metadata: OFF
[OK] No stat updates during querying INFORMATION_SCHEMA.
-------- Security Recommendations ------------------------------------------------------------------
[OK] There are no anonymous accounts for any database users
[OK] All database users have passwords assigned
[--] There are 620 basic passwords in the list.
-------- CVE Security Recommendations --------------------------------------------------------------
[OK] NO SECURITY CVE FOUND FOR YOUR VERSION
-------- Performance Metrics -----------------------------------------------------------------------
[--] Up for: 15h 30m 14s (17K q [0.309 qps], 1K conn, TX: 30M, RX: 2M)
[--] Reads / Writes: 96% / 4%
[--] Binary logging is enabled (GTID MODE: ON)
[--] Physical Memory : 976.8M
[--] Max MySQL memory : 775.8M
[--] Other process memory: 0B
[--] Total buffers: 688.5M global + 2.9M per thread (30 max threads)
[--] P_S Max memory usage: 72B
[--] Galera GCache Max memory usage: 0B
[OK] Maximum reached memory usage: 697.2M (71.38% of installed RAM)
[OK] Maximum possible memory usage: 775.8M (79.42% of installed RAM)
[OK] Overall possible memory usage with other process is compatible with memory available
[OK] Slow queries: 0% (0/17K)
[OK] Highest usage of available connections: 10% (3/30)
[OK] Aborted connections: 0.37% (7/1882)
[OK] Query cache is disabled by default due to mutex contention on multiprocessor machines.
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 1K sorts)
[OK] No joins without indexes
[!!] Temporary tables created on disk: 41% (633 on disk / 1K total)
[OK] Thread cache hit rate: 99% (17 created / 1K connections)
[OK] Table cache hit rate: 86% (17K hits / 20K requests)
[OK] table_definition_cache(400) is upper than number of tables(323)
[OK] Open file limit used: 0% (62/16K)
[OK] Table locks acquired immediately: 100% (1K immediate / 1K locks)
[OK] Binlog cache memory access: 99.13% (456 Memory / 460 Total)
-------- Performance schema ------------------------------------------------------------------------
[--] Memory used by P_S: 72B
[--] Sys schema is installed.
-------- ThreadPool Metrics ------------------------------------------------------------------------
[--] ThreadPool stat is enabled.
[--] Thread Pool Size: 1 thread(s).
[--] Using default value is good enough for your version (10.6.5-MariaDB-1:10.6.5+maria~focal-log)
-------- MyISAM Metrics ----------------------------------------------------------------------------
[!!] Key buffer used: 19.7% (103K used / 524K cache)
[OK] Key buffer size / total MyISAM indexes: 512.0K/0B
-------- InnoDB Metrics ----------------------------------------------------------------------------
[--] InnoDB is enabled.
[OK] InnoDB File per table is activated
[OK] InnoDB buffer pool / data size: 512.0M/2.1M
[OK] Ratio InnoDB log file size / InnoDB Buffer pool size: 128.0M * 1/512.0M should be equal to 25%
[--] Number of InnoDB Buffer Pool Chunk : 4 for 1 Buffer Pool Instance(s)
[OK] Innodb_buffer_pool_size aligned with Innodb_buffer_pool_chunk_size & Innodb_buffer_pool_instances
[OK] InnoDB Read buffer efficiency: 99.78% (212234 hits/ 212704 total)
[!!] InnoDB Write Log efficiency: 107.91% (532 hits/ 493 total)
[OK] InnoDB log waits: 0.00% (0 waits / 1025 writes)
-------- Aria Metrics ------------------------------------------------------------------------------
[--] Aria Storage Engine is enabled.
[OK] Aria pagecache size / total Aria indexes: 128.0M/352.0K
[!!] Aria pagecache hit rate: 90.2% (6K cached / 645 reads)
-------- TokuDB Metrics ----------------------------------------------------------------------------
[--] TokuDB is disabled.
-------- XtraDB Metrics ----------------------------------------------------------------------------
[--] XtraDB is disabled.
-------- Galera Metrics ----------------------------------------------------------------------------
[--] Galera is disabled.
-------- Replication Metrics -----------------------------------------------------------------------
[--] Galera Synchronous replication: NO
[--] No replication slave(s) for this server.
[--] Binlog format: MIXED
[--] XA support enabled: ON
[--] Semi synchronous replication Master: OFF
[--] Semi synchronous replication Slave: OFF
[--] This is a standalone server
-------- Recommendations ---------------------------------------------------------------------------
General recommendations:
MySQL was started within the last 24 hours - recommendations may be inaccurate
When making adjustments, make tmp_table_size/max_heap_table_size equal
Reduce your SELECT DISTINCT queries which have no LIMIT clause
Variables to adjust:
tmp_table_size (> 16M)
max_heap_table_size (> 16M)
OPcacheの導入
$ sudo vim /etc/php/8.1/fpm/php.ini
でphp.ini
を編集します。php.ini
;; 省略 ;;
[opcache]
; zend_extensionとしてopcacheを読み込む
zend_extension = opcache
; OPcacheを有効化
opcache.enable = 1
; トレーシングJITを有効化
; 処理が複数回行われる場所を動的に発見し、該当する部分をトレースしてコンパイル対象にする
opcache.jit = on
; コンパイル済みのJITコードを保存する共有メモリの合計サイズ
opcache.jit_buffer_size = 128M
; OPcacheのコマンドラインを有効化
opcache.enable_cli = 1
; OPcacheが使用するメモリのサイズ
opcache.memory_consumption = 128
; インターン(intern)された文字列を格納するために使用されるメモリ量
opcache.interned_strings_buffer = 8
; OPcacheのハッシュテーブルキーの最大数
opcache.max_accelerated_files = 10000
; スクリプトのタイムスタンプをチェックする秒数
; "0"では常にチェックを行う
; "opcache.validate_timestamps"が無効の場合はこの設定が無視される
; 数値が多いほど更新頻度が減るため、パフォーマンスアップに繋がるが、PHPファイル編集後の反映が遅延する
opcache.revalidate_freq = 3
; OPcacheに含まれる全てのPHPDocコメントを破棄してコードを縮小化
; ただし、注釈のためにコメントを活用しているツールが破壊される可能性がある
; (Doctrine、Zend Framework 2 および PHPUnitなど)
; "0"で無効化
opcache.save_comments = 0
; "file_exists()"、"is_file()"および"is_readable()"が呼ばれた際、
; ファイルが既にキャッシュ済かOPcacheからチェックする
; ただし、"opcache.validate_timestamps"が無効な場合は古いファイルが返される可能性あり
; "1"で有効化
opcache.enable_file_override = 1
;; 省略 ;;
$ sudo service php8.1-fpm restart
で再起動を行います。/wp-admin/
等のログインした者以外アクセスできない場所に設置したり、使用しない時にはファイルを削除するなどの対策を推奨します。APCuの導入
$ sudo apt install php8.1-apcu --no-install-recommends
でAPCuをインストールできます。--no-install-recommends
を付ける理由として、執筆時点のAPCuではPHP7のパッケージもインストールに含めていることから、オプションを追加することでPHP7のインストールを中止しています。$ sudo vim /etc/php/8.1/fpm/php.ini
で編集を行います。php.ini
;; 省略 ;;
[apcu]
; 拡張機能としてapcu.soを読み込む
extension = apcu.so
; APCuの有効化
apc.enabled = 1
; APCuのコマンドラインを有効化
apc.enable_cli = 1
; APCuが使用する個別の共有メモリセグメントのサイズ
apc.shm_size = 128M
; APCuのキャッシュが保持される秒数
; "0"の場合、キャッシュメモリが不足した際に完全に削除される
apc.ttl = 3600
; キャッシュがガベージコレクションのリストに掲載される秒数
apc.gc_ttl=3600
; mmapされたメモリ領域をファイルベースか共有メモリベースに決める際、
; mmapモジュールに渡すmktempスタイルのファイルマスク
; ファイルベースのmmapの場合はXを6つ付ける
; POSIXスタイルの場合は.shmをマスク内のどこかに付ける
apc.mmap_file_mask=/tmp/apc.XXXXXX
;; 省略 ;;
$ sudo service php8.1-fpm restart
で再起動します。apc.php
を公開ディレクトリに配置し、その後ブラウザでそのファイルにアクセスするとモニタリング状況が表示されます。/wp-admin/
等のログインした者以外アクセスできない場所に設置、そして使用しない時にはファイルを削除するなどの対策を推奨します。
次回はWordPressのセキュリティ設定
様々な項目を編集する必要がありますが、今回の設定により、初期状態と比べて非常にパフォーマンスが向上していることを体感できるはずです。
PHPそのもののパフォーマンスも良くなっているため、数年前より更に高速化しています。
次回はWordPressのセキュリティ設定について紹介していきたいと思います。
セキュリティ設定はこの記事でまとめて紹介するつもりでしたが、今回の記事を含めて思った以上に長くなってしまうため、分けることにしました。
WordPressは特にセキュリティについてあれこれ言われることが多いため、できるだけその心配を解消します。
参考資料
- PHP: Hypertext Preprocessor
- Ubuntu 20.04にPHP8.0をaptコマンドでインストール
- Ubuntu 20.04に PHP8.1をインストールする
- 4.ubuntuでnginxが稼働するPCにPHPをインストール
- PHP 8の新機能(新機能、改善点、およびJITコンパイラー)
- How To Install PHP 8.1 on Ubuntu 22.04|20.04|18.04
- MariaDB Knowledge Base
- MariaDB vs MySQL: [2022] Everything You Need to Know
- Ubuntu 20.04 LTSに最新版MariaDBをインストールする
- MariaDB(MySQL)のバージョンを確認する【勘違いが多い】
- ubuntu で apt インストールした mariadb(mysql) のroot パスワードがわからないので初期設定を探した
- ERROR 1356 (HY000): View 'mysql.user' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
- MariaDBの初期パスワード変更方法
- 【chown】Linuxでファイルやディレクトリの所有者やグループ変更するコマンド
- Ubuntu 20.04にLAMPスタックでWordPressをインストールする方法
- WordPressのパーミッション設定 決定版
- NginxでWordPressを使う時の設定をまとめてみた
- WordPressのサイトヘルスステータスを〇良好にする
- WordPress の安全性を高める
- WordPress の更新で FTP のアクセス情報を聞かれたら?
- nginxとphp-fpmの接続で何故www-dataを記述する必要があるのか
- AWS環境のWordPressサイトヘルスステータス「1つ以上の必須モジュールが存在しません。」「バックルラウンドの更新が想定通りに動作していません。」の解消方法【Apache】
- 今さら聞きづらい「ファイルパーミッション」について
- Linux: SUID、SGID、スティッキービットまとめ
- UbuntuにphpMyAdminをインストールする(最新版phpMyAdminにも対応)
- phpMyAdminをUbuntu20.04+NGINXに入れる
- phpMyAdminの環境保管領域を設定する
- phpMyAdmin のインストールと動作検証
- phpMyAdmin のインストールとセキュリティ設定メモ
- phpMyAdminのセキュリティ対策
- phpMyAdminの簡単にできるセキュリティ対策【Apache】
- NginxでphpMyAdminを使用する
- Nginx でDigest認証を使う
- Basic認証・Digest認証・Form認証をざっくり理解
- How To Install and Secure phpMyAdmin with Nginx on an Ubuntu 20.04 Server
- wordpressをWEB/AP/DBサーバの3層構造で構築
- WEBサーバとDBサーバを使用してwordpressを構築
- 【さくらのVPS】DBサーバを外部に置いたWordpress構築(webサーバのセットアップ)
- 【さくらのVPS】DBサーバを外部に置いたWordpress構築(dbサーバのセットアップ)
- (Mysql) GRANT文が意味不明だったのでまとめた
- MySQL の Flush Privileges が本当に必要なときは?
- MySQLのFLUSH PRIVILEGESが必要なケース
- MariaDBのインストール
- MariaDB 10.4.1?のユーザー認証がカオスな話(Unix_Socket)
- 認証プラグイン-Unixソケット
- Ubunt 16.04でMariaDBをインストールするとパスワードが変
- Ubuntu 18.04 + MariaDB
- ERROR 2002 (HY000): Can't connect to MySQL server on '192.168.1.15' (115)
- Module ngx_http_fastcgi_module
- とにかく速いWordPress
- Nginx | Wordpress
- PHP FastCGI Example
- 28日目:nginx+FastCGIでRCCのサイトを高速化!
- Nginx の fastcgi cache を利用して WordPress を高速化する
- Flushing the nginx fastcgi cache via PHP (and/or WordPress)
- How to Setup FastCGI Caching with Nginx on your VPS
- キャッシュ設定 | wpX
- EasyEngine WooCommerce config with FastCGI Cache /pelmered/wpfcwc.conf
- nginxのtry_filesわかりにくすぎ問題
- MD5 Hash Generator
- 【PHPの「parse_url」関数について知りたかったので調べました】
- WordPress上部の管理バーに項目を追加、削除した話
- [PHP] URLをパースしていろいろ取得する方法
- PHPの「正しい」リダイレクト方法と、HTTPステータスコード
- WordPressで現在の記事の編集ページへのURLを取得する
- php-fpm の設定を理解してサイトのパフォーマンスを向上させる
- php-fpmについてざっくり紹介してみる
- php-fpm をチューニングしてみました
- 【PHP-FPM】適切なプロセス設定について
- PHP7.4 ぼくのかんがえたさいきょうのphp.ini
- PHP-FPMの設定(パフォーマンス対策)
- [PHP] PHP-FPMのチューニングをするときに考えたことと行ったこと
- Finding the correct pm.max_children settings for PHP-FPM
- PHP-FPM Process Calculator
- PHP アプリケーションの並列性の最適化
- PHP マニュアル
- 安全を考えてPHPの実行時設定を調整する
- PHP memory_limit ? understanding and increasing this setting
- MySQLパフォーマンスチューニング -my.cnfの見直し-
- MariaDBの5.5と10.2でチューニング&ベンチマーク比較(1) - mysqltuner編
- InnoDB の DoubleWrite 技術をみる
- Linuxのコマンド実行で使うserviceとsystemctlの違いとは何か?
- MariaDBのメモリ割り当て
- 電算星組 性能対策設定(システムチューニング)
- MySQLパフォーマンスチューニング概要
- MySQLのクエリキャッシュについてまとめた。
- MySQLをチューニング,そしてスケールアップ/スケールアウトへ
- Amazon RDS for MySQL のパラメータ設定 パート 1: パフォーマンス関連のパラメータ
- 開発環境用最低限のMySQL / MariaDB設定
- メモリ1GBなWordPressサーバに特化したMySQL5.6セッティング
- MySQLへのJDBC接続で、とあるバグを踏むまでの話 -(1)「max_allowed_packet」の基本的な働き
- 限界までMySQLを使い尽くす!!
- MariaDB(10.3.23)でレプリケーション
- MySQLTuner fix for “Reduce or eliminate unclosed connections and network issues”
- 今日は、MySQL Tunerを試してみたの日。
- MySQL max_connections は雑に設定しておけば良い
- performance_schemaをsysで使い倒す!
- PHP8で追加されたJITと、PHP OPcacheについて徹底解説!「悪りぃが、こっから先は一方通行だ」
- PHPの重鎮、廣川類氏のコラム「PHPの最新状況:PHP 8.0リリース間近」(第14回)
- PHP8のJITを有効にして、PHP7と速度比較する
- OPcache インストール設定
- Runtime Configuration
- APC User Cache
- APCu インストール 設定
- php8.0-apcu installs php7.4 packages #1603
- WordPressサイトをエクスポートする方法
- PHPの最後の終了タグは付けないでおこうねというお話
- phpMyAdmin 環境保管領域
- [PageSpeed Insights100点] WordPressチューニング15手順
- nginxでWordPressの設定する時に出てくるディレクティブのメモ
- Nginx で WordPress を使う時の注意点
- Cookie ポリシー
- How to Setup Separate NGINX FastCGI Cache for Mobile & Desktop Users
- Turn Your WordPress Site Into a Static Site With Aggressive Nginx Page Caching
- 新たなログイン用URLを作る