Ubuntuでnginx1.24とApache2.4+PHP8.2のセットアップ

Web

Ubuntu環境でnginxをリバースプロキシーとして設定し、裏の処理を同一サーバー内のApacheに任せる構成でWebサーバーのセットアップを行います。
利点として、Wordpressが生成する.htaccessがそのまま使うことができ、nginxが持つキャッシュ機能も設定追加で活用することが可能です。 前回に引き続き、今回も少し長めの内容となりますがご了承ください。

nginx1.24のインストール

最新のnginxをインストールできるよう、設定ファイルを新規作成します。

/etc/apt/sources.list.d/nginx.listdeb https://nginx.org/packages/ubuntu/ jammy nginx
deb-src https://nginx.org/packages/ubuntu/ jammy nginx
「jammy」の部分はバージョン情報となります。
詳細は次の公式情報(英文)からご確認ください。
Installing NGINX Open Source | NGINX Documentation
Install NGINX Open Source either as a prebuilt package or from source, following step-by-step instructions for all suppo...

次にnginx公式が公開している署名鍵をインポートします。
次のコマンドを順に実行して、署名鍵の取得・インポート・不要になった署名鍵を削除してます。

wget https://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key
rm nginx_signing.key

次のコマンドを実行すると、nginxがインストールされます。

sudo apt update -y
sudo apt install -y nginx

インストールが完了したら、次のコマンドでnginxの自動起動設定と起動を行います。

sudo systemctl enable nginx
sudo systemctl start nginx

nginxが使用する80番,443番ポートを開放するため。次のコマンドでファイアウォールの設定を変更します。

sudo ufw allow 'nginx Full'
sudo ufw reload

ここまでサーバー設定に問題がなければ、IPアドレスによるアクセスでnginxの標準ページが表示されるはずです。

http://xxx.xxx.xxx.xxx/

「xxx.xxx.xxx.xxx」の箇所をVPSのグローバルIPに変えてアクセスしてみましょう。

PHP8.2とApache含むモジュール一式のインストール

最新のPHPをインストールできるよう、リポジトリーの追加を行います。

sudo apt-add-repository ppa:ondrej/php
sudo apt update

次にインストールしたいバージョンのPHP(今回はPHP8.2)とWordPress稼働に必要な関連モジュールを一括インストールします。

sudo apt update -y
sudo apt install -y php8.2 php8.2-mysql php8.2-curl php8.2-dom php8.2-imagick php8.2-gd php8.2-mbstring php8.2-zip php8.2-intl

PHP8.2をインストールするとApache2.4もセットで付いてきます。
もしnginx単独でPHPを動かしたい場合、「php8.2」を指定せず「php8.2-fpm」に変更してください。PHP8.2本体だけインストールされてApache2.4はインストールされません。

インストールが完了したら、次のコマンドでApacheの自動起動設定と起動を行います。

sudo systemctl enable apache2
sudo systemctl start apache2

PHP8.2の設定を行う

PHPの設定ファイルである「php.ini」を編集します。
設定項目が膨大であるため、編集前に初期の状態を把握できるようにオリジナルファイルをコピーしておきましょう。

sudo cp /etc/php/8.2/apache2/php.ini /etc/php/8.2/apache2/php.ini.proto

設定変更箇所ですが、まずPHPのバージョン情報を晒す「expose_php」を無効にします。
また、ファイルアップロードに関わる設定として

  • memory_limit (1プロセス辺りのメモリー上限)
  • post_max_size (ヘッダー含めた1リクエストで扱う総データサイズ上限)
  • upload_max_filesize (1リクエストで扱うファイルサイズ上限)

の設定も変更します。これを行っていないとWordPressでテーマやプラグインのアップロードが行えません。設定値のバランスですが、

memory_limit >> post_max_size > upload_max_filesize

となるよう、うまく調整してください。

/etc/php/8.2/apache2/php.ini・・・
expose_php = On
expose_php = Off
・・・
memory_limit 128M
・・・
post_max_size = 8M
post_max_size = 64M
・・・
upload_max_filesize = 2M
upload_max_filesize = 50M
・・・
・・・

設定例では「memory_limit」のみデフォルト値のままにしています。
もし128Mより大きいファイルを取り扱いたい場合、サーバーのメモリースペックを意識しつつ「memory_limit」の値を調整してください。

Apache2.4の設定を行う

