TL;DR
nginx -t を実行して正確なファイルとライン番号を特定してください。タイポ、セミコロンの欠落、またはモジュールの不一致を修正し、systemctl reload nginx でリロードします。
sudo nginx -t
# 表示されたエラーを修正する
sudo systemctl reload nginx
このエラーの意味
設定変更を適用する前に、Nginxは読み込むすべてのファイルをパースします。認識できないディレクティブに遭遇すると、即座に停止します:
nginx: [emerg] unknown directive "ssl_stapling" in /etc/nginx/sites-enabled/mysite.conf:14
[emerg] は、Nginxが起動またはリロードを拒否することを意味します。既存の実行中のインスタンスはそのまま動き続けますが、エラーが修正されるまで設定変更は一切反映されません。
原因は主に4つあります:
- ディレクティブ名のタイポ(例:
server_nameの代わりにservr_name) - Nginxビルドにコンパイルされていないモジュールに属するディレクティブ
- 誤ったコンテキストに配置されたディレクティブ(例:
httpではなくserver内のlog_format) - パーサーを狂わせる波括弧の欠落または不一致
ステップ1 — 設定テストを実行して出力を確認する
常にここから始めてください。Nginx組み込みのテストが正確なファイル、行番号、ディレクティブ名を教えてくれます:
sudo nginx -t
出力例:
nginx: [emerg] unknown directive "proxy_cache_purge" in /etc/nginx/conf.d/cache.conf:8
nginx: configuration file /etc/nginx/nginx.conf test failed
表示されたファイルの該当行を開きます:
sudo nano /etc/nginx/conf.d/cache.conf
ステップ2 — よくある原因を修正する
ディレクティブ名のタイポ
公式Nginxドキュメントでスペルを確認してください。よくあるミスはこのようなものです:
# 誤り
servr_name example.com;
acces_log /var/log/nginx/access.log;
# 正しい
server_name example.com;
access_log /var/log/nginx/access.log;
インストールされていないモジュールが必要なディレクティブ
proxy_cache_purge、geoip_country、image_filter などのディレクティブはデフォルトのNginxパッケージに含まれていません。バイナリに実際に含まれているものを確認してください:
nginx -V 2>&1 | grep -- '--with'
モジュールが不足している場合は、Ubuntu/Debianで適切なパッケージをインストールします:
# GeoIPの場合
sudo apt install nginx-module-geoip
# 画像フィルターの場合
sudo apt install nginx-module-image-filter
次に、/etc/nginx/nginx.conf の先頭でロードします:
load_module modules/ngx_http_geoip_module.so;
proxy_cache_purge などのサードパーティディレクティブについては、ngx_cache_purge モジュールを使ってNginxをコンパイルするか、キャッシュ無効化の戦略を全面的に見直す必要があります。
誤ったコンテキストのディレクティブ
各ディレクティブは特定のブロック内でのみ有効です。たとえば log_format は http 内にのみ記述できます。server 内に置くとNginxはエラーを返します:
# log_format は http 内にのみ記述する
http {
log_format main '$remote_addr "$request" $status'; # 正しい
server {
log_format main '$remote_addr "$request"'; # 誤り — エラーになる
}
}
迷った場合は、移動する前にNginxドキュメントでそのディレクティブの「Context」行を確認してください。
パーサーコンテキストを狂わせる波括弧の不一致
閉じ波括弧が1つ欠けるだけで、それ以降のすべてのディレクティブが誤ったブロックにあるように見えてしまいます。エラーメッセージがすぐに混乱を招きます。波括弧を数えてください:
grep -c '{' /etc/nginx/sites-enabled/mysite.conf
grep -c '}' /etc/nginx/sites-enabled/mysite.conf
数は一致しているはずです。一致しない場合は、手動で欠落している波括弧を探すか、シンタックス対応エディタでファイルを開いてください。
ステップ3 — 修正を確認する
ファイルを編集したら、リロードする前にテストしてください。このステップは絶対に省略しないでください:
sudo nginx -t
正常な出力は次のようになります:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
次にリロードします。再起動ではなく、リロードはゼロダウンタイムです:
sudo systemctl reload nginx
正常に稼働しているか確認します:
sudo systemctl status nginx
curl -I http://localhost
ステップ4 — インクルードされているファイルをすべて確認する
Nginxは複数の場所から設定を読み込みます。nginx -t が触っていないファイルを指している場合は、それをインクルードしているものを探してください:
grep -r 'include' /etc/nginx/nginx.conf /etc/nginx/conf.d/ /etc/nginx/sites-enabled/
Dockerコンテナや他のサーバーからコピーされた設定ファイルは、異なるNginxビルドのモジュールやシンタックスを参照していることがよくあります。これが謎のエラーの一般的な原因です。
予防策
これらのエラーのほとんどを防ぐ3つの習慣:
- 毎回のリロード前に
nginx -tを実行する — デプロイスクリプトに組み込んで自動化しましょう /etc/nginx/をgitで管理する。1行の差分が、目視では見落とすタイポを発見します- YAMLテンプレートやAnsibleからNginx設定を生成する場合は、ToolCraftのYAML ↔ JSONコンバーターでYAMLを事前にチェックする — 壊れた設定としてレンダリングされる前に構造的な問題を検出します。ブラウザ内で動作し、何もアップロードされません
- ステージング環境では、本番と同じNginxバージョンでテストする。モジュールの利用可能性は1.18と1.24で異なります
クイックリファレンス — ディレクティブとそのコンテキスト
http {
# httpレベル: gzip, log_format, upstream, sendfile
gzip on;
server {
# serverレベル: listen, server_name, root, ssl_*
listen 80;
server_name example.com;
root /var/www/html;
location / {
# locationレベル: try_files, proxy_pass, return, rewrite
try_files $uri $uri/ =404;
}
}
}

