エラーの概要
証明書の更新やサーバー移行後、NginxまたはApacheが起動を拒否します:
nginx: [emerg] SSL_CTX_use_PrivateKey_file("/etc/ssl/private/server.key") failed
(SSL: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib)
またはOpenSSLから直接:
error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
サーバーが起動しません。HTTPSがダウンしています。修正しましょう。
エラーの意味
OpenSSLが秘密鍵の読み込みを試みましたが、失敗しました。原因は主に3つあります:
- 鍵ファイルの不一致 — 秘密鍵が証明書と対応していない(最も多い原因)
- PEMファイルの破損または切り捨て — ファイルが破損、途中で切れている、または部分的に上書きされている
- フォーマットの誤り — 鍵がbase64 PEMではなくバイナリDER形式になっているか、ヘッダーが欠落している
対処する前に診断を行ってください — 各ケースの修正方法はまったく異なります。
手順1:鍵と証明書が一致しているか確認する
両方のコマンドを実行してMD5の出力を比較してください。ハッシュが一致していれば、鍵と証明書は有効なペアです:
# 証明書のフィンガープリント
openssl x509 -noout -modulus -in /etc/ssl/certs/server.crt | openssl md5
# 秘密鍵のフィンガープリント
openssl rsa -noout -modulus -in /etc/ssl/private/server.key | openssl md5
一致している場合の出力例:
(stdin)= a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
(stdin)= a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 ← 同じ = 正常
ハッシュが異なる場合はペアが一致していません。手順3に直接進んでください。
手順2:PEMファイルが破損していないか確認する
鍵を直接読み込んでみてください:
openssl rsa -in /etc/ssl/private/server.key -check
正常な鍵の場合は以下が表示されます:
RSA key ok
ここでエラーが発生する場合、ファイルが破損しているか、最初から有効なPEM鍵ではなかったことを意味します。
ファイルの先頭と末尾も確認してください:
head -1 /etc/ssl/private/server.key
tail -1 /etc/ssl/private/server.key
有効なRSA鍵ファイルの形式:
-----BEGIN RSA PRIVATE KEY-----
...base64 content...
-----END RSA PRIVATE KEY-----
PKCS#8形式(新しいツールやECDSA鍵で使用):
-----BEGIN PRIVATE KEY-----
...base64 content...
-----END PRIVATE KEY-----
バイナリの文字化けや末尾が欠落している場合はファイルが破損しています。バックアップから復元するか、証明書を再発行してください。
手順3:鍵と証明書の不一致を修正する
鍵と証明書が異なる発行タイミングのものになっています。最もよくあるシナリオ:証明書を更新したが、新しい証明書が別のパスに配置され、古い鍵が残ってしまっているケースです。またはデプロイスクリプトが今月の証明書と先四半期のパッケージの鍵を組み合わせてしまったケースもあります。
オプションA — 元の秘密鍵がどこかに残っている場合
バックアップの場所、CSRを生成したマシン、またはシークレットストレージ(HashiCorp Vault、GitHub Secrets、AWS Secrets Manager)を確認してください。見つかったら、本番環境に触れる前に一致を確認してください:
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in recovered.key | openssl md5
一致した場合、所定の場所に配置してリロードします:
cp recovered.key /etc/ssl/private/server.key
chmod 600 /etc/ssl/private/server.key
nginx -t && systemctl reload nginx
オプションB — 鍵が失われた場合、ゼロから再発行する
鍵がなければ近道はありません。新しい鍵ペアを生成し、新しいCSRを作成して、CAから新しい証明書を取得してください:
# 新しい2048ビット鍵(長期使用の証明書には4096を使用)
openssl genrsa -out /etc/ssl/private/server.key 2048
# 新しい鍵からCSRを作成
openssl req -new -key /etc/ssl/private/server.key -out server.csr
Let's Encrypt、DigiCert、または元の証明書を発行したCAにCSRを提出してください。今すぐテストのブロックを解除するための自己署名証明書の場合:
openssl req -x509 -new -nodes \
-key /etc/ssl/private/server.key \
-sha256 -days 365 \
-out /etc/ssl/certs/server.crt
オプションC — 鍵がDER形式の場合
head -1 で-----BEGINヘッダーではなくバイナリの文字化けが表示される場合、ファイルはDER形式でエンコードされています。以下のコマンド一つで修正できます:
openssl rsa -inform DER -in server.key.der -outform PEM -out /etc/ssl/private/server.key
手順4:ファイルのパーミッションを修正する
パーミッションが誤っているとサイレントエラーが発生します — OpenSSLが鍵を読み取れませんが、エラーメッセージにそれが明示されない場合があります。正しく設定してください:
# 秘密鍵:rootのみアクセス可能
chmod 600 /etc/ssl/private/server.key
chown root:root /etc/ssl/private/server.key
# 証明書:全員が読み取り可能でも問題なし
chmod 644 /etc/ssl/certs/server.crt
Ubuntuでは、Nginxはwww-dataとして実行されます。rootが所有する600パーミッションの鍵は完全にブロックされます。修正方法:
chown root:www-data /etc/ssl/private/server.key
chmod 640 /etc/ssl/private/server.key
修正の確認
リロードする前に設定をテストしてください — サーバーを2度ダウンさせないように:
# Nginx
nginx -t
# Apache
apachectl configtest
その後リロードします:
systemctl reload nginx
# または
systemctl reload apache2
正しい証明書が実際に提供されているか確認します:
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com 2>/dev/null | openssl x509 -noout -dates -subject
ドメイン名と有効期限が表示されます。出力に誤ったドメインが表示される場合、設定内の証明書パスがまだ古いファイルを指しています。
診断チェックリスト
- 証明書と鍵のMD5モジュラスが同一であること — 毎回必ずこれを最初に確認する
openssl rsa -in key.pem -checkが "RSA key ok" を返すこと- PEMファイルが
-----BEGIN ... KEY-----で始まり-----END ... KEY-----で終わること - パーミッション:秘密鍵は600(またはwww-data用に640)、証明書は644
- Nginx/Apache設定内の鍵ファイルパスが実際のファイルの場所と完全に一致していること — 末尾のスラッシュ、シンボリックリンクも含めて
次回以降の予防策
鍵とCSRを同じコマンドで、同じディレクトリに、ファイル名に年を含めて生成してください。異なる発行タイミングのファイルを混在させることがなくなります:
openssl req -newkey rsa:2048 -nodes \
-keyout /etc/ssl/private/yourdomain-2026.key \
-out /etc/ssl/csr/yourdomain-2026.csr
デプロイスクリプトにモジュラスチェックを追加してください。2つのコマンド、10秒で、毎回必ずこの問題を検出できます。

