メインコンテンツに移動

これまでRed Hat Enterprise LinuxにnginxやPHP8、mysql community serverをインストールして動作確認までおこなってきました。
本日は、この環境にdrupal9をインストールして動作確認します。
最初に、このCMS用にデータベースを作成します。ユーザーも作成し、データベースにすべての権限を付与します。

mysql -u root -p
CREATE DATABASE testdb DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON testdb.* TO 'testuser'@'localhost';
show databases;
quit

ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

上記のエラーが発生したら、大文字小文字、英数字、それに記号を含めたパスワードを作成します。

https://www.drupal.org/download

公式サイトでダウンロードするファイルのリンクを取得します。


wgetコマンドでダウンロードして、展開します。

cd /tmp
wget https://www.drupal.org/download-latest/tar.gz
tar -xvf tar.gz

drupalにバージョンが付いたディレクトリが作成され、その中に必要ファイルが含まれています。
このディレクトリごとディレクトリ名を変更しつつドキュメントルートに移動します。

sudo mv drupal-9.1.7 /usr/share/nginx/html/drupal

次のディレクトリにdrupal用にconfファイルを作成します。ここには他にもwww.confというファイルがあり、これを動作するように編集してもOKです。ただし、知識が必要でトラブルに悩まされました。学習目的の人は、内容を見て編集することも一つの手段であると思います。
以前苦労した例
listen.acl_users = apache,nginx
をコメント扱いにしないと、listen.ownerやlisten.groupの記述が有効にならない。それゆえ、sockファイルの所有権が設定通りにいかずページが表示できなかった。
ここでは、動作確認しているconfファイルを新規で作成します。

cd /etc/php-fpm.d
sudo vi drupal.conf

[drupal]
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx
listen = /run/php-fpm/drupal.sock
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
pm.max_requests = 500
chdir = /

次はphp-fpmの確認をします。インストールしたばかりだと起動していません。
起動するとrunというディレクトリの下にphp-fpmというディレクトリが作成され、さらにsockファイルも作成されます。この時、sockファイルの所有権がnginxであることを確認します。

sudo systemctl status php-fpm
sudo systemctl start php-fpm
cd /run/php-fpm
ls -l

停止すると、このディレクトリとsockファイルは消えます。このファイルの役割はnginxとphp-fpmの通信を可能にすることです。

sudo systemctl stop php-fpm
cd /run/php-fpm
sudo systemctl start php-fpm

今度はnginxの動作に必要なファイルを作成します。最初に存在しているdefault.confを編集して使い回してもOKですが、公式サイトにnginx用の記述例があるので新規で作成します。

https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/

cd /etc/nginx/conf.d
sudo vi drupal.conf

server {
listen 80;
server_name showa.xyz;
root /usr/share/nginx/html/drupal; ## <-- Your only path reference.

access_log /var/log/nginx/showa.xyz.access.log;
error_log /var/log/nginx/showa.xyz.error.log;

location = /favicon.ico {
log_not_found off;
access_log off;
}

location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}

# Very rarely should these ever be accessed outside of your lan
location ~* \.(txt|log)$ {
allow 192.168.0.0/16;
deny all;
}

location ~ \..*/.*\.php$ {
return 403;
}

location ~ ^/sites/.*/private/ {
return 403;
}

# Block access to scripts in site files directory
location ~ ^/sites/[^/]+/files/.*\.php$ {
deny all;
}

# Allow "Well-Known URIs" as per RFC 5785
location ~* ^/.well-known/ {
allow all;
}

# Block access to "hidden" files and directories whose names begin with a
# period. This includes directories used by version control systems such
# as Subversion or Git to store control files.
location ~ (^|/)\. {
return 403;
}

location / {
# try_files $uri @rewrite; # For Drupal <= 6
try_files $uri /index.php?$query_string; # For Drupal >= 7
}

location @rewrite {
#rewrite ^/(.*)$ /index.php?q=$1; # For Drupal <= 6
rewrite ^ /index.php; # For Drupal >= 7
}

# Don't allow direct access to PHP files in the vendor directory.
location ~ /vendor/.*\.php$ {
deny all;
return 404;
}

