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