メニュー

1-9 ドメイン個別設定とリバースプロキシ構築

Nginxをリバースプロキシとして使用する。
設定・編集はNginxとApacheの両方。

リバースプロキシの確認方法の補足

最初はrootディレクティブにテストページを指定してリバースプロキシを実装できているかどうかを確認したほうがいい。
チェックポイントは以下の2つ。

  • NginxのロゴのところがApacheのロゴに変わっているか。
    →変わっていなければApacheの設定を読み込めていない。
  • テストページで使用するファイルへのアクセスが403になっていないか。
    →403だったらもしかするとApache側でDirectoryディレクティブが設定されていないか、Directoryディレクティブがあっても「Require all granted」で全体アクセスを許可していないかも。

Nginx:ディレクトリsites-availableとsites-enabledの準備

ディレクトリsites-availableとsites-enabledを用意せずともドメインに対する設定そのものはできる。

sites-availableとsites-enabledを用意するメリットは以下の2点。

  • 設定ファイルはそのままの状態で、サイトを一時的に非公開にしたり無効にできる。
  • 一時的に非公開にしたサイトをすぐに公開できる。

OSやリポジトリによっては、予めsites-availableとsites-enabledが用意されていることもある。

まずは/etc/nginx/の中にディレクトリsites-enabledとsites-availableを作成する。

mkdir /etc/nginx/sites-available
mkdir /etc/nginx/sites-enabled

