Servers and proxies

Nginx SSL_CTX_use_PrivateKey failed: fix the private key

By · Last verified

Error messagenginx: [emerg] SSL_CTX_use_PrivateKey("/etc/nginx/ssl/example.com.key") failed

Nginx prints this, or the related cannot load certificate key "...": PEM_read_bio_PrivateKey() failed, when it cannot use the private key in ssl_certificate_key. The text in parentheses after failed is the real reason: a mismatched key, a file that is not a PEM key, an encrypted key, or a file Nginx cannot read.

Quick fix

The reason in parentheses decides the fix.

Validate the key and the certificate pair outside Nginx:

sudo openssl pkey -in /etc/nginx/ssl/example.com.key -noout && echo "key parses"
sudo openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -pubkey | openssl sha256
sudo openssl pkey -in /etc/nginx/ssl/example.com.key -pubout | openssl sha256

Then match the reason Nginx printed:

Reason in the log Meaning Go to
key values mismatch key belongs to another certificate key values mismatch
no start line, DECODER routines::unsupported not a PEM private key Cause 2
bad decrypt, bad password read, passphrase prompt encrypted key Cause 3
Permission denied, No such file or directory file access Cause 4

Fix, then run sudo nginx -t && sudo systemctl reload nginx.

Causes

1. The key does not match the certificate

A key that does not match the certificate is the most frequent reason behind SSL_CTX_use_PrivateKey ... failed; see key values mismatch.

2. The file is not a PEM private key

Nginx expects a PEM block such as -----BEGIN PRIVATE KEY-----, BEGIN RSA PRIVATE KEY or BEGIN EC PRIVATE KEY. DER files, PKCS#12 (.pfx/.p12) bundles, a certificate given as the key, or an empty file produce decoder errors such as no start line (OpenSSL 1.1.1) or DECODER routines::unsupported (OpenSSL 3).

  • Confirm: head -1 example.com.key does not show a BEGIN ... PRIVATE KEY line, or file example.com.key reports binary data.
  • Fix: convert:
# DER to PEM
openssl pkey -inform DER -in example.com.der -out example.com.key
# PKCS#12 to PEM key
openssl pkcs12 -in site.pfx -nocerts -nodes -out example.com.key

Also check for a UTF-8 byte-order mark or Windows line endings added by an editor (dos2unix removes them).

3. The key is encrypted

Keys created with a passphrase start with BEGIN ENCRYPTED PRIVATE KEY (or contain Proc-Type: 4,ENCRYPTED). Nginx then prompts for the passphrase on the console, and service managers fail with bad decrypt or bad password read.

  • Fix: add the passphrase to a root-only file and reference it:
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_password_file   /etc/nginx/ssl/example.com.pass;

or decrypt once with openssl pkey -in enc.key -out example.com.key and protect the result with chmod 600.

4. File permissions, paths or SELinux

  • Confirm: the message contains BIO_new_file() failed with Permission denied or No such file or directory. On RHEL-family systems, ls -Z shows a label such as user_home_t for files moved from a home directory.
  • Fix: correct the path, set chown root:root and chmod 600, and on SELinux systems restore labels with sudo restorecon -Rv /etc/nginx/ssl.

5. Unsupported key type for the OpenSSL build

Old OpenSSL builds cannot load newer key types, and some FIPS-mode builds reject small or non-approved keys.

  • Fix: use an RSA 2048+ or ECDSA P-256/P-384 key, which every current build supports.

Fixes by environment

On every system, Nginx needs a PEM key that matches the certificate, that it can decrypt, and that the master process can read.

Debian / Ubuntu: keys usually live under /etc/ssl/private/ (mode 710, group ssl-cert); keep Nginx's key there or under /etc/nginx/ssl/.

RHEL / Rocky / AlmaLinux: put keys under /etc/pki/tls/private/ or /etc/nginx/ssl/ and run restorecon after copying.

Docker: mount keys read-only and check the user the container starts as; official Nginx images start the master as root, but rootless variants may need the key readable by their user.

Let's Encrypt: reference /etc/letsencrypt/live/<name>/privkey.pem; Certbot writes unencrypted PEM keys with restrictive permissions.

Don't do this

  • chmod 644 or 777 on the key to "fix permissions". Any local user or compromised web application could then copy the key.
  • Put the passphrase in the Nginx config or a world-readable file. Use ssl_password_file with root-only permissions.
  • Store keys inside the web root. A misconfigured location block can serve them to anyone.

FAQ

Nginx asks "Enter PEM pass phrase" on every restart. How do I stop it?

The key is encrypted. Either list the passphrase in a file referenced by ssl_password_file (readable only by root), or write a decrypted copy with openssl pkey -in enc.key -out example.com.key and protect it with chmod 600. Automated restarts cannot type a passphrase.

I have a .pfx file from Windows. Which part goes into ssl_certificate_key?

Extract the key with openssl pkcs12 -in site.pfx -nocerts -nodes -out example.com.key and the certificate chain with -nokeys. The SSL converter explains each format.

Does Nginx need the key to be readable by the www-data or nginx user?

No. The master process runs as root and reads certificates and keys at start-up. Keep keys owned by root with mode 600; worker processes do not need access.

Sources

  1. nginx ngx_http_ssl_module (ssl_certificate_key, ssl_password_file)
  2. nginx: Configuring HTTPS servers
  3. OpenSSL openssl-pkey
  4. OpenSSL openssl-rsa