devops
A
信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
nginxのよくある設定ミスとトラブルシューティング
nginxの設定でハマりやすいポイントを解説。502 Bad Gateway・CORS問題・SSL設定ミス・WebSocketプロキシ・レート制限などの問題と解決策をまとめます。
一言結論
nginxのトラブルの大半は502はupstreamタイムアウト、CORSはadd_headerの二重設定、WebSocketはUpgradeヘッダーの欠落が原因であり、nginx -tとerror.logの確認を最初のステップにすれば原因特定が格段に速い。
デバッグの基本コマンド
# 設定ファイルの文法チェック
nginx -t
# 設定を再読み込み(ダウンタイムなし)
nginx -s reload
# エラーログをリアルタイム確認
tail -f /var/log/nginx/error.log
# アクセスログ確認
tail -f /var/log/nginx/access.log
よくあるエラーとその原因
502 Bad Gateway
上流サーバー(アプリ)への接続失敗。
# まず上流サーバーが動いているか確認
curl http://localhost:3000/health
# nginx エラーログを確認
grep "502\|upstream" /var/log/nginx/error.log
# ❌ よくある設定ミス(上流の URL が間違っている)
upstream app {
server 127.0.0.1:3000;
}
# ✅ タイムアウトを適切に設定
upstream app {
server 127.0.0.1:3000;
keepalive 32;
}
server {
location / {
proxy_pass http://app;
proxy_read_timeout 60s;
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
}
}
CORS エラー
# ✅ CORS ヘッダーを nginx で追加
location /api/ {
proxy_pass http://app;
# プリフライトリクエスト
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://frontend.example.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Max-Age' 1728000;
return 204;
}
add_header 'Access-Control-Allow-Origin' 'https://frontend.example.com';
}
WebSocket プロキシ
# ✅ WebSocket に必要なヘッダー
location /ws/ {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400s; # 長時間接続のためタイムアウトを延長
}
SSL / HTTPS の設定
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# ✅ 推奨 SSL 設定
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# HSTS(6ヶ月間 HTTPS を強制)
add_header Strict-Transport-Security "max-age=15768000" always;
}
# HTTP → HTTPS リダイレクト
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
413 Request Entity Too Large
# ✅ アップロードサイズの制限を変更
http {
client_max_body_size 50M; # デフォルトは 1MB
}
レート制限
http {
# IP ごとに 10req/s を制限
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
proxy_pass http://app;
}
}
}
静的ファイルのキャッシュ最適化
location ~* \.(js|css|png|jpg|webp|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
# gzip 圧縮
gzip on;
gzip_types text/css application/javascript image/svg+xml;
gzip_min_length 1024;
}
セキュリティヘッダーの追加
server {
# クリックジャッキング防止
add_header X-Frame-Options "SAMEORIGIN" always;
# MIME スニッフィング防止
add_header X-Content-Type-Options "nosniff" always;
# XSS 保護
add_header X-XSS-Protection "1; mode=block" always;
# リファラーポリシー
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# nginx のバージョン情報を隠す
server_tokens off;
}
まとめ
| 問題 | 確認ポイント |
|---|---|
| 502 Bad Gateway | 上流サーバーが動いているか・タイムアウト設定 |
| CORS エラー | add_header Access-Control-* の設定 |
| WebSocket 切断 | Upgrade・Connection ヘッダー・タイムアウト |
| SSL エラー | 証明書パス・TLS バージョン |
| アップロード失敗 | client_max_body_size |
まず nginx -t で文法チェック、次に tail -f /var/log/nginx/error.log でエラーを確認するのが基本フローです。
参考: nginx 公式ドキュメント