Troubleshooting Nginx Permission Denied Errors on Non-Standard Ports (8090, 9090)


2 views

During a recent deployment, I encountered an odd Nginx behavior where standard ports (80, 8080) worked perfectly, but attempts to use ports like 8090 or 9090 resulted in permission errors:

2023/08/15 14:22:45 [emerg] 30181#0: bind() to 0.0.0.0:8090 failed (13: Permission denied)

The root cause lies in SELinux (Security-Enhanced Linux) which is enabled by default on Fedora/RHEL systems. SELinux implements Mandatory Access Control (MAC) that restricts what ports services can bind to.

Check SELinux status with:

sestatus
# Should show: SELinux status: enabled

To see which ports SELinux permits Nginx to bind to:

semanage port -l | grep http
# Typical output:
http_port_t      tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

Notice 8090 and 9090 are missing from this list.

To permanently allow Nginx to bind to port 8090:

sudo semanage port -a -t http_port_t -p tcp 8090
sudo semanage port -a -t http_port_t -p tcp 9090

Verify the changes:

semanage port -l | grep http_port_t

For testing purposes only, you can temporarily set SELinux to permissive mode:

sudo setenforce 0
# Remember to revert after testing:
sudo setenforce 1

If you prefer to understand the exact denial before making changes:

sudo ausearch -m avc -c nginx | grep denied
sudo grep nginx /var/log/audit/audit.log | audit2allow

After implementing Solution 1, test your Nginx configuration:

sudo nginx -t
sudo systemctl restart nginx
ss -tulnp | grep nginx

For advanced users, consider using systemd socket activation which handles port binding differently:

[Unit]
Description=NGINX Socket Activation

[Socket]
ListenStream=8090
BindIPv6Only=both
Service=nginx.service

[Install]
WantedBy=sockets.target

When working with nginx on Linux systems, you might encounter permission issues when binding to non-standard ports (anything above 1024) while standard ports like 80 or 8080 work fine. This typically manifests with errors like:

2023/02/15 14:30:45 [emerg] 30181#0: bind() to 0.0.0.0:8090 failed (13: Permission denied)

The original poster noted several important details:

  • Ports 80 and 8080 work without issues
  • Port 8090 fails with permission denied
  • Other services (like Python's SimpleHTTPServer) can bind to 8090
  • nginx runs as user 'nginx' which belongs to group 'git'

SELinux Context Issues

On Fedora systems (which use SELinux by default), this is often the root cause. Check current settings:

# Check SELinux status
sestatus

# View current port contexts
semanage port -l | grep http

To allow nginx to bind to port 8090:

# Add the port to http_port_t context
semanage port -a -t http_port_t -p tcp 8090

# Verify the change
semanage port -l | grep http_port_t

Firewall Configuration

While this typically wouldn't cause a bind error, it's worth checking:

# Check firewall rules
firewall-cmd --list-all

# Add port 8090 if needed
firewall-cmd --permanent --add-port=8090/tcp
firewall-cmd --reload

Process Capabilities

nginx might need special capabilities to bind to non-standard ports:

# Check current capabilities
getcap /usr/sbin/nginx

# Set required capabilities
setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx

If you can't modify SELinux policies:

# Temporary solution (not recommended for production)
setenforce 0

# Or create custom policy module
audit2allow -a -M nginx_port
semodule -i nginx_port.pp

After making changes:

# Restart nginx
systemctl restart nginx

# Verify port binding
netstat -tulnp | grep nginx
ss -tulnp | grep nginx

Here's a complete working server block for port 8090:

server {
    listen 8090;
    server_name example.com;
    
    location / {
        root /var/www/html;
        index index.html;
    }
    
    access_log /var/log/nginx/8090_access.log;
    error_log /var/log/nginx/8090_error.log;
}

Remember to test your configuration before applying:

nginx -t