# Protect files and directories from prying eyes.
location ~* \.(engine|inc|install|make|module|profile|po|sh|.*sql|theme|twig|tpl(\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|/(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock)|web\.config)$|/#.*#$|\.php(~|\.sw[op]|\.bak|\.orig|\.save)$ {
deny all;
return 404;
}

# In Drupal 8, we must also match new paths where the '.php' appears in
# the middle, such as update.php/selection. The rule we use is strict,
# and only allows this pattern with the update.php front controller.
# This allows legacy path aliases in the form of
# blog/index.php/legacy-path to continue to route to Drupal nodes. If
# you do not have any paths like that, then you might prefer to use a
# laxer rule, such as:
# location ~ \.php(/|$) {
# The laxer rule will continue to work if Drupal uses this new URL
# pattern with front controllers other than update.php in a future
# release.
location ~ '\.php$|^/update.php' {
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
# Ensure the php file exists. Mitigates CVE-2019-11043
try_files $fastcgi_script_name =404;
# Security note: If you're running a version of PHP older than the
# latest 5.3, you should have "cgi.fix_pathinfo = 0;" in php.ini.
# See http://serverfault.com/q/627903/94922 for details.
include fastcgi_params;
# Block httpoxy attacks. See https://httpoxy.org/.
fastcgi_param HTTP_PROXY "";
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param QUERY_STRING $query_string;
fastcgi_intercept_errors on;
# PHP 5 socket location.
#fastcgi_pass unix:/var/run/php5-fpm.sock;
# PHP 7 socket location.
fastcgi_pass unix:/run/php-fpm/drupal.sock;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
try_files $uri @rewrite;
expires max;
log_not_found off;
}

# Fighting with Styles? This little gem is amazing.
# location ~ ^/sites/.*/files/imagecache/ { # For Drupal <= 6
location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7
try_files $uri @rewrite;
}

# Handle private files through Drupal. Private file's path can come
# with a language prefix.
location ~ ^(/[a-z\-]+)?/system/files/ { # For Drupal >= 7
try_files $uri /index.php?$query_string;
}

# Enforce clean URLs
# Removes index.php from urls like www.example.com/index.php/my-page --> www.example.com/my-page
# Could be done with 301 for permanent or other redirect codes.
if ($request_uri ~* "^(.*/)index\.php/(.*)") {
return 307 $1$2;
}
}

この記述例をコピーして貼り付け、編集します。
編集した個所
listen 80;
を追記。
server_name showa.xyz;
root /usr/share/nginx/html/drupal;
access_log /var/log/nginx/showa.xyz.access.log;
error_log /var/log/nginx/showa.xyz.error.log;
fastcgi_pass unix:/run/php-fpm/drupal.sock;
を自分の環境に合わせて書き換え。

次のディレクトリにあるdefault.settings.phpというファイルをsettings.phpというファイル名に変更するか、コピーしておきます。このディレクトリの下にfilesというディレクトリも作成します。
その後、一番上の階層から下の階層まで所有権をnginxに変更します。

cd /usr/share/nginx/html/drupal/sites/default
sudo cp default.settings.php settings.php
sudo mkdir files
sudo chown -R nginx:nginx /usr/share/nginx/html/drupal

ここまで終わったらブラウザでアクセスしてみましょう。
失敗しました。

502 Bad Gateway

下記のようなログでした。

recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 126.110.51.39, server: showa.xyz, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/drupal.sock:", host: "showa.xyz"

色々試行錯誤しましたが、SELinuxが原因のようでした。SELinuxとはLinuxのセキュリティ機能です。
状態を確認後一時的に無効にします。一時的ですので再起動すると有効になります。

getenforce
sudo setenforce 0

再度アクセスすると、今度はうまくいきました。
途中で不足しているPHPの拡張機能が表示されたら適宜修正します。

sudo dnf install php php-gd

データベースの構成まで進みましたが、先ほど作成したデータベースの設定が現れません。SQLiteしか選択肢がありません。

PHPでデータベースを使用できるようにする拡張機能を追加します。

sudo dnf install php php-mysqlnd

いったんDrupalフォルダを削除して、再び設定後インストールウィザードを開始します。今度はインストール済みのmysql community serverで作成したデータベースに接続できました。