Solving “nginx: [emerg] BIO_new_file: Permission denied” SSL Certificate Error


2 views

The error error:0200100D:system library:fopen:Permission denied occurs when NGINX lacks read permissions for your SSL certificate (.crt) or key (.key) files. Despite correct ownership or even chmod 777, the issue may persist due to deeper system-level restrictions.

# Verify file permissions and ownership  
ls -l /etc/nginx/ssl/mysite_com/mysite_com.crt  
# Expected output:  
# -rw-r--r-- 1 nginx nginx 1234 Jun  1 12:34 /etc/nginx/ssl/mysite_com/mysite_com.crt  

# Check SELinux context (if applicable)  
ls -Z /etc/nginx/ssl/mysite_com/mysite_com.crt  

1. Permission Hierarchy: Ensure all parent directories (/etc/nginx/ssl) grant execute (x) permission to the NGINX user:

sudo chmod +x /etc/nginx /etc/nginx/ssl /etc/nginx/ssl/mysite_com  

2. AppArmor/SELinux: Override security module restrictions:

# For AppArmor (Ubuntu):  
sudo aa-complain /usr/sbin/nginx  

# For SELinux (RHEL/CentOS):  
sudo chcon -Rt httpd_sys_content_t /etc/nginx/ssl/  

If the error persists, use strace to trace system calls:

sudo strace -e trace=file nginx -t 2>&1 | grep mysite_com.crt  
# Look for EACCES (Permission Denied) errors  

Ensure your server block references the correct paths:

server {  
    listen 443 ssl;  
    server_name mysite.com;  
    ssl_certificate /etc/nginx/ssl/mysite_com/mysite_com.crt;  
    ssl_certificate_key /etc/nginx/ssl/mysite_com/mysite_com.key;  
    # Rest of the config...  
}  

After changes, always test with sudo nginx -t and reload using sudo systemctl reload nginx.


The error message error:0200100D:system library:fopen:Permission denied indicates that NGINX cannot read your SSL certificate file due to filesystem permissions. This typically happens when:

  • The NGINX worker process user lacks read permissions
  • SELinux/apparmor security contexts are misconfigured
  • The certificate path contains symlinks with incorrect permissions
  • The parent directory has restrictive permissions

First, check the current permissions and ownership:

ls -la /etc/nginx/ssl/mysite_com/mysite_com.crt

You should see output similar to:

-rw-r--r-- 1 root root 5432 May 15 10:00 /etc/nginx/ssl/mysite_com/mysite_com.crt

For most Linux distributions running NGINX:

sudo chown root:www-data /etc/nginx/ssl/mysite_com/mysite_com.crt
sudo chmod 640 /etc/nginx/ssl/mysite_com/mysite_com.crt

If using CentOS/RHEL with SELinux:

sudo chcon -R -t httpd_sys_content_t /etc/nginx/ssl/

Verify which user NGINX runs as:

ps aux | grep nginx

Common configurations:

  • Debian/Ubuntu: www-data
  • CentOS/RHEL: nginx
  • Arch Linux: http

For deeper investigation, trace the file access attempts:

sudo strace -e openat -p $(pgrep -f "nginx: worker")

Here's a full remediation script:

# Set proper ownership
sudo chown -R root:www-data /etc/nginx/ssl/

# Set directory permissions
sudo chmod -R 750 /etc/nginx/ssl/

# Set file permissions
sudo find /etc/nginx/ssl/ -type f -exec chmod 640 {} \;

# If using SELinux
sudo semanage fcontext -a -t httpd_sys_content_t "/etc/nginx/ssl(/.*)?"
sudo restorecon -Rv /etc/nginx/ssl/

# Reload NGINX
sudo nginx -t && sudo systemctl reload nginx

Consider this more secure directory structure:

/etc/nginx/
├── ssl/
│   ├── certs/          # 750 root:www-data
│   │   └── mysite_com.crt
│   ├── private/        # 710 root:www-data
│   │   └── mysite_com.key
│   └── dhparams.pem    # 640 root:www-data

After making changes, test with:

sudo -u www-data cat /etc/nginx/ssl/mysite_com/mysite_com.crt > /dev/null
sudo nginx -t