エラーの内容
Nginxを起動またはリロードすると、ターミナルやログに次のメッセージが表示されます:
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
nginx: [emerg] bind() to 0.0.0.0:443 failed (13: Permission denied)
nginx: [emerg] still could not bind()
Nginxは終了し、トラフィックは一切処理されません。サービスが完全に停止してしまいます。
発生原因
Linuxでは1024番未満のポートは特権ポートとして扱われます。バインドできるのはrootユーザー、または明示的にCAP_NET_BIND_SERVICEの権限を付与されたプロセスのみです。通常、Nginxはrootとして起動し、ポート80と443を確保してから、www-dataやnginxといった制限付きユーザーでワーカープロセスをフォークします。このエラーは、マスタープロセスがバインド処理に到達できなかったことを意味します。主な原因は以下のとおりです:
- Nginxがroot以外のユーザーによって直接起動された
- バイナリに
CAP_NET_BIND_SERVICEケーパビリティが設定されていない - systemdのサービス設定により、最初から非特権ユーザーとしてNginxが起動している
- コンテナやサンドボックスが特権ポートへのアクセスをブロックしている
注意点として、これはAddress already in useとは異なります。この場合ポートは空いています。Nginxにそのポートを使用する権限がないのが問題です。
手順ごとの対処法
1. Nginxの起動方法を確認する
何かを変更する前に、Nginxを実際に実行しているユーザーを確認します:
ps aux | grep nginx
# またはsystemdユニットを確認する:
systemctl cat nginx
サービスファイルのUser=行がケーパビリティを持たない非rootアカウントを指している場合、それが原因です。
2. rootとしてNginxを起動する(通常の方法)
Nginxはrootとして起動するように設計されています。マスタープロセスが最初にポートをバインドし、その後すぐにnginx.confで定義されたワーカーユーザーに権限を降格します。特別な設定は不要です。
sudo systemctl start nginx
# または直接起動する:
sudo nginx
これで動作する場合、元の起動コマンドでsudoが省略されていたことが原因です。
3. バイナリにCAP_NET_BIND_SERVICEを付与する(rootレスの環境)
意図的にrootなしでNginxを実行する場合は、必要なケーパビリティだけを付与します:
sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx
ケーパビリティが設定されたか確認します:
getcap /usr/sbin/nginx
# 期待される出力:
# /usr/sbin/nginx cap_net_bind_service=+ep
これで完了です。Nginxはroot権限なしでポート80と443をバインドできるようになります。
4. systemdサービスの設定を修正する
問題がユニットファイル自体にある場合もあります。Nginxがバインドを試みる前にsystemdが権限を降格させている可能性があります。サービスをオーバーライドして修正します:
sudo systemctl edit nginx
マスタープロセスをrootとして起動するよう設定します:
[Service]
User=root
変更を適用します:
sudo systemctl daemon-reload
sudo systemctl restart nginx
5. Docker / コンテナ環境
コンテナはデフォルトで特権ポートをブロックすることが多いです。2つのクリーンな方法があります:
方法A — コンテナ内でNginxを高番号ポート(例:8080)でリッスンさせ、Dockerでホストのポート80にマッピングします:
docker run -p 80:8080 my-nginx-image
コンテナ内のNginx設定を更新します:
listen 8080;
方法B — コンテナに直接NET_BIND_SERVICEケーパビリティを追加します:
docker run --cap-add=NET_BIND_SERVICE -p 80:80 my-nginx-image
修正の確認
上記のいずれかの修正を適用したら、Nginxが正常に動作しているか確認します:
sudo systemctl status nginx
active (running)と表示されているか確認します。次に、正しいポートでリッスンしているか確認します:
sudo ss -tlnp | grep nginx
# または:
sudo netstat -tlnp | grep :80
期待される出力:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6))
最後に、トラフィックが正常に流れているか確認するためにリクエストを送ります:
curl -I http://localhost
補足情報
- 403 Forbiddenと混同しないでください — このエラーはOSのソケットレベルで、起動時に発生します。Webルートやファイルのパーミッションとは無関係です。
- **Nginxパッケージのアップグレードでsetcapの設定が消えます。**ケーパビリティはバイナリファイルに紐づいています。パッケージ更新で
/usr/sbin/nginxが置き換えられるたびに、setcapを再実行する必要があります。インストール後のフックやデプロイスクリプトに追加しておくことをお勧めします。 - **RHEL/CentOSではSELinuxまたはAppArmorを先に確認してください。**SELinuxが有効なシステムではrootでもブロックされることがあります。
getenforceを実行して現在のモードを確認します。Enforcingの場合は、semanage port -a -t http_port_t -p tcp 80でポートを明示的に許可してください。 - ソケットファイルやログディレクトリのchmodなど、関連するファイルパーミッションの問題を解決する場合は、ToolCraftのUnix Permissions Calculatorが便利です。8進数表記を覚えなくても、視覚的にchmod値を設定できます。

