The Nginx SSL certificate not found error means Nginx tried to load your SSL certificate and private key files for a specific server block, but it couldn’t find them at the specified paths.
Here are the most common reasons and how to fix them:
1. Incorrect File Paths in Nginx Configuration
- Diagnosis: Check your Nginx server block configuration file (usually in
/etc/nginx/sites-available/or/etc/nginx/conf.d/). Look for thessl_certificateandssl_certificate_keydirectives. - Cause: The paths you’ve specified for your certificate (
.crtor.pem) and private key (.key) files don’t actually exist where Nginx is looking. This is the most frequent culprit. - Fix:
- Navigate to the directory specified in your
ssl_certificateandssl_certificate_keydirectives usingls -l /path/to/your/ssl/files/. - If the files aren’t there, correct the paths in your Nginx configuration file. For example, if your files are actually in
/etc/letsencrypt/live/yourdomain.com/, change your config to:ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; - This works because Nginx needs to know the exact location of these files to load them into memory for SSL/TLS connections.
- Navigate to the directory specified in your
- Why it happens: Typos, moving certificate files without updating Nginx, or using default paths that don’t match your installation.
2. Permissions Issues
- Diagnosis: After verifying the paths are correct, check the permissions of the certificate and key files using
ls -l /path/to/your/ssl/files/. - Cause: The
www-datauser (or whatever user Nginx runs as, often found in/etc/nginx/nginx.confwith theuserdirective) doesn’t have read access to the certificate and private key files. The private key is especially sensitive. - Fix: Ensure the Nginx user can read the files. For Let’s Encrypt files, this typically involves giving read access to the group Nginx is part of (often
www-dataornginx).sudo chmod 644 /etc/letsencrypt/live/yourdomain.com/fullchain.pem sudo chmod 600 /etc/letsencrypt/live/yourdomain.com/privkey.pem sudo chown root:www-data /etc/letsencrypt/live/yourdomain.com/fullchain.pem sudo chown root:www-data /etc/letsencrypt/live/yourdomain.com/privkey.pemchmod 644for the certificate allows the owner to read/write, and others to read.chmod 600for the private key only allows the owner to read/write, which is crucial for security.chown root:www-dataensures the files are owned by root but readable by the Nginx worker process.
- Why it happens: Incorrect file permissions prevent the Nginx worker process from accessing the sensitive private key or the certificate itself.
3. Incomplete Certificate Chain
- Diagnosis: Use
openssl x509 -in /path/to/your/certificate.crt -text -nooutto inspect the certificate andopenssl verify -CAfile /path/to/your/chain.crt /path/to/your/certificate.crt. - Cause: You might be providing only the server certificate and not the intermediate certificates (the certificate chain). Browsers need the full chain to trust your certificate.
- Fix: Concatenate your server certificate with any intermediate certificates provided by your Certificate Authority (CA) into a single file. Let’s Encrypt often provides this as
fullchain.pem.
Then, pointcat your_domain.crt intermediate_chain.crt > fullchain.pemssl_certificateto thisfullchain.pemfile:ssl_certificate /path/to/your/fullchain.pem; ssl_certificate_key /path/to/your/privkey.pem; - Why it happens: Browsers expect a complete chain of trust from your certificate back to a trusted root CA. Missing intermediates break this chain.
4. SELinux or AppArmor Restrictions
- Diagnosis: Check system logs for SELinux or AppArmor denials. On systems with SELinux, use
sudo ausearch -m avc -ts recent. On AppArmor systems, check/var/log/audit/audit.logor/var/log/syslog. - Cause: Security modules like SELinux or AppArmor might be preventing Nginx from accessing files in non-standard locations, even if file permissions are correct.
- Fix:
- SELinux: If using Let’s Encrypt in its default location, SELinux usually has rules for it. If you’ve moved files, you might need to adjust the SELinux context:
sudo semanage fcontext -a -t httpd_cert_t "/path/to/your/ssl/files(/.*)?" sudo restorecon -Rv /path/to/your/ssl/files - AppArmor: Edit the Nginx AppArmor profile (e.g.,
/etc/apparmor.d/usr.sbin.nginx) to include read access for your certificate and key file paths. Then reload AppArmor:sudo systemctl reload apparmor
- SELinux: If using Let’s Encrypt in its default location, SELinux usually has rules for it. If you’ve moved files, you might need to adjust the SELinux context:
- Why it happens: These security modules enforce strict access controls, and Nginx might be denied access to certificate files if their location isn’t explicitly allowed.
5. Certificate or Key File Corruption
- Diagnosis: Try to read the files and check their size.
sudo openssl x509 -in /path/to/your/fullchain.pem -text -noout sudo openssl rsa -in /path/to/your/privkey.pem -check - Cause: The certificate or private key file might be corrupted during download, transfer, or due to disk issues.
- Fix: Re-download or re-generate your certificate and private key. If using Certbot, you can run
sudo certbot renewto attempt renewal. - Why it happens: Corrupted files contain invalid data, preventing Nginx from parsing them correctly.
6. Nginx Not Reloaded/Restarted After Changes
- Diagnosis: After making any configuration changes, always test Nginx configuration and reload.
sudo nginx -t sudo systemctl reload nginx - Cause: You’ve corrected the paths or permissions, but Nginx is still running with its old configuration, which points to the non-existent files.
- Fix: Apply the Nginx configuration test and reload command.
- Why it happens: Nginx loads its configuration into memory on startup or reload. Until this is done, it operates with the previously loaded configuration.
After fixing these, you should test your Nginx configuration with sudo nginx -t and then reload Nginx with sudo systemctl reload nginx.
The next error you might encounter is an "SSL handshake failed" error if your cipher suites are misconfigured or if the client and server cannot agree on a TLS version.