tl;dr
access_log
には変数を使えるけど制約が多い。error_log
には使えない。ホスト名の数だけ server
directiveを列挙した方が早そう。
nginx 1.21.1 で確認した。
変数を使えるかどうか
表題のことが気になったので調べた。部内k8sクラスタにアプリケーションをデプロイする際に、ホスト名を列挙するだけで同じようなnginxの設定を反映できるようにしたい、そしてアクセスログやエラーログをホスト名ごとに分けたい、という経緯である。つまり以下のように書けるとありがたい。
server { listen [::]:443 ssl http2; server_name host-a.example.com host-b.example.com; access_log /var/log/nginx/$host.access.log main; error_log /var/log/nginx/$host.error.log; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://upstream; } }
access_log
http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log を見ると、ファイル名に変数を使うことができるように読める。ただし制約がいろいろある。とくに、nginxを動かすuserがログファイルの出力先ディレクトリに書き込み可能でなければならない、という制約に引っかかった。/var/log/nginx
の所有者が root:root
で、パーミッションが700のときに、nginxを www-data
userなどで動かしているとアクセスログが出力されない。
error_log
http://nginx.org/en/docs/ngx_core_module.html#error_log を見ると access_log
とは違って変数に対する言及がなく、使えなさそう。実際、先述のようなnginx.confを反映したら /var/log/nginx/$host.error.log
というファイルができていた……。
最終的にどうしたか
ホスト名を列挙しておいて、ホスト名の数だけ server
directiveを展開するようにした。具体的には、以下のようなitamae recipeを反映した。
node.reverse_merge!( nginx_hosts: %w[ host-a.example.com host-b.example.com ], # 中略 ) template '/etc/nginx/conf.d/multiple-hosts.conf' do owner 'root' group 'root' mode '0644' notifies :reload, 'service[nginx]' end
templates/etc/nginx/conf.d/multiple-hosts.conf
は以下のような内容になっている。
<% node[:nginx_hosts].each do |host| -%> server { listen [::]:443 ssl http2; server_name <%= host %>; access_log /var/log/nginx/<%= host %>.access.log main; error_log /var/log/nginx/<%= host %>.error.log; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://upstream; } } <% end -%>