Nginxで複数サービスを公開する設定

WordPress、Redmine、GitLabなど1サーバで複数サービス利用したい。そう思ってしまいました。

このブログサーバ、数か月アクセスしてもエラーになっていました。理由はNginxでWordPressだとかGitLabなんかを公開してどこからでもアクセスできるようにしたいという目的のために、設定をゴロゴロと変えていたからです。昨日やっと上手くいきました。

正直最初はイライラしながらやっていたので、金輪際このストレスから解放されるためにここに記録したいと思います。

構成

1ドメインに対して、複数サイト公開する形式です。すなわちファイルパスでサービスを切り替えることになります。

べつに、DNSサーバを立ち上げたことがないから面倒だとか、SSLの契約を変えるのが面倒だなんて言ってないし、そんなお金がないとも言ってない…。ただの時短と倹約です。

 

イメージはこんな感じです。プロトコルもドメインも同じですが、サービスごとに異なるファイルパスを用意してます。

WordPress: https://domain.com/wordpress/

Redmine: https://domain.com/redmine/

GitLab: https://domain.com/gitlab/

 

ちなみにですが、仮にサービスごとにドメインを分けた場合、ドメインごとSSLを契約またはサブドメインもサポートするSSLを契約する必要があります。さくらのSSLの場合(掲載時点)ですが、個別のSSL契約だと990円・サブドメインサポートだと18,150円もします。ぶっちゃけ個別に契約するのは面倒だし、サブドメインサポートは高すぎる。よってファイルパスで分けたかったわけです。

サブドメインのwordpress等は、以下の例では”domain.com”の部分さえ契約して自分でDNS立てれば用意できるので、1ドメインの契約だけで済むのでその点では安く済みます。です。

WordPress: https://wordpress.domain.com/

Redmine: https://redmine.domain.com/

GitLab: https://gitlab.domain.com/

上手くいった設定内容

SSLの記述は気にしないで忘れてください。

 

以下設定の0番はWordPressの設定だからと入れ子にしてみました。後々見たら推奨されていない設定でした。ここで/wp/としても中でも/wp/と書く必要があり、正直面倒だと思いました。

1番は設定ファイルを参照できないようにしています。

2番はファイルではなくディレクトリにアクセスされた場合にindex.phpにリダイレクトする設定にします。/wp/は/wp/index.phpへ、/wp/admin/だと/wp/admin/index.phpへアクセスすることになります。

3番はPHP実行に必要なCGI設定行います。それに加えて、/wp/index.phpにアクセスされた場合/path/to/app/wp/index.phpではなく、/path/to/app/index.phpにアクセスするように設定しています。

4番はCSSやJSのファイルをインクルードするために記述しています。

 

http {
    # 間はすっ飛ばす
    server {
        root /path/to/app/
        
        # SSL
        ssl_certificate "サーバ証明書(.crt)";
        ssl_certificate_key "サーバ証明書のキー";
        ssl_password_file "サーバ証明書のパスワード";
        
        #その他...
        
        # 0. WordPressの場合
        location ^~ /wp/ {
            root /path/to/app/blog/
            
            # 1. access deny config file.
            location = /wp/wp-config.php {
                deny all;
            }
            
            # 2. redirect to index.php, In default
            location ~ /wp/(|.+/)$ {
                rewrite ^(.*)$ $1/index.php;
            }
            
            # 3. execute php file(CGI)
            location ~ /wp/.+\.php.* {
              rewrite /wp/(.*)$ /$1 break;
              include fastcgi.conf;
              fastcgi_pass   unix:/run/php-fpm/www.sock;
            }
            
            # 4. CSS/JS etc.
            location ~ /wp/.+(?!php)$ {
              rewrite /wp/(.*)$ /$1 break;
            }
        }
    }
}

それに加えて、”wp-config.php”の”WP_HOME”と”WP_SITEURL”もファイルパスを明示的に記しておきます。

define('WP_HOME','https://domain.com/wordpress/');
define('WP_SITEURL','https://domain.com/wordpress/')

何故、当初上手くいかなかったのか

  • 2番のリダイレクト設定

リクエストのファイルパスがファイルではなくディレクトリだった場合にindex.phpにリダイレクトしている設定です。

最初ここを”rewrite ^(.*)$ $1/index.php$is_args$args;”にしていました。この設定だとリダイレクト先URLとファイルパスが以下の内容になってしまいます。

URL:”http://domain.com/index.php?p=100?p=100″

ファイルパス:”index.php?p=100″ ↞こんなファイルパスあるわけがない。

そしてこれはブラウザ側には知らされないし、デフォルトだとNginxのログにも表示されません。全く気付かずに永遠と時間を過ごしてしまいました。

 

気づけたのはNginxのログをデバッグモードにしたおかげです。そこで上のような妙なURLとファイルパスが出力されていたわけです。

デバッグモードは”error_log”の末尾に”debug”を追記し、詳細いなログを出したい”server”ディレクティブに”rewrite_log on;”を追記するだけでした。

error_log /var/log/nginx/error.log debug;

http {
    server {
        rewrite_log on;
        
        # その他
    }
}
  • PHP実行時のリダイレクト設定

“root”とリクエストのファイルパスが単純につなげ合わせたものと異なっていたため、各サービス用のファイルパスは削除するように仕向けなければなりません。

設定内容が

root: /path/to/app/blog/
リクエスト: http://domain.com/wordpress/index.php
の場合、設定がなければアクセスするファイルパスは
/path/to/app/blog/wordpress/index.php
になります。
今回用意したファイルパスは
/path/to/app/blog/index.php
のため、間の”/wordpress”を削除されるべきです。
よって最終的に3番で正規表現を用いて削除しているわけなのです。

 

これは4番でCSSなどにも適用しています。

今後の展望

GrafanaZabbix、Redmineなどをこの設定を用いて公開していこうと思う。

ちなみに他にAnsibleやTerraformにも興味あり。

コメントを残す