- Authors
- Name
- 1. Nginxアーキテクチャと設定構造
- 2. Virtual Host / Server Block設定
- 3. リバースプロキシ設定
- 4. ロードバランシング
- 5. SSL/TLS設定
- 6. キャッシング設定
- 7. Rate LimitingとConnection Limiting
- 8. Gzip/Brotli圧縮
- 9. セキュリティヘッダー
- 10. アクセス制御(Access Control)
- 11. ログ設定
- 12. パフォーマンスチューニング
- 13. URLリライティングとリダイレクション
- 14. 静的ファイル配信最適化
- 15. ヘルスチェックとモニタリング
- 総合プロダクション設定チェックリスト
- 参考資料
1. Nginxアーキテクチャと設定構造
1.1 イベント駆動アーキテクチャ:Master-Workerモデル
Nginxは、Apache httpdのプロセス/スレッドベースモデルとは根本的に異なるイベント駆動(Event-Driven)アーキテクチャを採用した。この設計哲学こそが、Nginxが単一サーバーで数十万の同時接続を処理できる核心的な理由である。
┌─────────────────────────────────────────────────────────┐
│ Master Process │
│ - 設定ファイルの読み込みと検証 │
│ - Workerプロセスの生成/管理 (fork) │
│ - ポートバインディング (80, 443) │
│ - シグナル処理 (reload, stop, reopen) │
└─────────┬───────────┬───────────┬───────────┬───────────┘
│ │ │ │
┌─────▼─────┐ ┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│ Worker 0 │ │Worker 1│ │Worker 2│ │Worker 3│
│ Event Loop │ │ ... │ │ ... │ │ ... │
│ epoll/kq │ │ │ │ │ │ │
│ 数千 conn │ │ │ │ │ │ │
└───────────┘ └────────┘ └────────┘ └────────┘
Master Processはroot権限で実行され、設定ファイルのパース、ポートバインディング、Workerプロセスの管理を担当する。fork()システムコールでWorkerを生成し、設定リロード時には既存の接続を切断せずに新しいWorkerを起動した後、既存のWorkerをgraceful shutdownする。
Worker Processは実際のクライアントリクエストを処理する核心的なユニットである。各Workerは独立したイベントループを運営し、OSのI/O多重化メカニズム(Linuxではepoll、FreeBSD/macOSではkqueue)を活用してブロッキングなしに数千の接続を同時に処理する。コネクションごとにスレッドを割り当てる方式と比較して、コンテキストスイッチとメモリオーバーヘッドが劇的に削減される。
1.2 nginx.conf 設定コンテキスト構造
Nginxの設定は階層的コンテキスト(Context)構造に従う。子コンテキストは親の設定を継承し、同じディレクティブを子で再宣言するとオーバーライドされる。
# ============================================
# Main Context(グローバル設定)
# ============================================
user nginx; # Workerプロセス実行ユーザー
worker_processes auto; # CPUコア数に合わせてWorkerを生成
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
# ============================================
# Events Context(接続処理設定)
# ============================================
events {
worker_connections 1024; # Worker当たりの最大同時接続数
multi_accept on; # 一度に複数の接続を受け入れる
use epoll; # Linuxでepollを使用(デフォルト)
}
# ============================================
# HTTP Context(HTTPプロトコル設定)
# ============================================
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# ========================================
# Server Context(仮想ホスト)
# ========================================
server {
listen 80;
server_name example.com;
# ====================================
# Location Context(URLパスマッチング)
# ====================================
location / {
root /var/www/html;
index index.html;
}
location /api/ {
proxy_pass http://backend;
}
}
}
# ============================================
# Stream Context(TCP/UDPプロキシ、L4)
# ============================================
stream {
server {
listen 3306;
proxy_pass mysql_backend;
}
}
コンテキスト階層のまとめ:
| コンテキスト | 位置 | 役割 |
|---|---|---|
| Main | 最上位 | グローバル設定 (user, worker, pid, error_log) |
| Events | Main内部 | 接続処理メカニズム (worker_connections) |
| HTTP | Main内部 | HTTPプロトコル関連の全体設定 |
| Server | HTTP内部 | 仮想ホスト(ドメイン別設定) |
| Location | Server内部 | URLパス別リクエスト処理ルール |
| Upstream | HTTP内部 | バックエンドサーバーグループ(ロードバランシング) |
| Stream | Main内部 | TCP/UDP L4プロキシ |
1.3 設定ファイル構造化のベストプラクティス
プロダクション環境では、単一のnginx.confにすべての設定を入れるのではなく、モジュール化して管理する。
/etc/nginx/
├── nginx.conf # メイン設定(includeで分離)
├── conf.d/ # 共通設定スニペット
│ ├── ssl-params.conf # SSL/TLS共通パラメータ
│ ├── proxy-params.conf # リバースプロキシ共通ヘッダー
│ ├── security-headers.conf # セキュリティヘッダー
│ └── gzip.conf # 圧縮設定
├── sites-available/ # サイト別設定ファイル
│ ├── example.com.conf
│ ├── api.example.com.conf
│ └── admin.example.com.conf
├── sites-enabled/ # 有効化されたサイト(シンボリックリンク)
│ ├── example.com.conf -> ../sites-available/example.com.conf
│ └── api.example.com.conf -> ../sites-available/api.example.com.conf
└── snippets/ # 再利用可能な設定フラグメント
├── letsencrypt.conf
└── fastcgi-php.conf
# nginx.conf メインファイル
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}
2. Virtual Host / Server Block設定
NginxのServer BlockはApacheのVirtual Hostに相当し、一つのサーバーで複数のドメインをホスティングできるようにする。
2.1 基本Server Block設定
# /etc/nginx/sites-available/example.com.conf
# ── プライマリドメイン ──
server {
listen 80;
listen [::]:80; # IPv6対応
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm;
# ドメイン別にアクセスログを分離
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
}
# ── セカンドドメイン ──
server {
listen 80;
listen [::]:80;
server_name blog.example.com;
root /var/www/blog.example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
2.2 Default Server(catch-all)
定義されていないドメインへのリクエストを処理するデフォルトサーバーブロックである。セキュリティのため、444(接続切断)で応答することが推奨される。
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _; # すべての未マッチドメイン
# 定義されていないホストリクエストは即座に接続を終了
return 444;
}
2.3 Server Nameマッチング優先順位
Nginxはserver_nameマッチング時に以下の優先順位に従う:
- 正確な名前:
server_name example.com - 前方ワイルドカード:
server_name *.example.com - 後方ワイルドカード:
server_name example.* - 正規表現:
server_name ~^(?<subdomain>.+)\.example\.com$ - default_server: 上記すべてが未マッチの場合
# 正規表現でサブドメインをキャプチャ
server {
listen 80;
server_name ~^(?<subdomain>.+)\.example\.com$;
location / {
root /var/www/$subdomain;
}
}
2.4 サイトの有効化/無効化
# サイト有効化
sudo ln -s /etc/nginx/sites-available/example.com.conf \
/etc/nginx/sites-enabled/example.com.conf
# 設定検証
sudo nginx -t
# リロード(無停止)
sudo systemctl reload nginx
3. リバースプロキシ設定
3.1 基本リバースプロキシ
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
# ── 必須プロキシヘッダー ──
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 X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
各ヘッダーの役割:
| ヘッダー | 目的 |
|---|---|
Host | 元のリクエストのHostヘッダーを転送 |
X-Real-IP | 実際のクライアントIP(プロキシ経由で元のIPを識別) |
X-Forwarded-For | プロキシチェーンを経由して蓄積されるクライアントIPリスト |
X-Forwarded-Proto | 元のプロトコル(http/https)―バックエンドでリダイレクト判断 |
X-Forwarded-Host | 元のHostヘッダー |
X-Forwarded-Port | 元のポート |
3.2 再利用可能なプロキシパラメータスニペット
# /etc/nginx/conf.d/proxy-params.conf
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 X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_http_version 1.1;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffering on;
# Server Blockでincludeして再利用
location / {
proxy_pass http://backend;
include /etc/nginx/conf.d/proxy-params.conf;
}
3.3 WebSocketプロキシ
WebSocketはHTTP Upgradeメカニズムを使用するため、UpgradeとConnectionのホップバイホップヘッダーを明示的に転送する必要がある。Nginxはデフォルトでこれらのヘッダーをフォワーディングしない。
# ── mapでConnectionヘッダーを動的設定 ──
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name ws.example.com;
location /ws/ {
proxy_pass http://127.0.0.1:8080;
# WebSocket必須設定
proxy_http_version 1.1; # HTTP/1.1必須(Upgrade対応)
proxy_set_header Upgrade $http_upgrade; # クライアントのUpgradeヘッダーを転送
proxy_set_header Connection $connection_upgrade; # 動的Connectionヘッダー
# 一般プロキシヘッダー
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocketは長時間接続のためタイムアウトを延長
proxy_read_timeout 86400s; # 24時間(デフォルト60秒ではidle接続が切断される)
proxy_send_timeout 86400s;
}
}
3.4 パスベースルーティング(マイクロサービス)
server {
listen 80;
server_name api.example.com;
# ユーザーサービス
location /api/users/ {
proxy_pass http://user-service:3001/; # 末尾の/に注意:/api/users/を除去して転送
include /etc/nginx/conf.d/proxy-params.conf;
}
# 注文サービス
location /api/orders/ {
proxy_pass http://order-service:3002/;
include /etc/nginx/conf.d/proxy-params.conf;
}
# 決済サービス
location /api/payments/ {
proxy_pass http://payment-service:3003/;
include /etc/nginx/conf.d/proxy-params.conf;
proxy_read_timeout 120s; # 決済はタイムアウトを延長
}
}
注意:
proxy_passのURL末尾に/があると、locationにマッチした部分が除去される。/api/users/123リクエストがhttp://user-service:3001/123として転送される。/がない場合は全URIがそのまま転送される。
4. ロードバランシング
4.1 Upstreamブロックとアルゴリズム
# ============================================
# 1. Round Robin(デフォルト)
# リクエストを順次分配
# ============================================
upstream backend_roundrobin {
server 10.0.0.1:8080; # デフォルトweight 1
server 10.0.0.2:8080;
server 10.0.0.3:8080;
}
# ============================================
# 2. Weighted Round Robin(重み付きラウンドロビン)
# サーバー性能に応じた比率分配
# ============================================
upstream backend_weighted {
server 10.0.0.1:8080 weight=5; # リクエストの5/8
server 10.0.0.2:8080 weight=2; # リクエストの2/8
server 10.0.0.3:8080 weight=1; # リクエストの1/8
}
# ============================================
# 3. Least Connections(最小接続数)
# アクティブ接続数が最も少ないサーバーへ転送
# ============================================
upstream backend_leastconn {
least_conn;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
server 10.0.0.3:8080;
}
# ============================================
# 4. IP Hash(セッション固定)
# 同一クライアントIP → 同一サーバー
# ============================================
upstream backend_iphash {
ip_hash;
server 10.0.0.1:8080;
server 10.0.0.2:8080;
server 10.0.0.3:8080;
}
# ============================================
# 5. Generic Hash(カスタムハッシュ)
# 任意の変数に基づくハッシュ
# ============================================
upstream backend_hash {
hash $request_uri consistent; # URIベース + 一貫性ハッシュ
server 10.0.0.1:8080;
server 10.0.0.2:8080;
server 10.0.0.3:8080;
}
アルゴリズム選択ガイド:
| アルゴリズム | 適した場面 | 注意点 |
|---|---|---|
| Round Robin | ステートレスサービス、同一スペックサーバー | サーバースペック差がある場合は不均衡 |
| Weighted | サーバースペックが異なる場合 | ウェイトの手動管理が必要 |
| Least Connections | リクエスト処理時間のばらつきが大きい場合 | 短いリクエスト中心ならRound Robinと類似 |
| IP Hash | セッション固定が必要な場合(レガシーアプリ) | サーバー追加/削除時に再分配が発生 |
| Generic Hash | キャッシュ最適化(同一URI → 同一サーバー) | consistentハッシュを推奨 |
4.2 サーバーステータスとバックアップ
upstream backend {
least_conn;
server 10.0.0.1:8080; # 正常サーバー
server 10.0.0.2:8080; # 正常サーバー
server 10.0.0.3:8080 backup; # バックアップ:上記サーバーがすべてダウンした時に有効化
server 10.0.0.4:8080 down; # 無効化(メンテナンス)
server 10.0.0.5:8080 max_fails=3 fail_timeout=30s;
# max_fails=3: 30秒以内に3回失敗すると異常判定
# fail_timeout=30s: 異常判定後30秒間リクエスト除外
}
4.3 Keepaliveコネクションプール
バックエンドサーバーとのTCP接続を再利用して接続の確立/解除オーバーヘッドを削減する。
upstream backend {
server 10.0.0.1:8080;
server 10.0.0.2:8080;
keepalive 32; # 各Workerが維持するアイドルコネクション数
keepalive_requests 1000; # 1つのコネクションで処理する最大リクエスト数
keepalive_timeout 60s; # アイドルコネクション維持時間
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1; # keepaliveにはHTTP/1.1が必須
proxy_set_header Connection ""; # "close"の代わりに空値でkeepaliveを有効化
}
}
5. SSL/TLS設定
5.1 基本HTTPS設定
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.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; # TLS 1.0、1.1を無効化
# ── Cipher Suites(TLS 1.2用) ──
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off; # TLS 1.3ではoff推奨
# ── 楕円曲線 ──
ssl_ecdh_curve X25519:secp384r1:secp256r1;
# ── セッション再利用 ──
ssl_session_cache shared:SSL:10m; # 10MB = 約40,000セッション
ssl_session_timeout 1d; # セッション有効期間
ssl_session_tickets off; # Forward Secrecyを保証
root /var/www/example.com/html;
index index.html;
}
5.2 HTTP → HTTPSリダイレクト
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# すべてのHTTPリクエストをHTTPSに301リダイレクト
return 301 https://$host$request_uri;
}
5.3 HSTS (HTTP Strict Transport Security)
# HTTPS server block内に追加
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
max-age=63072000: 2年間HTTPSのみ使用(最低1年推奨)includeSubDomains: すべてのサブドメインにも適用preload: ブラウザのHSTS Preloadリスト登録資格always: エラーレスポンス(4xx、5xx)でもヘッダーを送信
5.4 OCSP Stapling
OCSP Staplingはサーバーが証明書の有効性検証を代行し、クライアントのCA直接照会を不要にする。初期接続速度が改善され、プライバシーが保護される。
ssl_stapling on;
ssl_stapling_verify on;
# OCSPレスポンス検証用の信頼チェーン(Let's Encrypt中間証明書を含む)
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# OCSPレスポンダー照会用DNSリゾルバ
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
5.5 プロダクションSSL統合スニペット
# /etc/nginx/conf.d/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_ecdh_curve X25519:secp384r1:secp256r1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Server Blockでinclude
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/nginx/conf.d/ssl-params.conf;
# ... 残りの設定
}
5.6 Let's Encrypt自動更新(Certbot)
# 証明書発行
sudo certbot --nginx -d example.com -d www.example.com
# 自動更新テスト
sudo certbot renew --dry-run
# Cron自動更新(certbotが既に設定するが、明示的に記載)
echo "0 0,12 * * * root certbot renew --quiet --deploy-hook 'systemctl reload nginx'" \
| sudo tee /etc/cron.d/certbot-renew
6. キャッシング設定
6.1 Proxy Cache(リバースプロキシキャッシュ)
# ── HTTP Contextでキャッシュパスを定義 ──
proxy_cache_path /var/cache/nginx/proxy
levels=1:2 # 2段階ディレクトリ構造(ファイル分散)
keys_zone=proxy_cache:10m # キャッシュキー格納用共有メモリ(1MB ≈ 8,000キー)
max_size=1g # ディスクキャッシュ最大サイズ
inactive=60m # 60分間未使用のキャッシュを削除
use_temp_path=off; # 一時ファイルパスを使用しない(直接書き込み → 性能向上)
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://backend;
proxy_cache proxy_cache; # キャッシュゾーンを指定
proxy_cache_valid 200 302 10m; # 200、302レスポンスを10分間キャッシュ
proxy_cache_valid 404 1m; # 404レスポンスを1分間キャッシュ
proxy_cache_use_stale error timeout
updating
http_500 http_502
http_503 http_504; # バックエンドエラー時にstaleキャッシュを提供
proxy_cache_lock on; # 同時リクエスト時に1つだけバックエンドへ
proxy_cache_min_uses 2; # 2回以上リクエストされたURLのみキャッシュ
# デバッグ用キャッシュステータスヘッダー
add_header X-Cache-Status $upstream_cache_status;
}
# キャッシュバイパス(管理者用)
location /api/ {
proxy_pass http://backend;
proxy_cache proxy_cache;
# Cookieにnocacheがある場合、またはヘッダーにCache-Control: no-cacheがある場合にバイパス
proxy_cache_bypass $http_cache_control;
proxy_no_cache $cookie_nocache;
}
}
X-Cache-Statusの値:
| ステータス | 意味 |
|---|---|
HIT | キャッシュから直接提供 |
MISS | キャッシュなし → バックエンドにリクエスト |
EXPIRED | 期限切れキャッシュ → バックエンドに再リクエスト |
STALE | 期限切れだがstaleポリシーで提供 |
UPDATING | 更新中にstaleキャッシュを提供 |
BYPASS | キャッシュバイパスされた |
6.2 FastCGI Cache(PHPなど)
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=fastcgi_cache:10m
max_size=512m
inactive=30m;
server {
listen 80;
server_name wordpress.example.com;
# キャッシュバイパス条件の定義
set $skip_cache 0;
# POSTリクエストはキャッシュしない
if ($request_method = POST) {
set $skip_cache 1;
}
# クエリストリングがある場合はキャッシュしない
if ($query_string != "") {
set $skip_cache 1;
}
# WordPress管理者ページのキャッシュ除外
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php") {
set $skip_cache 1;
}
# ログインユーザーのキャッシュ除外
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_cache fastcgi_cache;
fastcgi_cache_valid 200 30m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache_use_stale error timeout updating http_500;
add_header X-FastCGI-Cache $upstream_cache_status;
}
}
6.3 ブラウザキャッシング(静的リソース)
# ── 静的ファイルの長期ブラウザキャッシュ ──
location ~* \.(jpg|jpeg|png|gif|ico|webp|avif|svg)$ {
expires 30d; # Expiresヘッダーを設定
add_header Cache-Control "public, immutable"; # ブラウザが再検証なしにキャッシュを使用
access_log off; # 静的ファイルのログを無効化(I/O削減)
}
location ~* \.(css|js)$ {
expires 7d;
add_header Cache-Control "public";
}
location ~* \.(woff|woff2|ttf|eot)$ {
expires 365d;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*"; # フォントCORS
}
# ── HTMLは短いキャッシュまたはno-cache ──
location ~* \.html$ {
expires -1; # no-cache
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
7. Rate LimitingとConnection Limiting
7.1 Rate Limiting(リクエストレート制限)
NginxのRate LimitingはLeaky Bucketアルゴリズムを使用する。リクエストはバケット(zone)に入り、設定されたレート(rate)で処理される。
# ── HTTP ContextでZoneを定義 ──
# キー:クライアントIP
# 共有メモリ:10MB(約160,000 IPアドレス格納)
# レート:秒あたり10リクエスト
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
# ログインエンドポイント:秒あたり1(ブルートフォース防止)
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# APIエンドポイント:秒あたり50
limit_req_zone $binary_remote_addr zone=api:10m rate=50r/s;
# Rate Limit超過時のログレベル
limit_req_status 429; # デフォルト503の代わりに429 Too Many Requests
limit_req_log_level warn;
server {
listen 80;
server_name example.com;
# ── 一般ページ ──
location / {
limit_req zone=general burst=20 nodelay;
# burst=20: 瞬間的に20個まで超過を許容
# nodelay: burst範囲内のリクエストを遅延なしに即座に処理
proxy_pass http://backend;
}
# ── ログインページ ──
location /login {
limit_req zone=login burst=5 nodelay;
proxy_pass http://backend;
}
# ── API ──
location /api/ {
limit_req zone=api burst=100 nodelay;
proxy_pass http://backend;
}
}
burstとnodelayの動作原理:
Rate: 10r/s, Burst: 20
時刻0に30リクエストが到着:
├── 10個: 即座に処理(rate範囲内)
├── 20個: burstキューに格納
│ nodelayなし: 100ms間隔で処理(2秒間)
│ nodelayあり: 即座に処理(キュースロットのみ占有)
└── 残り: 429で拒否
7.2 Connection Limiting(同時接続制限)
# クライアントIPあたりの同時接続数制限
limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;
# サーバー全体の同時接続数制限
limit_conn_zone $server_name zone=conn_per_server:10m;
limit_conn_status 429;
limit_conn_log_level warn;
server {
listen 80;
server_name example.com;
# IPあたり最大100同時接続
limit_conn conn_per_ip 100;
# サーバーあたり最大10,000同時接続
limit_conn conn_per_server 10000;
# ダウンロード帯域幅制限(オプション)
location /downloads/ {
limit_conn conn_per_ip 5; # ダウンロードはIPあたり5に制限
limit_rate 500k; # 接続あたり500KB/s速度制限
limit_rate_after 10m; # 最初の10MBは制限なし、以降制限
}
}
7.3 IPホワイトリストとRate Limitingの組み合わせ
# 内部ネットワークはRate Limitingを免除
geo $limit {
default 1;
10.0.0.0/8 0; # 内部ネットワーク
192.168.0.0/16 0; # 内部ネットワーク
172.16.0.0/12 0; # 内部ネットワーク
}
map $limit $limit_key {
0 ""; # 空キー → Rate Limiting適用されない
1 $binary_remote_addr; # 外部IP → Rate Limiting適用
}
limit_req_zone $limit_key zone=api:10m rate=10r/s;
8. Gzip/Brotli圧縮
8.1 Gzip圧縮設定
# /etc/nginx/conf.d/gzip.conf
gzip on;
gzip_vary on; # Vary: Accept-Encodingヘッダーを追加
gzip_proxied any; # プロキシレスポンスも圧縮
gzip_comp_level 6; # 圧縮レベル(1-9、6がパフォーマンス/圧縮のバランスポイント)
gzip_min_length 1000; # 1KB未満のファイルは圧縮効果なし → 除外
gzip_buffers 16 8k; # 圧縮バッファ
gzip_types
text/plain
text/css
text/javascript
text/xml
application/javascript
application/json
application/xml
application/rss+xml
application/atom+xml
application/vnd.ms-fontobject
font/opentype
font/ttf
image/svg+xml
image/x-icon;
# 既に圧縮されたファイルを除外(画像、動画などはgzip_typesに未含)
gzip_disable "msie6"; # IE6を無効化(レガシー)
8.2 Brotli圧縮設定
BrotliはGzip比で15-25%高い圧縮率を提供する。ほとんどのモダンブラウザが対応しており、Nginxではngx_brotliモジュールが必要である。
# Brotli動的圧縮
brotli on;
brotli_comp_level 6; # 動的圧縮はレベル6推奨(11はCPU過負荷)
brotli_min_length 1000;
brotli_types
text/plain
text/css
text/javascript
text/xml
application/javascript
application/json
application/xml
application/rss+xml
font/opentype
font/ttf
image/svg+xml;
# Brotli静的圧縮(事前圧縮された.brファイルを提供)
brotli_static on;
8.3 デュアル圧縮戦略
Brotli対応ブラウザにはBrotliで、非対応ブラウザにはGzipでフォールバックする。
# ビルド時に静的ファイルを事前圧縮(CI/CDパイプライン)
# gzip -k -9 dist/**/*.{js,css,html,json,svg}
# brotli -k -q 11 dist/**/*.{js,css,html,json,svg}
# Nginx設定
brotli_static on; # .brファイルがあれば優先提供
gzip_static on; # .gzファイルがあれば提供(Brotli非対応時)
gzip on; # 事前圧縮ファイルがなければ動的gzip
圧縮性能比較:
| アルゴリズム | 圧縮率(一般JS) | CPU負荷(動的) | ブラウザ対応 |
|---|---|---|---|
| Gzip L6 | 70-75% | 低い | 99%以上 |
| Brotli L6 | 75-80% | 中程度 | 96%以上 |
| Brotli L11 | 80-85% | 高い(静的専用) | 96%以上 |
9. セキュリティヘッダー
9.1 総合セキュリティヘッダー設定
# /etc/nginx/conf.d/security-headers.conf
# ── クリックジャッキング防止 ──
add_header X-Frame-Options "DENY" always;
# DENY: いかなるサイトもiframeで埋め込み不可
# SAMEORIGIN: 同じドメインのみiframe許可
# 参考: CSP frame-ancestorsがより現代的な代替手段
# ── MIMEタイプスニッフィング防止 ──
add_header X-Content-Type-Options "nosniff" always;
# ブラウザがContent-Typeを無視して独自判断することを防止
# ── XSSフィルター(レガシー、現代ブラウザはCSPを使用) ──
add_header X-XSS-Protection "0" always;
# 最新の推奨: "0"(無効化)― CSPがより安全で正確
# ── Referrer情報制御 ──
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 同じドメイン: 完全なURLを送信
# 異なるドメイン: origin(ドメイン)のみ送信
# HTTP→HTTPSダウングレード: 送信しない
# ── パーミッションポリシー(カメラ、マイク、位置情報など制御) ──
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
# すべての機能を無効化(必要なもののみ許可)
# ── HSTS ──
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# ── Cross-Originポリシー ──
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
9.2 Content Security Policy (CSP)
CSPは最も強力なセキュリティヘッダーだが、設定が複雑である。Report-Onlyモードで開始して違反事項をモニタリングした後、段階的に適用することが推奨される。
# ── 第1段階:Report-Onlyモード(ブロックせずに違反のみ報告) ──
add_header Content-Security-Policy-Report-Only
"default-src 'self';
script-src 'self' https://cdn.example.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
report-uri /csp-report;" always;
# ── 第2段階:実際の適用(違反時にブロック) ──
add_header Content-Security-Policy
"default-src 'self';
script-src 'self' https://cdn.example.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';" always;
9.3 Server Blockでの統合適用
server {
listen 443 ssl http2;
server_name example.com;
include /etc/nginx/conf.d/ssl-params.conf;
include /etc/nginx/conf.d/security-headers.conf;
# セキュリティ関連の追加設定
server_tokens off; # Nginxバージョン情報を非表示
more_clear_headers Server; # Serverヘッダーを削除(headers-moreモジュール)
# ...
}
10. アクセス制御(Access Control)
10.1 IPベースアクセス制御
# ── 管理者ページ:特定IPのみ許可 ──
location /admin/ {
allow 10.0.0.0/8; # 内部ネットワーク
allow 203.0.113.50; # 特定の管理者IP
deny all; # 残りはすべて拒否
proxy_pass http://backend;
}
# ── 特定IP遮断 ──
location / {
deny 192.168.1.100; # 特定IP遮断
deny 10.0.0.0/24; # サブネット遮断
allow all; # 残りを許可
# 注意:allow/denyの順序が重要!先にマッチしたルールが適用される
proxy_pass http://backend;
}
10.2 HTTP Basic Authentication
# htpasswdファイル作成
sudo apt install apache2-utils # Debian/Ubuntu
# sudo yum install httpd-tools # RHEL/CentOS
# ユーザー作成(-c: ファイル新規作成、-B: bcryptハッシュ)
sudo htpasswd -cB /etc/nginx/.htpasswd admin
# ユーザー追加
sudo htpasswd -B /etc/nginx/.htpasswd developer
# ── 特定パスにBasic Authを適用 ──
location /admin/ {
auth_basic "Administrator Area"; # 認証プロンプトメッセージ
auth_basic_user_file /etc/nginx/.htpasswd; # パスワードファイル
proxy_pass http://backend;
}
# ── 特定パスのみ認証免除 ──
location /admin/health {
auth_basic off; # ヘルスチェックは認証免除
proxy_pass http://backend;
}
10.3 IP + Auth組み合わせ(satisfyディレクティブ)
location /admin/ {
# satisfy any → IP許可 OR 認証成功のいずれかを満たせばアクセス許可
# satisfy all → IP許可 AND 認証成功の両方を満たす必要がある
satisfy any;
# IPホワイトリスト
allow 10.0.0.0/8;
deny all;
# Basic Auth(IPホワイトリスト外からのアクセス時)
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://backend;
}
10.4 GeoIPベースアクセス制御
# GeoIP2モジュールが必要(ngx_http_geoip2_module)
geoip2 /usr/share/GeoIP/GeoLite2-Country.mmdb {
auto_reload 60m;
$geoip2_data_country_code country iso_code;
}
# 特定の国を遮断
map $geoip2_data_country_code $allowed_country {
default yes;
CN no; # 中国
RU no; # ロシア
}
server {
if ($allowed_country = no) {
return 403;
}
}
11. ログ設定
11.1 基本ログ設定
# ── Access Log ──
# デフォルトlog_format: combined
log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log combined;
# ── Error Log ──
# レベル: debug, info, notice, warn, error, crit, alert, emerg
error_log /var/log/nginx/error.log warn;
11.2 JSONログフォーマット(ログ分析ツール連携)
JSON形式の構造化ロギングは、Elasticsearch、Datadog、Splunkなどの分析ツールとの連携に必須である。
log_format json_combined escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"request_method":"$request_method",'
'"request_uri":"$request_uri",'
'"server_protocol":"$server_protocol",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"upstream_addr":"$upstream_addr",'
'"upstream_status":"$upstream_status",'
'"upstream_response_time":"$upstream_response_time",'
'"ssl_protocol":"$ssl_protocol",'
'"ssl_cipher":"$ssl_cipher",'
'"request_id":"$request_id"'
'}';
access_log /var/log/nginx/access.json.log json_combined;
11.3 条件付きロギング
# ── ヘルスチェックリクエストのログ除外 ──
map $request_uri $loggable {
~*^/health 0;
~*^/ready 0;
~*^/metrics 0;
default 1;
}
access_log /var/log/nginx/access.log combined if=$loggable;
# ── エラーリクエストのみ個別ロギング ──
map $status $is_error {
~^[45] 1;
default 0;
}
access_log /var/log/nginx/error_requests.log combined if=$is_error;
# ── 低速リクエストのロギング(1秒以上) ──
map $request_time $is_slow {
~^[1-9] 1; # 1秒以上
~^[0-9]{2} 1; # 10秒以上
default 0;
}
access_log /var/log/nginx/slow_requests.log json_combined if=$is_slow;
11.4 ドメイン別ログ分離
server {
server_name example.com;
access_log /var/log/nginx/example.com.access.log json_combined;
error_log /var/log/nginx/example.com.error.log warn;
}
server {
server_name api.example.com;
access_log /var/log/nginx/api.example.com.access.log json_combined;
error_log /var/log/nginx/api.example.com.error.log warn;
}
11.5 ログローテーション(logrotate)
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # 毎日ローテーション
missingok # ログファイルがなくてもエラーにしない
rotate 14 # 14日分保持
compress # gzip圧縮
delaycompress # 直前のファイルは圧縮しない
notifempty # 空のファイルはローテーションしない
create 0640 nginx adm # 新規ファイルの権限
sharedscripts
postrotate
# Nginxにログファイルの再オープンシグナルを送信
if [ -f /run/nginx.pid ]; then
kill -USR1 $(cat /run/nginx.pid)
fi
endscript
}
12. パフォーマンスチューニング
12.1 Workerプロセスと接続
# ── Main Context ──
worker_processes auto; # CPUコア数に合わせる(手動設定: 4, 8など)
worker_rlimit_nofile 65535; # Worker当たりの最大ファイルディスクリプタ数
events {
worker_connections 4096; # Worker当たりの最大同時接続数
multi_accept on; # 1つのイベントループで複数接続を受け入れる
use epoll; # Linux: epoll(デフォルト)
}
最大同時接続数の計算式:
最大接続数 = worker_processes x worker_connections
例: 4 workers x 4096 connections = 16,384同時接続
リバースプロキシ時(クライアント + バックエンドの2接続):
実際の同時クライアント数 = 16,384 / 2 = 8,192
12.2 Keepalive設定
http {
# ── クライアントKeepalive ──
keepalive_timeout 65; # クライアントkeepalive維持時間(秒)
keepalive_requests 1000; # 1つのkeepalive接続で処理する最大リクエスト数
# ── タイムアウト ──
client_body_timeout 12; # クライアントリクエストボディ受信タイムアウト
client_header_timeout 12; # クライアントリクエストヘッダー受信タイムアウト
send_timeout 10; # クライアントへのレスポンス送信タイムアウト
reset_timedout_connection on; # タイムアウト接続を即座にリセット(メモリ解放)
}
12.3 バッファ設定
http {
# ── クライアントリクエストバッファ ──
client_body_buffer_size 16k; # リクエストボディバッファ(超過時にディスク書き込み)
client_header_buffer_size 1k; # リクエストヘッダーバッファ
client_max_body_size 100m; # 最大アップロードサイズ(デフォルト1MB)
large_client_header_buffers 4 16k; # 大きなヘッダー用バッファ
# ── プロキシバッファ ──
proxy_buffers 16 32k; # バックエンドレスポンス格納バッファ
proxy_buffer_size 16k; # 最初のレスポンス(ヘッダー)バッファ
proxy_busy_buffers_size 64k; # クライアントへ送信中のバッファサイズ
proxy_temp_file_write_size 64k; # ディスクに書き込む一時ファイルサイズ
}
12.4 プロダクションパフォーマンスチューニング総合
# /etc/nginx/nginx.conf ― プロダクション最適化
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
http {
# ── MIME & 基本設定 ──
include /etc/nginx/mime.types;
default_type application/octet-stream;
charset utf-8;
server_tokens off; # バージョン情報を非表示
# ── ファイル転送最適化 ──
sendfile on; # カーネルレベルのファイル転送
tcp_nopush on; # sendfileと併用:パケット最適化
tcp_nodelay on; # Nagleアルゴリズムを無効化
aio on; # 非同期I/O
# ── Keepalive ──
keepalive_timeout 65;
keepalive_requests 1000;
# ── タイムアウト ──
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
reset_timedout_connection on;
# ── バッファ ──
client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 100m;
large_client_header_buffers 4 16k;
# ── Open File Cache ──
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# ── 圧縮、SSL、ログなどinclude ──
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf;
}
13. URLリライティングとリダイレクション
13.1 returnディレクティブ(推奨)
returnはrewriteよりシンプルで効率的である。URL変更が必要なほとんどの場合、まずreturnを検討すべきである。
# ── HTTP → HTTPSリダイレクト ──
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# ── www → non-www正規化 ──
server {
listen 443 ssl http2;
server_name www.example.com;
return 301 https://example.com$request_uri;
}
# ── ドメイン変更リダイレクト ──
server {
listen 80;
listen 443 ssl http2;
server_name old-domain.com www.old-domain.com;
return 301 https://new-domain.com$request_uri;
}
# ── 特定パスリダイレクト ──
location /old-page {
return 301 /new-page;
}
# ── メンテナンスモード ──
location / {
return 503; # Service Unavailable
}
# error_pageと組み合わせ
error_page 503 /maintenance.html;
location = /maintenance.html {
root /var/www/html;
internal;
}
13.2 rewriteディレクティブ
rewriteは正規表現ベースのURL変換が必要な場合に使用する。
# ── 基本構文 ──
# rewrite regex replacement [flag];
# flag: last | break | redirect (302) | permanent (301)
# ── バージョンなしのAPIパスに変換 ──
rewrite ^/api/v1/(.*)$ /api/$1 last;
# /api/v1/users → /api/users に内部リライト
# last: 新しいlocationマッチングを開始
# ── 拡張子除去(Clean URL) ──
rewrite ^/(.*)\.html$ /$1 permanent;
# /about.html → /about(301リダイレクト)
# ── クエリストリング付きリライト ──
rewrite ^/search/(.*)$ /search?q=$1? last;
# 末尾に?を付けると元のクエリストリングが除去される
# ── 多言語URL ──
rewrite ^/ko/(.*)$ /$1?lang=ko last;
rewrite ^/en/(.*)$ /$1?lang=en last;
rewrite ^/ja/(.*)$ /$1?lang=ja last;
rewriteフラグ比較:
| フラグ | 動作 | 用途 |
|---|---|---|
last | リライト後に新しいlocationマッチング | 内部ルーティング変更 |
break | リライト後に現在のlocation内で処理 | 現在のブロック内変換 |
redirect | 302一時リダイレクト | 一時的な移動 |
permanent | 301永久リダイレクト | 永久的な移動 |
13.3 try_filesディレクティブ
try_filesはファイル/ディレクトリの存在を順次確認し、SPAやフレームワークで必須である。
# ── SPA(React、Vue、Angularなど) ──
location / {
root /var/www/spa;
try_files $uri $uri/ /index.html;
# 1. $uri: リクエストされたファイルがあるか確認
# 2. $uri/: ディレクトリがあるか確認
# 3. /index.html: 上記すべてない場合index.html(SPAルーティング)
}
# ── Next.js / Nuxt.js ──
location / {
try_files $uri $uri/ @proxy;
}
location @proxy {
proxy_pass http://127.0.0.1:3000;
include /etc/nginx/conf.d/proxy-params.conf;
}
# ── PHP(WordPress、Laravel) ──
location / {
try_files $uri $uri/ /index.php?$args;
}
# ── 静的ファイル優先 → バックエンドフォールバック ──
location / {
root /var/www/static;
try_files $uri @backend;
}
location @backend {
proxy_pass http://app_server;
}
13.4 条件付きリダイレクト
# ── モバイルデバイスリダイレクト ──
if ($http_user_agent ~* "(Android|iPhone|iPad)") {
return 302 https://m.example.com$request_uri;
}
# ── 特定クエリパラメータベース ──
if ($arg_redirect) {
return 302 $arg_redirect;
}
# ── mapで複雑なリダイレクト管理 ──
map $request_uri $redirect_uri {
/old-blog/post-1 /blog/new-post-1;
/old-blog/post-2 /blog/new-post-2;
/products/legacy /shop/all;
default "";
}
server {
if ($redirect_uri) {
return 301 $redirect_uri;
}
}
14. 静的ファイル配信最適化
14.1 コアファイル転送ディレクティブ
http {
# ── sendfile ──
# カーネルのsendfile()システムコールを使用してファイルを直接ソケットに転送
# ユーザースペースのメモリコピーを排除し、CPU使用量とコンテキストスイッチを削減
sendfile on;
# ── tcp_nopush ──
# sendfileと連動:HTTPヘッダーとファイルの先頭部分を1つのパケットで送信
# ネットワークパケット数を削減して帯域幅効率を向上
tcp_nopush on;
# ── tcp_nodelay ──
# Nagleアルゴリズムを無効化:小さなパケットを即座に送信
# keepalive接続でのレイテンシを削減(tcp_nopushと併用可能)
tcp_nodelay on;
}
転送方式の比較:
sendfile off(デフォルト):
ディスク → カーネルバッファ → ユーザーメモリ(Nginx) → カーネルソケットバッファ → ネットワーク
[読み込み] [コピー] [書き込み]
sendfile on:
ディスク → カーネルバッファ ─────────────────────────→ カーネルソケットバッファ → ネットワーク
[読み込み] [ゼロコピー:CPU介入なし] [転送]
14.2 Open File Cache
繰り返しリクエストされるファイルのディスクリプタ、サイズ、更新時刻をキャッシュして、ファイルシステム照会を最小化する。
http {
# 最大10,000件のファイル情報をキャッシュ、30秒間未使用で削除
open_file_cache max=10000 inactive=30s;
# キャッシュされた情報を60秒ごとに再検証
open_file_cache_valid 60s;
# 最低2回以上リクエストされたファイルのみキャッシュ(1回限りのリクエストをフィルタ)
open_file_cache_min_uses 2;
# ファイル未検出(ENOENT)エラーもキャッシュ(存在しないファイルの繰り返し照会を防止)
open_file_cache_errors on;
}
14.3 静的ファイル配信総合設定
server {
listen 443 ssl http2;
server_name static.example.com;
root /var/www/static;
# ── 画像 ──
location ~* \.(jpg|jpeg|png|gif|ico|webp|avif|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
access_log off;
log_not_found off; # 404ログも無効化
# 画像専用制限
limit_rate 2m; # 接続あたり2MB/s
}
# ── CSS/JS(キャッシュバスティング戦略と併用) ──
location ~* \.(css|js)$ {
expires 365d; # ハッシュベースファイル名なら長期キャッシュ
add_header Cache-Control "public, immutable";
gzip_static on;
brotli_static on;
}
# ── フォント ──
location ~* \.(woff|woff2|ttf|eot|otf)$ {
expires 365d;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
}
# ── メディアファイル ──
location ~* \.(mp4|webm|ogg|mp3|wav)$ {
expires 30d;
add_header Cache-Control "public";
# Rangeリクエスト対応(動画シーク)
add_header Accept-Ranges bytes;
}
# ── ディレクトリリスティング防止 ──
location / {
autoindex off;
}
# ── 隠しファイルへのアクセス遮断 ──
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
14.4 HTTP/2 Server Push(オプション)
# 主要リソースをクライアントリクエスト前に事前送信
location = /index.html {
http2_push /css/main.css;
http2_push /js/app.js;
http2_push /images/logo.webp;
}
参考: HTTP/2 Server Pushは一部のブラウザでサポートが終了しており、
103 Early Hintsが代替として台頭している。
15. ヘルスチェックとモニタリング
15.1 Stub Status(基本モニタリング)
Nginx OSSに含まれるstub_statusモジュールでリアルタイムの接続状態を確認できる。
server {
listen 8080; # 別ポートで分離
server_name localhost;
# 内部ネットワークからのアクセスのみ許可
allow 10.0.0.0/8;
allow 127.0.0.1;
deny all;
location /nginx_status {
stub_status;
}
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
stub_status出力例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
| 項目 | 意味 |
|---|---|
Active connections | 現在のアクティブ接続数(Reading + Writing + Waiting) |
accepts | 総受け入れ接続数 |
handled | 総処理接続数(= acceptsなら正常) |
requests | 総処理リクエスト数 |
Reading | クライアントリクエストヘッダーを読み込み中の接続数 |
Writing | クライアントにレスポンスを送信中の接続数 |
Waiting | keepaliveアイドル接続数 |
15.2 パッシブヘルスチェック(Upstreamモニタリング)
Nginx OSSは実際のトラフィックベースのパッシブヘルスチェックのみ対応している。
upstream backend {
server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.3:8080 max_fails=3 fail_timeout=30s backup;
# max_fails=3: 30秒以内に3回連続失敗でサーバーを異常と判定
# fail_timeout=30s: 異常判定後30秒間そのサーバーへリクエスト送信しない
# 30秒後に再度リクエストを送り復旧を確認
}
server {
location / {
proxy_pass http://backend;
# どのレスポンスを「失敗」と判定するかを設定
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_timeout 10s; # 次のサーバーを試行する最大時間
proxy_next_upstream_tries 3; # 最大リトライ回数
}
}
15.3 アクティブヘルスチェック(NGINX Plusまたは外部ソリューション)
# ── NGINX Plusでのアクティブヘルスチェック ──
upstream backend {
zone backend_zone 64k; # 共有メモリゾーン必須
server 10.0.0.1:8080;
server 10.0.0.2:8080;
}
server {
location / {
proxy_pass http://backend;
health_check interval=5s # 5秒ごとにチェック
fails=3 # 3回失敗で異常
passes=2 # 2回成功で復旧
uri=/health; # ヘルスチェックエンドポイント
}
}
15.4 Prometheus連携(nginx-prometheus-exporter)
# docker-compose.yml
services:
nginx-exporter:
image: nginx/nginx-prometheus-exporter:1.3
command:
- --nginx.scrape-uri=http://nginx:8080/nginx_status
ports:
- '9113:9113'
depends_on:
- nginx
# prometheus.yml
scrape_configs:
- job_name: 'nginx'
static_configs:
- targets: ['nginx-exporter:9113']
15.5 カスタムヘルスチェックエンドポイント
# ── Liveness Probe(Nginx自体の動作確認) ──
location = /healthz {
access_log off;
return 200 "alive\n";
add_header Content-Type text/plain;
}
# ── Readiness Probe(バックエンド接続を含む確認) ──
location = /readyz {
access_log off;
proxy_pass http://backend/health;
proxy_connect_timeout 2s;
proxy_read_timeout 2s;
# バックエンドレスポンス失敗時503
error_page 502 503 504 = @not_ready;
}
location @not_ready {
return 503 "not ready\n";
add_header Content-Type text/plain;
}
# Kubernetesでの活用
apiVersion: v1
kind: Pod
spec:
containers:
- name: nginx
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /readyz
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
総合プロダクション設定チェックリスト
プロダクション環境にNginxをデプロイする際に確認すべき重要項目を整理する。
| カテゴリ | 項目 | ステータス |
|---|---|---|
| アーキテクチャ | worker_processes auto設定 | [ ] |
| アーキテクチャ | worker_connections適切な値に設定 | [ ] |
| SSL/TLS | TLSv1.2 + TLSv1.3のみ有効化 | [ ] |
| SSL/TLS | 強力なCipher Suitesの設定 | [ ] |
| SSL/TLS | OCSP Stapling有効化 | [ ] |
| SSL/TLS | HSTSヘッダー設定 | [ ] |
| SSL/TLS | HTTP → HTTPSリダイレクト | [ ] |
| セキュリティ | server_tokens off | [ ] |
| セキュリティ | セキュリティヘッダー(CSP、X-Frame-Optionsなど)設定 | [ ] |
| セキュリティ | Rate Limiting設定 | [ ] |
| セキュリティ | 管理者ページアクセス制御 | [ ] |
| パフォーマンス | sendfile、tcp_nopush、tcp_nodelay有効化 | [ ] |
| パフォーマンス | Gzip/Brotli圧縮設定 | [ ] |
| パフォーマンス | open_file_cache設定 | [ ] |
| パフォーマンス | 静的ファイルブラウザキャッシング設定 | [ ] |
| パフォーマンス | Upstream keepalive設定 | [ ] |
| キャッシング | proxy_cacheまたはfastcgi_cache設定 | [ ] |
| キャッシング | proxy_cache_use_stale設定 | [ ] |
| モニタリング | stub_status有効化(内部専用) | [ ] |
| モニタリング | ヘルスチェックエンドポイント構成 | [ ] |
| ロギング | JSONログフォーマット設定 | [ ] |
| ロギング | ログローテーション設定 | [ ] |
| ロギング | ヘルスチェック/静的ファイルログ除外 | [ ] |
| プロキシ | 必須プロキシヘッダー設定 | [ ] |
| プロキシ | WebSocketプロキシ設定(必要時) | [ ] |
| ロードバランシング | 適切なアルゴリズム選択 | [ ] |
| ロードバランシング | バックアップサーバー構成 | [ ] |
参考資料
- Nginx Official Documentation
- Nginx Beginner's Guide
- DigitalOcean - Understanding Nginx Configuration File Structure
- Inside NGINX: How We Designed for Performance and Scale
- NGINX Reverse Proxy Guide
- Nginx WebSocket Proxying
- NGINX HTTP Load Balancing
- NGINX TLS 1.3 Hardening Guide
- A Guide to Caching with NGINX
- Rate Limiting with NGINX
- NGINX Gzip Compression Guide
- Tuning NGINX for Performance
- Creating NGINX Rewrite Rules
- NGINX sendfile, tcp_nopush, tcp_nodelay Explained
- NGINX Health Checks
- Mozilla SSL Configuration Generator