やりたかったこと

nginxの設定でURLごとに別々の処理をしたかった。 /api/ のパスだけバックエンドに転送して、それ以外は静的ファイルを返す設定を書こうとしたらlocationの書き方で詰まった。

locationディレクティブの種類

完全一致(= 修飾子)

location = /favicon.ico {
    log_not_found off;
    access_log off;
}
  • URLが完全に一致した場合だけマッチする
  • 優先度が最も高い
  • faviconやrobots.txtのログを抑制するのによく使う

前方一致(修飾子なし)

location /api/ {
    proxy_pass http://localhost:3000;
}
  • /api/ から始まるすべてのURLにマッチする
  • 設定がシンプルで一番よく使う

前方一致優先(^~ 修飾子)

location ^~ /static/ {
    root /var/www;
}
  • マッチしたら正規表現ブロックの評価をスキップする
  • 静的ファイルを正規表現より優先したい時に使う

正規表現(~ または ~* 修飾子)

# 大文字小文字を区別する
location ~ \.php$ {
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    include fastcgi_params;
}

# 大文字小文字を区別しない
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
    expires 30d;
    access_log off;
}
  • ~ は大文字小文字を区別する
  • ~* は区別しない
  • 画像・CSS・JSなどの静的ファイルキャッシュ設定によく使う

マッチの優先順位

  1. = 完全一致(最優先)
  2. ^~ 前方一致優先(正規表現をスキップ)
  3. ~ または ~* 正規表現(定義順で評価)
  4. 修飾子なしの前方一致(最長一致)

よく使う設定例

PHPアプリとAPIの振り分け

server {
    listen 80;
    server_name example.com;
    root /var/www/html;

    location = / {
        index index.php;
    }

    location /api/ {
        proxy_pass http://localhost:3000/;
        proxy_set_header Host $host;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
    }
}

静的ファイルのキャッシュ設定

location ~* \.(jpg|jpeg|png|gif|ico|svg|css|js|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

ハマったポイント

  • = は完全一致なので /favicon.ico/ のようなスラッシュ付きにはマッチしない
  • 正規表現ブロックは定義した順番で評価されるので、より厳密なパターンを先に書く
  • proxy_pass の末尾スラッシュの有無でパスの扱いが変わる(/api/foo/foo になる場合がある)
  • location をネストする時は aliasroot の違いに注意(alias はパスを置換する)
  • 設定変更後は nginx -t でテストしてから systemctl reload nginx するのが安全

関連記事

おすすめのVPS/ドメイン/スクール

VPSを使って本番環境を構築するなら、以下のサービスがおすすめです。