Nginx SSL Certificate Chain File Error: Fixing “No Such File or Directory” Issue


1 views

The error you're encountering is quite specific:

nginx: [emerg] SSL_CTX_use_certificate_chain_file("/path/to/cert.pem") failed (SSL:
error:02001002:system library:fopen:No such file or directory
error:20074002:BIO routines:FILE_CTRL:system lib error:140DC002:SSL
routines:SSL_CTX_use_certificate_chain_file:system lib)

This indicates Nginx cannot access the certificate file at the specified path, despite your confirmation that the file exists.

Let's verify several potential issues:

1. File Permissions

Check if Nginx has proper read permissions:

ls -l /path/to/cert.pem

You should see something like:

-rw-r--r-- 1 root root 1234 Jun  1 12:34 /path/to/cert.pem

If not, adjust permissions:

chmod 644 /path/to/cert.pem
chown root:root /path/to/cert.pem

2. SELinux Context (For RHEL/CentOS)

Check and set proper context:

ls -Z /path/to/cert.pem
chcon -t cert_t /path/to/cert.pem

3. Certificate Chain Format

Verify your merged certificate format is correct. A proper chain should look like:

-----BEGIN CERTIFICATE-----
(Your domain certificate)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Intermediate certificate)
-----END CERTIFICATE-----

Here's a proper SSL configuration snippet:

server {
    listen 443 ssl;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/private.key;
    
    # Other SSL settings...
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    # ...
}

If the issue persists, try these steps:

1. Test with Absolute Path

Use the full absolute path in your Nginx config:

ssl_certificate /etc/nginx/ssl/cert.pem;

2. Verify File with OpenSSL

Check if OpenSSL can read the file:

openssl x509 -in /path/to/cert.pem -text -noout

3. Check Nginx Worker Process User

Ensure the Nginx worker user can access the file:

ps aux | grep nginx
sudo -u www-data cat /path/to/cert.pem
  • File exists at specified path
  • Proper permissions (644)
  • Correct ownership (root:root or nginx user)
  • Valid certificate chain format
  • No SELinux restrictions (or proper context)
  • Using absolute path in configuration

When you encounter the error SSL_CTX_use_certificate_chain_file() failed with a No such file or directory message, Nginx is telling you it cannot locate or access your SSL certificate file despite your confidence in its existence. This typically points to one of several underlying issues we need to investigate.

Based on my experience administering hundreds of Nginx servers, here are the most frequent offenders:

1. Incorrect file permissions (nginx worker process can't read the file)
2. SELinux/AppArmor restrictions (common on RHEL/CentOS and Ubuntu)
3. Symbolic link resolution issues
4. Certificate chain formatting problems
5. Case sensitivity mismatches in paths

You mentioned merging domain.crt and intermediate.crt manually. Let me share the proper way to concatenate certificates:

# Correct merging order (your domain cert first):
cat domain.crt intermediate.crt > cert.pem

# Verify the certificate chain structure
openssl crl2pkcs7 -nocrl -certfile cert.pem | openssl pkcs7 -print_certs -noout

A common mistake is including unnecessary blank lines between certificates or incorrect line endings. The file should use UNIX line endings (LF) and have exactly one blank line between certificates.

Run these commands to verify permissions (adjust paths as needed):

# Check file existence and permissions
ls -l /path/to/cert.pem

# Verify nginx worker user can access the file
sudo -u nginx test -r /path/to/cert.pem && echo "Readable" || echo "Not readable"

# Check parent directory permissions (often overlooked)
namei -l /path/to/cert.pem

For systems with mandatory access controls:

# For SELinux (RHEL/CentOS):
ls -Z /path/to/cert.pem
sudo chcon -R -t cert_t /path/to/cert.pem

# For AppArmor (Ubuntu/Debian):
sudo aa-status | grep nginx

Add this to your nginx.conf for better debugging:

events {}
http {
    error_log /var/log/nginx/ssl_error.log debug;
    server {
        listen 443 ssl;
        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;
        location / {
            return 200 "SSL Test OK";
        }
    }
}

Then test with:

sudo nginx -t
sudo tail -f /var/log/nginx/ssl_error.log

If the above doesn't resolve it, consider:

# 1. Try absolute path instead of relative:
ssl_certificate /full/path/to/cert.pem;

# 2. Verify file encoding:
file /path/to/cert.pem

# 3. Check for hidden characters:
cat -A /path/to/cert.pem

# 4. Test with a simple self-signed cert as control:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /tmp/test.key -out /tmp/test.crt \
    -subj "/CN=localhost"