Resolving Nginx Permission Denied (13) Errors for WebP Images Generated by PHP Imagick

Published: 2026-07-05
Author: DP
Views: 0
Category: PHP
Content
## 1. The Problem In daily web development and operations, you might encounter situations where Nginx fails to access specific images and returns a `403 Forbidden` error. Checking the Nginx error logs usually reveals something like this: ```text [error] 111#111: *26717 open() "/var/www/wiki.lib00.com/public_resources/pics/article_cover.webp" failed (13: Permission denied), client: 180.127.x.x, server: wiki.lib00.com, request: "GET /pics/article_cover.webp HTTP/2.0" ``` Upon troubleshooting, you may find that the parent directory has correct permissions (`0777` or `0755`), and files uploaded directly via native PHP functions have the correct `0644` (readable) permissions. However, **WebP images processed and saved via the PHP Imagick extension end up with `0600` permissions**. Since `0600` only allows read/write access to the file owner, the Nginx worker process (usually `www-data` or `nginx`) cannot read the file, triggering the `Permission denied (13)` error. --- ## 2. Root Cause Analysis This is a classic Umask (User file-creation mode mask) issue. Under the hood, `Imagick::writeImage` calls the ImageMagick C library. In certain system environments or ImageMagick versions, its default file mask handling for creating new files is stricter than PHP's native `move_uploaded_file`. While PHP's `move_uploaded_file` tries to respect the web server's default permission settings, creating a file with `Imagick` is a "new file creation" process entirely restricted by the current PHP process's `umask`. This causes the newly generated file to lose read permissions for group and other users. --- ## 3. Solutions To completely resolve this permission issue in your `wiki.lib00` projects, we provide the following three solutions: ### Solution 1: Manually Set Permissions (Highly Recommended) The safest and most compatible approach in PHP is to explicitly call the `chmod` function after `writeImage`. This ensures that file permissions are always correct, regardless of server environment changes. ```php $image = new Imagick('source.jpg'); // ... Image processing logic ... $image->setImageFormat('webp'); $filePath = '/var/www/wiki.lib00.com/public_resources/pics/output.webp'; $image->writeImage($filePath); // Explicitly change permissions to 0644, allowing Nginx to read chmod($filePath, 0644); $image->clear(); $image->destroy(); ``` ### Solution 2: Dynamically Modify Umask in the Script If you prefer not to call `chmod` everywhere, you can modify the process's `umask` at the beginning of your image processing script. Setting `umask(0022)` ensures that new files are created with `0644` permissions. ```php // Set umask before processing images $oldUmask = umask(0022); // Execute Imagick save operation $image->writeImage($filePath); // Restore original umask to avoid affecting other operations umask($oldUmask); ``` ### Solution 3: Modify PHP-FPM Configuration (System-Level Fix) If your PHP runs via PHP-FPM, you can globally set the default umask in the FPM pool configuration file. This is a once-and-for-all method. 1. Locate the PHP-FPM pool configuration file (usually at `/etc/php/x.x/fpm/pool.d/www.conf`). 2. Find or add the following configuration: ```ini ; Set the umask for the pool umask = 0022 ``` 3. Restart the PHP-FPM service: `systemctl restart php-fpm`. --- ## 4. Bonus: Fixing Nginx Directory Index Forbidden Error While troubleshooting the above issue, you might also encounter a `directory index of ... is forbidden` error. This means that when accessing a directory (e.g., `wiki.lib00.com/`), Nginx cannot find a default index file (like `index.php`) and directory listing is disabled. **How to fix:** In the `location /` block of your Nginx configuration, ensure the correct `index` directive is set: ```nginx location / { root /var/www/wiki.lib00.com/public_resources/; index index.php index.html index.htm; } ```
Related Contents