まずnginxで使用するポートと被らないよう、ポート関連の設定ファイルを編集します。
80番ポートはnginxがHTTP通信で使用するため、内部通信用に「8080」に書き換えます。
443番ポートはnginxがHTTPS通信で使用し、内部通信では使用しないためコメントアウトします。

/etc/apache2/ports.conf・・・
Listen 80
Listen 8080

<IfModule ssl_module>
        Listen 443
</IfModule>
#<IfModule ssl_module>
#        Listen 443
#</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
</IfModule>
#<IfModule mod_gnutls.c>
#        Listen 443
#</IfModule>
・・・

次にApacheの実行ユーザーを変更します。
今回は前回の記事で作成したWebサーバー統括ユーザーに設定します。

・・・
# Since there is no sane way to get the parsed apache2 config in scripts, some
# settings are defined via environment variables and then used in apache2ctl,
# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
export APACHE_RUN_USER=USER_NAME
export APACHE_RUN_GROUP=USER_NAME
# temporary state file location. This might be changed to /run in Wheezy+1
・・・

次にセキュリティ面で修正しておきたい設定を変更します。

/etc/apache2/apache2.conf・・・
Options Indexes FollowSymLinks
Options FollowSymLinks
・・・
/etc/apache2/conf-available/security.conf・・・
ServerTokens OS
ServerTokens Prod
・・・
ServerSignature On
ServerSignature Off
・・・

リバースプロキシー配下のApacheがリモートIPを取得できるよう、読込モジュールを設定します。

/etc/apache2/mods-available/remoteip.confRemoteIPInternalProxy 127.0.0.1
RemoteIPHeader        X-Forwarded-For
RemoteIPProxiesHeader X-Forwarded-By

「RemoteIPInternalProxy」は同一サーバーのnginxをリバースプロキシとして使用しているため、「127.0.0.1」を指定しています。
もし外部のプロキシーを使用する場合、「RemoteIPInternalProxy」ではなく「RemoteIPTrustedProxy」にて対象IPを追加設定しましょう。

設定ファイルの編集が完了したら、次のコマンドで必要なモジュール一式を有効にします。

sudo a2enmod remoteip headers

a2enmodコマンドはmods-enabledディレクトリーに対し、指定のload/confファイルのシンボリックをまとめて作成してくれます。
スペース区切りで複数モジュールを一括指定できるため、個別でシンボリックリンクを作成するより楽です。

次にバーチャルホストの設定を行います。
まず、/var/www/配下に独自ドメインのディレクトリーを作成し、更にその中に公開用ディレクトリーを作成します。

sudo install -o USER_NAME -g USER_NAME -d /var/www/your-domain.tld/public
sudo chown USER_NAME:USER_NAME /var/www/your-domain.tld

その後、画面表示の確認に使用するPHPファイルも作成します。
出力内容については、動作確認できるものであれば何でもかまいません。

/var/www/your-domain.tld/public/index.php<?php
echo '<h1>View test.</h1>';
echo '<pre>';
print_r($_SERVER);
echo '</pre>';

ディレクトリーとテストファイルの作成が完了したら、バーチャルホスト設定ファイルを新規作成します。WordPressの脆弱性となり得るアクセスに対する制限も同時に行っています。

/etc/apache2/sites-available/your-domain.tld.conf<VirtualHost *:8080>
    ServerName your-domain.tld
    DocumentRoot /var/www/your-domain.tld/public
    DirectoryIndex index.php index.html index.htm
    <Directory /var/www/your-domain.tld/public>
        AllowOverride all
        <Files "license.txt">
            Require all denied
        </Files>
        <Files "readme.html">
            Require all denied
        </Files>
        <Files "wp-config.php">
            Require all denied
        </Files>
        <Files "wp-config-sample.php">
            Require all denied
        </Files>
        <Files "xmlrpc.php">
            Require all denied
        </Files>
    </Directory>
    <LocationMatch ^/wp-includes/(.*)\.php$>
        Require all denied
    </LocationMatch>
    <LocationMatch ^/wp-content/(.*)\.php$>
        Require all denied
    </LocationMatch>
</VirtualHost>

もしWordPressの管理画面へアクセスする端末が固定IP環境下である場合、次の設定も追加します。