/etc/nginx/nginx.confには、/etc/nginx/sites-enabledの中にあるファイルを読み込む設定を追記する。
httpブロックの「include /etc/nginx/conf.d/*.conf;」の下にincludeディレクティブを追加。

include /etc/nginx/sites-enabled/*;

本当は/etc/nginx/conf.d内にincludeを書いてもいいのかもしれないけど、ドメイン名によっては他の設定ファイルより先読みされてうまく動作しなくなるケースもあるかもしれないと思った。

Nginx:Apacheに転送する共通confファイルの準備

includeディレクティブで読み込む共通confファイルを用意する。個別に読み込むので/etc/nginx/conf.d内にファイルを作らない。
ユーザー側で/etc/nginxの中にディレクトリフォルダを作ってよい。今回はサンプルとして、Apacheに転送する共通confファイル/etc/nginx/my-custom/reverse-proxy-apache.confを用意する方針で話を進める。

# log
access_log /var/log/nginx/apache_access.log main;
error_log /var/log/nginx/apache_error.log debug;

# reverse proxy
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Port  $server_port;
proxy_http_version 1.1;

問題を切り分けられるようにしたいので、apache用のログを出す設定を追加。

Nginx:ドメインの個別設定

/etc/nginx/sites-availableの中にドメインの設定ファイルを入れる。hoge.example.comを用意するなら、一見でどのドメインの設定かわかるように/etc/nginx/sites-available/hoge.example.comというファイル名で保存するのがオススメ。

server {

  # value
  set $site_domain example.com;
  set $site_sub_val hoge;

  # domain
  server_name hoge.example.com;

  # log
  access_log /var/log/nginx/domain/${site_domain}/${site_sub_val}__access.log main;
  error_log /var/log/nginx/domain/example.com/hoge__error.log debug;



  #
  # site-custom
  #

  location / {
    proxy_pass http://hoge.example.com:8080;
    include /etc/nginx/my-custom/reverse-proxy-apache.conf;
    root /home/hogehoge-user/public_html/${site_domain}/sub/${site_sub_val}/www;
    index index.html index.php;
  }

}

setディレクティブで変数を定義できる。
いくつか変数を用意したのに活用していない箇所があるけれど、たとえばエラーログのところに変数を使うとシンタックスエラーになってしまったのでそのまま手打ちにしている。他のところは、別の機会でもう一度検証してみる。

locationディレクティブのデフォルト設定に対して、Apacheに転送する共通confファイルをincludeする。

proxy_passディレクティブにはApacheで指定したポート(8080)を後ろに付けておくこと。

indexディレクティブには以下のように、パスを指定することも可能。

  location /2024open/ {
    index index.html index.php /coming_soon.html;
  }
SSL化したときのproxy_pass

proxy_passのURLは「http」のままにする。(ただしSSLの設定の仕方によるかも)

/etc/nginx/sites-enabledにドメイン個別設定ファイルのリンボリックリンクを作成する

ln -s /etc/nginx/sites-available/hoge.example.com /etc/nginx/sites-enabled/hoge.example.com

/etc/nginx/sites-enabledにシンボリックリンクを作成したあとNginxを再起動するとドメイン個別設定が反映される。

サイトを一時的に非公開もしくは無効にしたいときは、/etc/nginx/sites-enabledの中にある対象ドメインのシンボリックリンクを削除してNginxを再起動する。設定ファイルそのものは/etc/nginx/sites-available側に残っているのですぐに再公開できる。

ドメイン統一の設定方法

example.comをwwwなしにドメイン統一するなら、wwwありのファイルは以下のように作成する。

server {
  listen 80;
  listen [::]:80;
  server_name www.example.com;
  access_log /var/log/nginx/domain/example.com/www_access.log main;
  error_log /var/log/nginx/domain/example.com/www_error.log debug;

  location / {
    rewrite ^(.*)$ http://example.com$1 permanent;
  }
}

リダイレクト先はwwwなしの方を指定する。

「listen [::]:80;」というのはipv6のポート設定。

Apache:VirtualHost設定

VirtualHostディレクティブにはApacheで指定したポート(8080)を後ろに付けておくこと。

<VirtualHost *:8080>
  ServerName hoge.example.com
  DocumentRoot /home/hogehoge-user/public_html/example.com/sub/hoge/www
  CustomLog logs/domain/example.com/hoge__access.log combined
  ErrorLog logs/domain/example.com/hoge__error.log
  DirectoryIndex index.html index.php
  AddDefaultCharset UTF-8

  <Directory /home/hogehoge-user/public_html/example.com/sub/hoge/www>
    Require all granted
  </Directory>
</VirtualHost>

DirectoryIndexディレクティブの設定はNginx側と合わせないとWEB表示がおかしくなるので注意する。

Directoryディレクティブには「Require all granted」を入れてアクセスを許可する。この記述がないとWEBサイトは表示されているけれどステータスコードが403になったり一部の表示が崩れる恐れもある。

余談:403エラーの原因が発覚したときのこと

私はDirectoryディレクティブに「Require all granted」を入れないといけないことを知らなかったので、以下の記事を見つけて偶然にも助かった笑

SELinuxが原因で403になることもある模様。同様の問題に出会したときのために参考リンクとして貼っておく。

余談:当時の検証

根本たる原因はDirectoryディレクティブの設定だったが、当時の検証を何かあったときに後々読み返すものとしてメモしておく。

ApacheのsuEXECを無効にする

Apache側のエラーログを確認すると「suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)」というエラーを発見。
もしかするとsuEXECが引っかかっているかもしれないと思い、suEXECを無効化してみることに。

apacheのsuEXECを無効にするには「/usr/sbin/suexec」を削除もしくはリネームする。
私は何かやらかした時が怖いのでリネームにした。(suEXECが根本たる原因ではなかったのですぐ復元できてホッとした)

mv /usr/sbin/suexec /usr/sbin/bk__suexec

httpd(apache)を再起動かけることでsuEXECが無効になる。

httpdを再起動して設定を反映したけれど、原因ではなかったので最終名前を戻して有効にする。

mv /usr/sbin/bk__suexec /usr/sbin/suexec

httpd_can_network_connect

httpd_can_network_connectを設定していないのが悪いかも?と思い、httpd_can_network_connectを有効にしてみることに。

httpd_can_network_connect     スクリプトやモジュールからのネットワーク接続を許可
https://www.tohoho-web.com/ex/selinux.html

まずは以下のコマンドで、SELinuxのhttpdのルールには何があるのかを確認する。

semanage boolean -l | grep httpd_

オフ状態のhttpd_can_network_connectが見つかったので有効にする。

setsebool httpd_can_network_connect on -P

httpdを再起動して設定を反映したけれど、原因ではなかったので最終無効に戻す。

setsebool httpd_can_network_connect off -P

Apache:ログフォーマットで%h(リモートホスト)を変更する

Nginxをリバースプロキシに使用したため、Apacheの通常のログフォーマットだと全てのアクセスでリモートホストのところにサーバーIPアドレスが入ってしまう。正しくアクセス解析できないだけでなく、APIキーを使った登録でエラーが出る恐れがある。
※当時の私の環境ではリモートホストを正確に取得していなかっため、WordPress有料テーマのAPIキーの登録でエラーが発生していた。

正確なリモートホストを取得するよう「%h」ではなく「%{X-Forwarded-For}i」を使用する。

/etc/httpd/conf/httpd.confの設定を見直す。

修正箇所は以下の3つ。

# LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
# LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common
# LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio