Apacheと環境変数

ApacheのVirtualHostのServerNameに環境変数から作る文字列を入れたかった。
ヘルスチェックなどでhttp://hostsに記載されたサーバのホスト名/でアクセスしたいとき、各サーバによってホスト名が異なるため、ServerNameには各サーバで別の値が設定されるべきだが、各サーバで設定をそろえるためにはServerNameに環境変数を入れることで対応する。

Apacheに環境変数を渡すには、/etc/sysconfig/httpdでexportする必要がある。

$ sudo sh -c 'echo "export HTTPD_HOST=\\`hostname\\`" >> /etc/sysconfig/httpd'
$ tail -1 /etc/sysconfig/httpd
export HTTPD_HOST=`hostname`

渡された環境変数は、httpd.conf内で${環境変数}で参照できる。前後に文字列をつけることもできる。全体をダブルクォーテーションで囲ってもOK。

<VirtualHost *:80>
  ServerName ${HTTPD_HOST}_global
  DocumentRoot /var/www/html
  (略)
</VirtualHost>

ServerNameの変更だけであれば、service httpd gracefulで設定が反映できるが、/etc/sysconfig/httpdで設定した環境変数をApacheに渡すには、Apacheを再起動しなければいけないので、service httpd restartを実行する。

$ cat /etc/hosts
192.168.1.2      http0001
xxx.xxx.xxx.xxx  http0001_global

$ curl -s --head http://http0001_global/ | head -1
HTTP/1.1 200 OK

Apacheとワイルドカード

環境変数を渡す方法の欠点は、httpd.confだけでなく/etc/sysconfig/httpdにも設定が必要なことと、それゆえApacheの再起動が必要なことにある。
ApacheのServerNameではワイルドカードが使えないが、ServerAliasでは使えるので、ワイルドカードで対応する方法も対応方法として考えておくといい。
各サーバの名前が、http0001からの連番方式などであれば、ワイルドカードがhttp????であればヒットする。正規表現が使えないので数値と文字の区別をつけることはできないが、そこは妥協するしかない。

<VirtualHost *:80>
  ServerAlias http????_global
  DocumentRoot /var/www/html
  (略)
</VirtualHost>

Nginxとhostname

Nginxの場合、サーバ名が$hostnameに設定されている。server_nameに変数を設定することはできないし、環境変数を扱うのも追加のmoduleが必要だが、$hostnameは固定値のようなもので、これだけはserver_nameに設定できる。

server {
    listen       80;
    listen       localhost:80;
    server_name  $hostname;
    root         /var/www/html;
    略
}

nginx.confの変更のみなので、設定後service nginx reloadを実施すればいい。

しかし今回の例だと、/etc/hostsに記載されたhost名_globalをドメインに使用している。"${hostname}_global"のように文字列を付け加えることはできない。

Nginxと正規表現

host名そのままの場合は$hostnameで大丈夫だが、今回の例に対応するために正規表現を使う。NginxはApacheと異なり、server_nameに正規表現を使用することができ、より正確で柔軟なマッチングができる。

server {
    listen       80;
    listen       localhost:80;
    server_name  "~^http[0-9]{4}_global$";
    root         /var/www/html;
    略
}

Nginxの正規表現は基本的にダブルクォーテーションでくくる必要はないが、量指定子{}を使う場合はダブルクォーテーションが必要。