この投稿は、ChatGpt (Microsoft Copilot) に聞いた結果をまとめたものです
※便宜上、引用ブロックで ChatGPT の内容を表現します。
【編集履歴】
2025/7/8
- SELinux を無効にした場合の挙動を追加。
結論
先に結論。
1.原因 : SELinux はドキュメントルートでのバーチャルホストしか許可していない
すくなくとも Amazon Linux 2023 ではそのようです。
SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
2.対策
あきらめてドキュメントルートを、バーチャルホストで使用したいディレクトリに変更する
もとのhttpd.conf や .htaccess はバックアップしといて、Apache 全体のドキュメントルートに関する設定はコメントアウトするかバックアップしといて消す。
その方が分かりやすいですし。
何が起こったか
Webブラウザで WordPress のURL( "https://subdomain.xxx.net") にアクセスしても index.php
が正しく表示されない。
Apache の "It works" の index.html
が表示される。(httpd.conf
の ドキュメントルート=デフォルトだとだいたい /var/www/html/index.html
)
暗号化しないHTTP の場合は、WordPress のサイトホームのページ( "http://subdomain.xxx.net") がちゃんと表示される。
httpd -S
VirtualHost configuration:
*:443 is a NameVirtualHost
default server tabit.net (/etc/httpd/conf.d/ssl.conf:56)
port 443 namevhost tabit.net (/etc/httpd/conf.d/ssl.conf:56)
alias me.tabit.net
port 443 namevhost me.tabit.net (/etc/httpd/conf.d/vhost.conf:48)
*:80 is a NameVirtualHost
default server tabit.net (/etc/httpd/conf.d/vhost.conf:1)
port 80 namevhost tabit.net (/etc/httpd/conf.d/vhost.conf:1)
port 80 namevhost me.tabit.net (/etc/httpd/conf.d/vhost.conf:29)
port 80 namevhost ip-1xx-31-xx-250.ap-northeast-1.compute.internal (/etc/httpd/conf.d/vhost.conf:59)
wild alias *.tabit.net
ServerRoot: "/etc/httpd"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/etc/httpd/logs/error_log"
Mutex cache-socache: using_defaults
Mutex authdigest-opaque: using_defaults
Mutex watchdog-callback: using_defaults
Mutex proxy-balancer-shm: using_defaults
Mutex rewrite-map: using_defaults
Mutex ssl-stapling-refresh: using_defaults
Mutex authdigest-client: using_defaults
Mutex lua-ivm-shm: using_defaults
Mutex ssl-stapling: using_defaults
Mutex proxy: using_defaults
Mutex authn-socache: using_defaults
Mutex ssl-cache: using_defaults
Mutex default: dir="/etc/httpd/run/" mechanism=default
PidFile: "/etc/httpd/run/httpd.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="apache" id=48 not_used
Group: name="apache" id=48 not_used
me.tabit.net
に対して正しい証明書がない場合、*:443
にマッチせず、httpd
側のデフォルト設定が適用される。たとえば、上の実行結果のように、
ServerRoot: "/etc/httpd"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/etc/httpd/logs/error_log"
となっていたら
Main DocumentRoot:
と書かれた行が読み込まれる。正しい証明書がないか、あるいは ホスト名と一致していないなどが考えられる。
環境
- OS : Amazon Linux 2023
- Apache/2.4.58
- PHP 8.2.9
- OpenSSL 3.0.8
Let's Encrypt
- certbot 4.1.1
WordPress (VirtualHost でマルチサイトホスティングを使用して構築)
- ルートディレクトリ:
/var/www/vhost/me
- wordpress 6.8.1
VirtualHost
- ドキュメントルート:
/var/www/vhost/me
Apache のログを確認してみる
エラーログ
-
1 行目 (
AH01264
) にscript not found
と書いてある。 -
2 行目には
Cannot serve directory /var/www/vhost/: No matching DirectoryIndex (index.html,index.php) found
とある。
[cgid:error] [pid 1881416:tid 1881460] [client 45.135.194.11:38822] AH01264: stderr from /var/www/cgi-bin/luci: script not found or unable to stat
[autoindex:error] [pid 1881416:tid 1881447] [client 118.89.233.234:43058] AH01276: Cannot serve directory /var/www/vhost/: No matching DirectoryIndex (index.html,index.php) found, and server-generated directory index forbidden by Options directive
アクセスログ
/
(DocumentRoot のパス) にアクセスがあり、リダイレクトしようとしている。
"GET / HTTP/1.1" 301 230 " ...
設定ファイルがどうなっているか
#1 : httpd の設定
まずは、デフォルトのドキュメントルート (+少しいじっている) に適用される設定の確認。
/var/www/html
が DocumentRoot
として認識されている (httpd -S
で確認した) 場合、そのリダイレクト先がどこなのか。
# DocumentRoot を確認する
sudo cat -n /etc/httpd/conf/httpd.conf | grep DocumentRoot
120 # DocumentRoot: The directory out of which you will serve your
124 DocumentRoot "/var/www/html"
まあ、error_log
に /var/www/vhost
という文字がある時点でドキュメントルートは正しく設定されていそうだが、一応リダイレクト先を確認する。
# /etc/httpd/conf/httpd.conf
# リダイレクト先
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
※結局はこのindex.htmlが https://subdomain.xxx.net にアクセスしたときに返されるため、"It works" のような Apache のデフォルトの表示がされます。
#2 : VirtualHost の設定
そして、次にバーチャルホストの側の設定。
実際に認識していてほしい /var/www/vhost/me
が DocumentRoot
である場合、/var/www/vhost/: No matching DirectoryIndex (index.html,index.php)
の字義通りに考えてみると、DirectoryIndex
の設定が間違っているか、不十分。
httpsに使用する 443番ポートの設定は、50行目くらいにかいてある。
# /etc/httpd/conf.d/vhost.conf (パスは各自のもの)
1 <VirtualHost *:80>
2 ServerName tabit.net
3 DocumentRoot /var/www/html
4
5 <Directory "/var/www/html">
6 AllowOverride All
7 Require all granted
8 </Directory>
......
29 <VirtualHost *:80>
30 ServerName me.tabit.net
31 DocumentRoot /var/www/vhost/me
32 AllowEncodedSlashes On
...
39
40 <Directory /var/www/vhost/me>
41 SetEnv HTTP_X_FORWARDED_PROTO http
42 SetEnv REAL_HOST_NAME me.tabit.net
43 AllowOverride All
44 Require all granted
45 </Directory>
46 </VirtualHost>
47
48 <VirtualHost *:443>
49 ServerName me.tabit.net
50 DocumentRoot /var/www/vhost/me
51
52 <Directory /var/www/vhost/me>
53 AllowOverride All
54 Require all granted
55 DirectoryIndex index.php
56 </Directory>
57 </VirtualHost>
.......
たしかに <Directory /var/www/vhost>
が無い。
<Directory /var/www/vhost/me>
はあるが。
というわけで、追加してみる。
48 <VirtualHost *:443>
49 ServerName me.tabit.net
50 DocumentRoot /var/www/vhost/me
51
- 52 #<Directory /var/www/vhost/me>
- 53 # AllowOverride All
- 54 # Require all granted
- 55 # DirectoryIndex index.php
- 56 #</Directory>
+ 57
+ 58 <Directory /var/www/vhost>
+ 59 AllowOverride All
+ 60 Require all granted
+ 61 DirectoryIndex me/index.php
+62 </Directory>
+63 </VirtualHost>
error_log
にエラーはでなくなったが、WordPress サイトのページがやはり正しく表示されない。It works
という画面に。
たすけて ChatGPT
この時点でまた ChatGPT に丸投げしてみました。
今の構成で me.tabit.net にアクセスすると /var/www/html/index.html が出る理由、ズバリ「Apache が /var/www/vhost/me ではなく /var/www/html を DocumentRoot として扱っている状態」です。
だそうです。SELinux の動きに合致する正しい答えですが、コメントアウトした設定に戻せと言われたので、上のエラーログの内容をそのまま投げてみました。
AH01276: Cannot serve directory /var/www/vhost/
意味:Apache は
/var/www/vhost/
にアクセスしようとしたけど、DirectoryIndex
に該当するファイルがなく、ディレクトリ一覧を表示することも禁止されている。
主な原因:
DocumentRoot
または Rewrite 設定が/var/www/vhost/
に向いてしまっている- そこに
index.php
やindex.html
が 存在していない- かつ、
Options Indexes
が無効なため、Apache はエラーを返す⚠️
AH01264: stderr from /var/www/cgi-bin/luci: script not found
意味:CGIスクリプト
/var/www/cgi-bin/luci
を実行しようとしたが、存在しないまたは 実行権限がない
おそらくこのリクエストは意図したものではなく、間違ったルート(たとえば/cgi-bin
)に飛んでる状態
Cannot serve directory
については、『/var/www/vhost/
に向いてしまっている』というのはたぶん ChatGpt の間違いで、ただしくは『/var/www/html/
に向いてしまっている』だと思います。
(SELinux が許してくれる httpd.conf
の方のドキュメントルートが /var/www/html/
なので)
RewriteBase
は /
なので、これが /var/www/vhost/
を指しているという可能性にはならないはず ( バーチャルホストの DocumentRoot
は /var/www/vhost/me
なので ) 。
再現
Rewrite
以下の 1, 2 行目のコードでドキュメントルートから index.php にRewrite されます。
# /var/www/vhost/me/.htaccess
RewriteBase /
RewriteRule ^index\.php$ - [L]
任意のファイルやディレクトリへのリクエストは、1,2 行目のルールだけが適用されます。
[L] はそこで終わり、という意味らしいです。
# .htaccess (続き)
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
バーチャルホストの設定
SELinux がたぶん、ここの DocumentRoot /var/www/html
以外のバーチャルホストへのアクセスを許可してくれない。httpd.conf
のドキュメントルートにのみアクセスを許してくれるため、それ以外を設定しても意味がない。
# /etc/httpd/conf.d/vhost.conf
<VirtualHost *:80>
ServerName tabit.net
DocumentRoot /var/www/html
<Directory "/var/www/html">
AllowOverride All
Require all granted
</Directory>
# meディレクトリへのアクセスをルーティング
<Directory "/var/www/html/me">
DirectoryIndex index.html
AllowOverride All
Require all granted
</Directory>
# meへのリクエストを適切なディレクトリへリダイレクト
RewriteEngine On
RewriteCond %{HTTP_HOST} ^tabit\.life$ [NC]
# RewriteRule ^(.*)$ https://me.tabit.net/$1 [R=301,L]
RewriteRule ^(.*)$ https://me.tabit.net/ [R=301,L]
# RewriteCond %{REQUEST_URI} ^/me(/.*)?$ [NC]
# RewriteRule ^(.*)$ /var/www/html/me/$1 [L]
ErrorLog /var/log/httpd/error_log
CustomLog /var/log/httpd/access_log combined
</VirtualHost>
<VirtualHost *:80>
ServerName me.tabit.net
DocumentRoot /var/www/vhost/me
AllowEncodedSlashes On
<Directory /var/www/vhost/me>
SetEnv HTTP_X_FORWARDED_PROTO http
SetEnv REAL_HOST_NAME me.tabit.net
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:443>
ServerName me.tabit.net
DocumentRoot /var/www/vhost/me
<Directory /var/www/vhost/me>
AllowOverride All
Require all granted
DirectoryIndex index.php
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerAlias *.tabit.net
DocumentRoot /var/www/vhost
<Directory "/var/www/vhost">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
※この状態で https://subdomain.xxx.net/wp-login.php にアクセスすると、"File not found" という (おそらく) SELinux が返していると思われる文字が表示されます。
(Apache の 404 ページに似て非なる表示に注意)
2025/7/8 追記:
→ SELinux を Disabled にして確認しても "File not found. "(https://subdomain.example.net/wp-login.php
) となる。https://subdomain.example.net
には It works ( /var/www/html/index.html
) と表示される。
# SELinux を無効にしてシステムを再起動
rpm -q grubby
grubby-8.40-51.amzn2023.0.4.x86_64
sudo grubby --update-kernel ALL --args selinux=0
sudo reboot
Connection to 35.79.153.134 closed by remote host.
Connection to 35.79.153.134 closed.
権限
SELinuxは、root権限に対するセキュリティのものらしいので、権限によっては工夫できるかもしれません。
今回は root 権限と同等の権限をもつユーザー ( ec2-user
) でもバーチャルホストにアクセスできるようになっています。そのため、SELinux がちゃんと働いていると思います。
ls -ld /var/www/vhost/me
drwxrwsr-x. 5 ec2-user ftp-user 16384 Jul 4 00:46 /var/www/vhost/me
# 所有者 (ec2-user) が apache グループに入っている (一部デフォルトの値を適当な文字に置き換えてます)
groups ec2-user
ec2-user : ec2-user abc yyyy xxxx apache
# apacheユーザーが所有グループ (ftp-user グループ) に 入っている
groups apache
apache : apache ftp-user
OpenSSL (v3.0)
# /etc/httpd/conf.d/ssl.conf
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/tabit.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/tabit.net/privkey.pem