/etc/apache2/sites-available/your-domain.tld.conf・・・
        <Files "xmlrpc.php">
            Require all denied
        </Files>
        <Files "wp-login.php">
            Require ip xxx.xxx.xxx.xxx
        </Files>
        <Files "wp-signup.php">
            Require ip xxx.xxx.xxx.xxx
        </Files>
    </Directory>
    <Directory /var/www/your-domain.tld/public/wp-admin>
        Require ip xxx.xxx.xxx.xxx
        <FilesMatch admin-ajax.php$>
            Require all granted
        </FilesMatch>
    </Directory>
    <LocationMatch ^/wp-includes/(.*)\.php$>
        Require all denied
    </LocationMatch>
    <LocationMatch ^/wp-content/(.*)\.php$>
        Require all denied
    </LocationMatch>
・・・
「Require ip」の箇所は管理者画面へのアクセスポイントとする固定IPを設定してください。
権限制御の詳細は次の公式マニュアル(英文)をご確認ください。
mod_authz_core - Apache HTTP Server Version 2.4

その後、次のコマンドでバーチャルホスト設定を有効にします。

sudo a2ensite your-domain.tld

最後に構文チェックを行います。

sudo apache2ctl -t

nginx1.24の設定を行う

まず共通設定の編集を行います。

/etc/nginx/nginx.conf・・・
    keepalive_timeout  65;

    gzip off;
    gzip on;
    gzip_types text/css text/javascript application/json application/octet-stream;
    server_tokens off;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
gzip圧縮対象を指定するgzip_typesですが、画像関係は再圧縮となり効率が悪いため対象外としています。
また、text/htmlは標準で圧縮されるため指定する必要がありません。指定すると重複指定の警告が出ます。
なお、JavaScriptのMIMEタイプを誤って記載してるサイトが多いですが、正解はtext/javascriptです。現在の各MIMEタイプについては次のサイトを確認するようにしましょう。
よくある MIME タイプ - HTTP | MDN
これは文書の種類に関連付けられている MIME タイプの一覧であり、一般的な拡張子の昇順に並べています。

サーバーへ送信可能なファイルサイズ上限を引き上げるため、次の設定ファイルを新規作成します。
php.iniの「post_max_size」で設定した値と同じになるようサイズを指定してください。

/etc/nginx/conf.d/client_max_body_size.confclient_max_body_size 64M;

次にバーチャルホストの設定を行います。

/etc/nginx/sites-available/your-domain.tldserver {
    listen 80;
    server_name your-domain.tld;
    access_log /var/log/nginx/your-domain.tld.access.log;
    error_log /var/log/nginx/your-domain.tld.error.log;

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_pass http://127.0.0.1:8080;
    }
}

設定変数で1点注意があります。
設定例で「$host」を使用している箇所ですが、インターネット上で情報を調べると「$host」ではなく「$http_host」にしている記事がいくつか散見されます。
「$http_host」を使うとホスト・ヘッダー・インジェクションの原因となるため、意図的な理由がなければ「$host」を常に使用することを推奨します。

有効サイトとしてsites-enabledディレクトリーにシンボリックリンクを作成します。
Apacheと違い便利コマンドはないため、普通のコマンドを使います。

sudo ln -s /etc/nginx/sites-available/your-domain.tld /etc/nginx/sites-enabled/your-domain.tld

最後に構文チェックを行います。

sudo nginx -t

バーチャルホストのページ表示を確認する

設定ファイルの編集が終わったら、Apacheとnginxを再起動します。

sudo systemctl restart nginx apache2

再起動後、Webブラウザで独自ドメインにアクセスします。

http://your-domain.tld/

先程作成したテスト用PHPファイルの内容が表示されていればOKです。

無料SSL「Let’s Encrypt」の導入と設定を行う

Let’s Encryptの証明書を簡単に導入するため、certbotをインストールします。
次のコマンドで必要なモジュールをまとめてインストールします。

sudo apt update -y
sudo apt install -y certbot python3-certbot-nginx

インストールが完了したら、次のコマンドを実行します。
nginxの指定ドメインのバーチャルホスト設定ファイルが自動更新され、SSL対応が完了します。

sudo certbot --nginx -d your-domain.tld --register-unsafely-without-email

Ubuntuだとこういう便利パッケージが充実していて楽ですね。
また、証明書の自動更新が有効になっているどうかは次のコマンドで確認可能です。

sudo certbot renew --dry-run

対象ドメインにHTTPS接続可能か確認し、問題なく画面表示されればOKです。

https://your-domain.tld/

HTTPS接続での画面表示も確認できたら、テスト用PHPファイルは削除します。

rm /var/www/your-domain/public/index.php

タイトルとURLをコピーしました