はじめに
この記事を最初に書いた時点(2020年1月)では、本Webサイト等ではWebサーバとしてApache httpdを使用しています。Apache httpdはこれまで仕事でも長らくお世話になっております。
しかし、本Webサイトの管理人たるpandaを取り巻く諸情勢の変化に鑑み、nginxの試し時がやって来たと思ったので、まずはページビューの少ないWebサイトのApache httpdをnginxに取り換えてみて、nginx自体の設定やファイル及びディレクトリのユーザ権限などで注意が必要と思われる点を
本記事の前提条件
Apache httpd及びWordpressは設定等により稼働状況を大きく変化させることができますが、この記事は以下の設定等が行われているものとして書いていきます。
- この記事のタイトルにあります通り、Apache httpdだけではなくphp-fpmも稼働させています。よってphp-fpmの設定のうち、プロセスや稼働させるプロセス数の設定の最適化のための設定についてはこの記事では扱いません。
- パーマリンクはデフォルトのもの(“https://pandanote.info/?p=5821″のようなフォーマットです。)を使用しています。
- WebサーバのディストリビューションはFedora(この記事を最初に書いた時点(2020年1月)はFedora 31)を使用しています。
nginxの設定で注意が必要だったところ
この節ではnginxの設定で注意が必要だったところを列挙していきます。
HTTPプロトコルを扱うポートへのアクセスをHTTPSプロトコルを扱うポートへ転送する
nginx.confのhttpのセクションの下のserverセクションのHTTPプロトコルを扱うポート(以下、「80番ポート」と書きます。)についての定義中の適当な場所(最初のlocationの定義の前あたり)に以下の設定を追加します。
http { | |
(中略) | |
server { | |
listen 80 default_server; | |
listen [::]:80 default_server; | |
(前略) | |
# location定義の前あたりに挿入。 | |
# 実際の設定として使用する際には、ドル記号の前のバックスラッシュは不要。 | |
return 301 https://$host$request_uri; | |
(後略) | |
} | |
} |
rewriteを行うことなく、サクッと転送です。
HTTPSプロトコルを扱うポートについての設定の追加
nginx.confの80番ポートについての定義(前節参照)の直後に以下の設定を追加します。
server { | |
listen 443 ssl http2 default_server; | |
listen [::]:443 ssl http2 default_server; | |
server_name (適切なドメイン名); | |
root (Apache httpdのDocumentRootの設定); | |
ssl_certificate (Apache httpdのSSLCertificateFileの設定); | |
ssl_certificate_key (Apache httpdのSSLCertificateKeyFileの設定); | |
ssl_session_cache shared:SSL:10m; | |
ssl_session_timeout 10m; | |
ssl_protocols TLSv1.3 TLSv1.2; | |
ssl_prefer_server_ciphers on; | |
client_max_body_size 50M; | |
index index.php index.html index.htm; | |
(以下location及びerror関連の設定が続きます…) | |
} |
TLSはv1.3及びv1.2のみのサポートとしています。古いバージョンのブラウザをサポート対象とするとセキュリティ上の問題があることの他に、古い仕様のHTMLの記述についてのサポートも必要になりますので、それを不要とすることで、サーバ管理上の負担を削減することも目的です。
また、client_max_body_sizeの値を調整することで、アップロードできるファイルの大きさを大きく設定しています。
WordPressの管理ページへのアクセスをIPアドレスで制限するための設定の別解
みんな大好きIPアドレスを使ったアクセスコントロールですが、他の条件と組み合わせる(e.g.特定の機種の端末で、かつ特定のIPアドレスからのアクセスのみ許可する場合。)場合には、
…のような許可リストを並べる方法が使えません。(´・ω・`)
そこで、mapモジュールを使います。
ありがたいことに、Fedora 31ではデフォルトで有効になっています。
ということで、httpセクションの下に以下の設定を追加します。なお、以下の例の変数allowed及びそれに格納するパラメータの定義の方法については特別なルールはありませんので、他の予約されている変数等と重複しない限り自由に定義できます。
- httpセクションの直下に以下の設定を追加します。この例では、アクセス元のIPアドレスがab.cd.ef.ghiと一致するか、先頭が2abc:defg:hijk:lmop:と一致する場合に限り変数allowedにallowをセットし、それ以外の場合にはdenyをセットします。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactershttp { (前略) map { ab.cd.ef.ghi allow; ~2abc:defg:hijk:lmop: allow; default deny; } (後略) }
なお、IPアドレスリストは文字列として扱われますのでサブネットマスクは使えません。IPv4アドレスの場合には前方一致と組み合わせて、aa.bb.cc. allow;スポンサーリンク
等のように設定する必要があります。また、defaultについても忘れずに設定します。 - serverセクションのうちの必要な場所でallowed変数を参照し、denyである場合には404を返すための設定を追加します。具体的には以下のような設定になります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactershttp { (略) server { (略) location /somewhere_to_restrict { (前略) if ($allowed = deny) { return 404; } (後略) } (略) } (略) }
特定の属性値を持つリクエストを許可するための設定例
例えば、前節の手順2の評価を行う前に以下のようにallowed変数を上書きすることで、特定のhttp_user_agentを送信する端末からのアクセスを無条件に許可する設定とすることができます。
http { | |
(略) | |
server { | |
(略) | |
location /somewhere_to_restrict { | |
(前略) | |
if ($http_user_agent ~ WhileMobile) { | |
return 404; | |
} | |
(中略) | |
if ($allowed = deny) { | |
return 404; | |
} | |
(後略) | |
} | |
(略) | |
} | |
(略) | |
} |
WordPress側で用意した404.phpを使用するための設定
Apache httpd+Wordpressではテーマ用のディレクトリの直下に”404.php”という名前のファイルを作成し、そこに404エラーが発生した場合に表示されるメッセージ等を記述しておいて、かつApache httpd側で以下の設定を行うと、404.phpで記述されたエラーページが表示される仕組みになっていました。
nginxには上記のような仕組みがありませんので、設定で何とかする必要があります。
具体的には404エラーが発生した際にはFastCGIにリクエストをforwardする設定を行います。その際に、FastCGIに適切なURLが渡るように設定する必要があります。
そこで、以下のように設定してみました。
http { | |
(略) | |
server { | |
(略) | |
error_page 404 = @notfound; | |
location @notfound { | |
root (Apache httpdでDocumentRootとして設定していた値); | |
include fastcgi_params; | |
fastcgi_index index.php; | |
fastcgi_param SERVER_NAME $host; | |
fastcgi_param SCRIPT_FILENAME $document_root/index.php; | |
fastcgi_param QUERY_STRING error=404; | |
fastcgi_pass php-fpm; | |
} | |
(略) | |
} | |
(略) | |
} |
FastCGIに対しては環境変数を設定できますが、呼び出すファイル名(ここではindex.php)とクエリ文字列(error=404)を別々の環境変数にセットするように設定してみました。
gzip圧縮の設定
gzip圧縮もhttpモジュールの設定中で以下のように設定します。
TLSv1.2以降に対応しているブラウザからの接続のみ受け付ける設定としているため、上記の設定のうち古いIE対策の2行目の記述は不要かもしれませんが、念のため設定しておきます。
nginx以外の設定変更
php-fpmの設定変更
Fedora 31ではphp-fpmの設定ファイルは/etc/php-fpm.dの下にありますが、/etc/php-fpm.d/www.confの設定のうち以下の設定を変更します。
ディレクトリ等のownerの変更
Apache httpd,php-fpmまたはwordpress.confが使用しているディレクトリ等のうちnginxが使用するものについてはownerをnginxに変更する必要があります。
Fedora 31では以下のディレクトリ等のownerをnginxに変更します。
- /etc/wordpress及びその直下のファイル
- /var/lib/php/session及びその直下のファイル
- /var/lib/php/wsdlcache及びその直下のファイル
- /var/lib/php/opcache及びその直下のファイル
- /usr/share/wordpress/wp-content/uploads及びその下のファイル
また、/etc/wordpressのpermissionを755に変更しました。
追加パッケージのインストール
Let’s encrypt用のプラグインのインストール
以下のコマンドを実行し、certbox-nginxパッケージをインストールします。
定性的な評価のようなもの
Apache httpdを稼働させた状態でアクセスしたときには一呼吸おいてからページが表示されていたように感じていたのですが、nginxに切り替えた後はその一呼吸がなくなったように感じました。
切り替えのための設定にミスがあると他のWebサイト様でも指摘のある通り404エラーを連発してしまうため、その解決のためにはそれなりの手間を要しますが、切り替えてみる価値はありそうです。
まとめ
Apache httpdで運用している期間が長くなってくると、設定ファイルが「秘伝のタレ」化しがちですが、たまにはリファクタリングしてみるのも悪くはないなぁと思いました。
古いブラウザからのアクセス対策についての設定はバッサリ削除できますので、割とおすすめです。
この記事は以上です。