この記事の要点
• nginx -tで設定テスト、nginx -s reloadでゼロダウンタイムリロード
• server/locationブロックでバーチャルホストとURLルーティングを定義
• リバースプロキシ・TLS終端・キャッシュ・レート制限を1台でカバー
概要
Nginx は高性能な HTTP サーバー兼リバースプロキシです。イベント駆動アーキテクチャにより少ないリソースで大量の同時接続を捌けるため、静的ファイル配信、リバースプロキシ、ロードバランサ、API ゲートウェイ、TLS 終端などで広く採用されています。本チートシートでは、現行安定版(1.26 系)で利用できる設定ディレクティブと運用コマンドを整理します。
ファイル構成
| パス | 説明 |
|---|---|
/etc/nginx/nginx.conf | メイン設定 |
/etc/nginx/conf.d/*.conf | 追加設定(include される) |
/etc/nginx/sites-available/ | サイト定義(Debian 系) |
/etc/nginx/sites-enabled/ | 有効化シンボリックリンク |
/var/log/nginx/access.log | アクセスログ |
/var/log/nginx/error.log | エラーログ |
/var/run/nginx.pid | PID ファイル |
運用コマンド
| コマンド | 説明 |
|---|---|
nginx | サーバー起動 |
nginx -s stop | 即時停止 |
nginx -s quit | グレースフル停止 |
nginx -s reload | 設定リロード |
nginx -s reopen | ログファイルを再オープン |
nginx -t | 設定ファイルのテスト |
nginx -T | 設定全体をダンプ |
nginx -v | バージョン |
nginx -V | ビルドオプション含む詳細 |
nginx -c <file> | 設定ファイル指定 |
nginx -p <prefix> | プレフィックス指定 |
systemctl reload nginx | systemd 経由でリロード |
systemctl restart nginx | systemd 経由で再起動 |
journalctl -u nginx | systemd ログ確認 |
ポイント: 設定変更のワークフローは「編集 → nginx -t(テスト) → nginx -s reload(反映)」の3ステップ。テストを飛ばすと本番が停止するリスクがあります。
設定ファイル基本構造
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
server / location ブロック
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /static/ {
alias /var/www/example/static/;
expires 30d;
access_log off;
}
location = /healthz {
return 200 "ok\n";
add_header Content-Type text/plain;
}
}
location マッチング
| 修飾子 | マッチ |
|---|---|
= | 完全一致(最優先) |
^~ | 前方一致でこの位置より下を探索しない |
~ | 正規表現(大文字小文字区別) |
~* | 正規表現(大文字小文字区別なし) |
| なし | 前方一致 |
優先順位: = → ^~ → 正規表現 → 通常前方一致。
注意: locationのマッチ優先順位は「= → ^~ → 正規表現 → 通常前方一致」です。意図しないマッチを避けるため、優先順位を理解しておきましょう。
リバースプロキシ
upstream app {
server 127.0.0.1:3000;
server 127.0.0.1:3001 weight=2;
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
ロードバランシング方式
| ディレクティブ | 説明 |
|---|---|
| 既定(round-robin) | 順番に振り分け |
least_conn | 接続数が最も少ないサーバへ |
ip_hash | クライアント IP でハッシュ |
hash <key> | 任意のキーでハッシュ |
random | ランダム |
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
server backup.example.com backup;
}
実践メモ: リバースプロキシではproxy_set_header Host $hostを必ず設定。バックエンドのバーチャルホスト解決に必要です。
HTTPS / TLS
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
root /var/www/example;
index index.html;
}
# HTTP → HTTPS リダイレクト
server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}
注意: HSTSヘッダを一度設定すると、ブラウザは指定期間HTTPSを強制します。テスト環境ではmax-ageを短くするか、設定しないようにしましょう。
ポイント: server_tokens offでNginxのバージョン情報を隠しましょう。セキュリティの基本対策として必須です。
キャッシュ
静的ファイルキャッシュ
location ~* \.(?:css|js|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
プロキシキャッシュ
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m
max_size=1g inactive=60m use_temp_path=off;
server {
location / {
proxy_cache app_cache;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://app;
}
}
レート制限
limit_req_zone $binary_remote_addr zone=api_rl:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_lim:10m;
server {
location /api/ {
limit_req zone=api_rl burst=20 nodelay;
limit_conn conn_lim 20;
proxy_pass http://app;
}
}
アクセス制御
location /admin/ {
allow 10.0.0.0/8;
allow 192.168.1.0/24;
deny all;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
.htpasswd 作成: htpasswd -c /etc/nginx/.htpasswd admin
URL 書き換え / リダイレクト
# 恒久リダイレクト
return 301 https://example.com$request_uri;
# 旧 URL を新 URL に
location = /old { return 301 /new; }
# rewrite ディレクティブ
rewrite ^/blog/(\d+)/(.+)$ /posts/$1-$2 permanent;
# 末尾スラッシュなしを付与
rewrite ^([^.]*[^/])$ $1/ permanent;
WebSocket プロキシ
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
location /ws/ {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
}
}
gzip / brotli
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain text/css text/xml
application/json application/javascript application/xml+rss
application/atom+xml image/svg+xml;
ログ
log_format combined_ext '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'urt="$upstream_response_time"';
access_log /var/log/nginx/access.log combined_ext buffer=32k flush=5s;
error_log /var/log/nginx/error.log warn;
エラーログレベル: debug info notice warn error crit alert emerg
よく使う変数
| 変数 | 説明 |
|---|---|
$host | リクエストのホスト名 |
$remote_addr | クライアント IP |
$request_uri | クエリを含むリクエスト URI |
$uri | 正規化された URI |
$args / $query_string | クエリ文字列 |
$arg_<name> | 個別のクエリパラメータ |
$http_<header> | 任意のリクエストヘッダ |
$cookie_<name> | クッキー値 |
$scheme | http / https |
$request_method | GET / POST など |
$status | レスポンスコード |
$body_bytes_sent | 送信ボディサイズ |
$request_time | リクエスト処理時間(秒) |
$upstream_response_time | upstream の応答時間 |
$upstream_cache_status | キャッシュヒット状況 |
実用例
1. SPA ルーティング(React / Vue)
location / {
try_files $uri $uri/ /index.html;
}
2. CORS ヘッダ
location /api/ {
add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
if ($request_method = OPTIONS) { return 204; }
proxy_pass http://app;
}
3. メンテナンスモード
set $maint 0;
if (-f /etc/nginx/maintenance.flag) { set $maint 1; }
if ($maint = 1) { return 503; }
error_page 503 /maintenance.html;
location = /maintenance.html { root /var/www/errors; internal; }
4. ヘッダで条件分岐
map $http_user_agent $is_bot {
default 0;
~*(bot|crawl|spider) 1;
}
5. リアル IP(プロキシ後段)
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
6. ファイルアップロード上限
client_max_body_size 50m;
client_body_timeout 60s;
7. ヘルスチェックエンドポイント
location = /healthz {
access_log off;
add_header Content-Type text/plain;
return 200 "ok\n";
}
8. デバッグ用に変数を返す
location = /debug {
default_type text/plain;
return 200 "host=$host ip=$remote_addr ua=$http_user_agent\n";
}
よく使うオプション早見表
| ディレクティブ | 文脈 | 用途 |
|---|---|---|
worker_processes | main | ワーカープロセス数 |
worker_connections | events | 1 ワーカーあたり最大接続 |
keepalive_timeout | http/server | keep-alive 維持時間 |
client_max_body_size | http/server/location | リクエストボディ上限 |
proxy_pass | location | バックエンド転送先 |
try_files | location | 順にファイルを試す |
return | server/location | ステータス返却 |
rewrite | server/location | URL 書き換え |
add_header | server/location | レスポンスヘッダ追加 |
expires | location | キャッシュ有効期限 |
deny / allow | location | アクセス制御 |
limit_req | location | リクエストレート制限 |
実践メモ: $upstream_cache_statusをレスポンスヘッダに追加すると、HIT/MISS/EXPIREDなどキャッシュの状態を確認でき、デバッグに便利です。
トラブルシューティング
| 症状 | 原因と対処 |
|---|---|
nginx: [emerg] bind() to 0.0.0.0:80 failed | ポート競合。ss -ltnp で確認 |
| 設定変更が反映されない | nginx -t && nginx -s reload を実行 |
| 502 Bad Gateway | upstream 停止またはタイムアウト。error.log を確認 |
| 504 Gateway Timeout | proxy_read_timeout を調整 |
| 413 Request Entity Too Large | client_max_body_size を引き上げ |
| 静的ファイルが配信されない | root / alias の指定を確認 |
| HTTPS 証明書エラー | ssl_certificate のフルチェーンを使用 |
access_log が更新されない | nginx -s reopen でファイル再オープン |
Tips & ベストプラクティス
- 設定変更前後で必ず
nginx -tを実行し、構文エラーで停止しないようにする。 - リロードは
nginx -s reload(ゼロダウンタイム)を使い、restartは最終手段にする。 server_tokens offでバージョン情報を隠す。add_headerは同じブロックで一度でも宣言すると親の宣言が無視されるため、共通ヘッダは include で集約する。- セキュリティヘッダ(HSTS、CSP、X-Content-Type-Options)は HTTPS で必ず付与する。
- リバースプロキシでは
proxy_set_header Host $hostを忘れない。バックエンドの仮想ホスト解決に必要。 - 静的アセットは
expiresとimmutableでブラウザキャッシュを最大化する。 - ログローテーションは
logrotateとnginx -s reopenを組み合わせる。 - 大量同時接続には
worker_connectionsと OS のnofile上限を一緒に上げる。 - TLS は
ssl_protocols TLSv1.2 TLSv1.3のみを許可し、古い SSL/TLS は無効化する。