How to Change NGINX User Permissions to Fix PHP mkdir() Permission Denied Errors


3 views

When switching from Apache to NGINX, a common issue arises with file system permissions. The key difference lies in how each web server handles process ownership:

# Apache typically runs as:
www-data:www-data

# While NGINX default user varies by OS:
nginx:nginx (CentOS/RHEL)
www-data:www-data (Debian/Ubuntu)

First verify the complete directory path permissions where your PHP script tries to create folders:

namei -l /full/path/to/target_directory
ls -ld /var/www

Common misconfigurations include:

  • Parent directories without execute (+x) permission
  • Incorrect group ownership on document root
  • SELinux/AppArmor restrictions (check with getenforce)

For PHP applications, we need to synchronize three components:

# NGINX main config (/etc/nginx/nginx.conf)
user www-data;
worker_processes auto;

# PHP-FPM pool config (/etc/php/7.x/fpm/pool.d/www.conf)
listen.owner = www-data
listen.group = www-data
user = www-data
group = www-data

Here's a complete setup example for Ubuntu/Debian systems:

# Set permissions recursively
sudo chown -R www-data:www-data /var/www
sudo find /var/www -type d -exec chmod 755 {} \;
sudo find /var/www -type f -exec chmod 644 {} \;

# Create PHP upload directory with correct perms
sudo mkdir -p /var/www/uploads
sudo chown www-data:www-data /var/www/uploads
sudo chmod 775 /var/www/uploads

# Verify PHP can create subdirectories
<?php
$path = '/var/www/uploads/new_folder';
if (!file_exists($path)) {
    mkdir($path, 0775, true); // 0775 allows group write
    chown($path, 'www-data');
    chgrp($path, 'www-data');
}
?>

For more complex environments consider:

  • Using POSIX ACLs for granular control:
    setfacl -R -m u:www-data:rwx /var/www
  • Creating a dedicated application user:
    sudo useradd -r -s /sbin/nologin webapp
    sudo usermod -a -G webapp www-data

Check effective permissions with:

# Show running processes
ps aux | grep -E 'nginx|php-fpm'

# Test as web server user
sudo -u www-data mkdir /tmp/test_dir

When switching from Apache to NGINX, a common stumbling block is file system permissions. The error Warning: mkdir(): Permission denied typically occurs because PHP-FPM (which processes PHP scripts under NGINX) is running under a different user than the web directory owner.

First, verify the current user configuration:

ps aux | grep nginx
ps aux | grep php-fpm

You'll typically see NGINX running as www-data or nginx, while PHP-FPM might use a separate user like php-fpm.

Edit the NGINX configuration file (usually at /etc/nginx/nginx.conf):

user www-data;
worker_processes auto;
pid /run/nginx.pid;
...

Change www-data to your desired user (must exist in the system).

For PHP-FPM, edit the pool configuration (often at /etc/php/{version}/fpm/pool.d/www.conf):

[www]
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
...

Ensure these values match your NGINX user.

For a typical LEMP stack setup:

# Create a dedicated user
sudo adduser webapp --system --no-create-home

# Set directory permissions
sudo chown -R webapp:webapp /var/www/html
sudo chmod -R 755 /var/www/html

# Configure NGINX
sudo nano /etc/nginx/nginx.conf
# Set: user webapp;

# Configure PHP-FPM
sudo nano /etc/php/8.2/fpm/pool.d/www.conf
# Set: user = webapp
#      group = webapp
#      listen.owner = webapp
#      listen.group = webapp

# Restart services
sudo systemctl restart nginx
sudo systemctl restart php8.2-fpm

For more complex setups, consider modifying your PHP code to handle permissions more gracefully:

// Try creating directory with error handling
if (!is_dir($path)) {
    try {
        if (!mkdir($path, 0755, true)) {
            throw new RuntimeException("Directory creation failed");
        }
    } catch (Exception $e) {
        error_log("Directory error: " . $e->getMessage());
        // Fallback: attempt with different permissions
        mkdir($path, 0775, true);
        chmod($path, 0755);
    }
}

If issues persist:

# Check SELinux status (if applicable)
sestatus

# Verify parent directory permissions
namei -l /path/to/your/directory