Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →The error usually means the account performing the upload cannot traverse one of the parent directories or cannot write to the destination directory. Find the web service’s actual Unix user, inspect every path component, then grant write access only to the upload directory through a web-server group or a narrowly scoped ACL. Do not solve it with chmod 777.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
What “permission denied” means for a /var/www upload
Linux checks permissions for the identity that performs the operation. A browser upload is normally handled by a web application running as a service account, not by the user you use for SSH or deployment. For every component of a path such as /var/www/example/uploads/photo.jpg, that identity must be able to search (execute) the directories leading to the destination. The destination directory must also allow writing to create the new entry.
As an Amazon Associate I earn from qualifying purchases.
Directory permissions have a different meaning from file permissions: read permits listing entries, write permits creating or deleting entries, and execute permits crossing or searching the directory. The Debian Handbook’s explanation of Unix rights describes why a directory can appear readable yet still reject an upload.
On Debian and Ubuntu, www-data is commonly the web-server account. Other distributions and configurations may use apache or another account, so verify the service configuration rather than assuming the name. Nextcloud’s source-installation documentation also emphasizes matching ownership to the account actually running the web server.
#1 Best Overall
Identify the account that is being denied
Your SSH account is not necessarily the application account
Running touch as your login user proves only that your login user has access. PHP, a framework worker, or another upload process may run under a separate Unix identity. First inspect your current identity:
id
Then determine the configured service account. Check the web server’s unit or process configuration and use that exact name in the tests below. Substitute apache wherever your system uses that account instead of www-data.
Inspect every directory in the path
namei -l /var/www/example/uploads
ls -ld /var/www /var/www/example /var/www/example/uploads
stat -c '%A %U:%G %n' /var/www /var/www/example /var/www/example/uploads
getfacl -p /var/www/example/uploads
namei -l displays each component, making a blocked parent easy to spot. ls -ld shows the owner, group and mode without listing the directory’s contents. stat gives a compact, script-friendly view. getfacl reveals access-control-list entries that may grant or deny permissions beyond the basic owner/group/other bits.
Look for these conditions:
- The service account is neither the owner nor a member of the owning group.
- The destination directory lacks group or owner write permission for that account.
- A parent such as
/var/wwwor/var/www/examplelacks execute permission for the account or its group. - An ACL changes the effective permission shown by the ordinary mode bits.
Reproduce the operation as the service account
sudo -u www-data touch /var/www/example/uploads/.perm-test
sudo rm /var/www/example/uploads/.perm-test
A successful create-and-remove test confirms that the Unix permission path is usable by the web process. If the first command fails, fix the path or ACL rather than changing permissions on unrelated files. Remove the test file only after checking whether the application created it with an unexpected owner or mode.
A safe ownership and group layout
For a conventional deployment, keep the application owned by the deploy user and assign the web server to the application’s group. Give the web process write access only where it must create uploads, caches or generated assets. This is easier to audit than making the entire document tree writable.
Apply the example layout
The following sequence uses a deploy account named deploy, the Debian-style web group www-data, and the path /var/www/example. Replace all three values with those used on your host.
Recommended Free Tools
sudo chown -R deploy:www-data /var/www/example
sudo find /var/www/example -type d -exec chmod 2755 {} +
sudo find /var/www/example -type f -exec chmod 644 {} +
sudo chmod 2775 /var/www/example/uploads
The recursive chown makes the deploy user the owner and the web group the group owner. The directory mode 2755 includes the setgid bit (the leading 2), so newly created entries normally inherit the directory’s group; it also leaves directories searchable while avoiding general write access. Regular files receive 644, which keeps them non-executable. The upload directory receives 2775: the owner and group can read, write and traverse it, and the setgid bit helps preserve group ownership for new entries.
New-file group inheritance depends on the filesystem and mount behavior, so verify the result instead of assuming it. The GNU Coreutils mode-structure documentation explains the setgid directory bit and its effect on group inheritance.
Verify the repaired path
sudo -u www-data touch /var/www/example/uploads/.perm-test
sudo -u www-data sh -c 'printf test > /var/www/example/uploads/.perm-test'
ls -l /var/www/example/uploads/.perm-test
sudo rm /var/www/example/uploads/.perm-test
getfacl -p /var/www/example/uploads
Confirm that the file is owned by the expected service identity or inherited group, then remove it. Test an actual application upload afterward, because the application may write to a different subdirectory, rename a temporary file, or create a second file during processing.
When changing the main group is not appropriate: use an ACL
Access-control lists are useful when the existing owner and group must remain unchanged, or when only one service account needs an exception. They let you grant the web account access to a specific directory without making the complete site group-writable.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Grant access to one upload directory
sudo setfacl -m u:www-data:rwx /var/www/example/uploads
sudo setfacl -d -m u:www-data:rwx /var/www/example/uploads
getfacl -p /var/www/example/uploads
The first command grants the running service account read, write and execute access to the directory. The second creates a default ACL so entries created there inherit an appropriate access entry. The ACL shown by getfacl is the authoritative check; an ACL mask can limit the effective permissions displayed for named users and groups.
Use an ACL when the exception is intentionally narrow and document who owns it. Remove it when the application no longer needs the access:
sudo setfacl -x u:www-data /var/www/example/uploads
sudo setfacl -k /var/www/example/uploads
getfacl -p /var/www/example/uploads
The Debian Handbook covers ACL entries and inheritance. ACLs provide finer granularity than a shared group, but they require administrators to inspect ACLs as well as ordinary mode bits during future troubleshooting.
Choose the least-permissive repair
| Approach | Identity receiving access | Write scope | New-file inheritance | Audit and exposure |
|---|---|---|---|---|
| Deploy owner plus web group | Any member of the selected group, including the web service | Only directories explicitly made group-writable, such as uploads |
Setgid commonly preserves the group; verify on the mounted filesystem | Simple to inspect with ls; exposure is limited to group members |
| Per-service ACL | The named service account | Only the directory and permissions named in the ACL | Default ACLs can apply permissions to descendants | Fine-grained and reversible, but requires getfacl checks |
| World-writable mode | Every local user and process | Any process can write where the mode is applied | Behavior is broad and difficult to control | Greatest exposure if the web process or another local account is compromised; not an appropriate repair |
Prefer the first option when a clearly defined deployment group is acceptable. Prefer an ACL when one service needs an exception and changing group membership would grant access to too many accounts.
Why common recursive chmod fixes fail
chmod -R 755 does not make uploads writable
Mode 755 gives the owner write permission but gives the group and other users only read and execute permission. A web process that is not the owner still cannot create files. Applying it recursively also marks regular files executable, which is unnecessary and can create misleading security reviews.
Rank #4
chmod -R 644 breaks directory traversal
Mode 644 is a file-style mode. Directories need execute permission to be searched or entered; removing it can prevent access even when the directory listing appears readable. Set directory and regular-file modes separately, as in the find commands above.
Changing only the target file is too late
An upload normally creates a new directory entry. There may be no target file to chmod beforehand, and a parent directory can deny the operation before the kernel evaluates the final name. Check every component with namei -l.
When ownership changes themselves fail
chown can return EACCES, EPERM or EROFS. The Linux chown manual documents these failure classes and additional causes.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Insufficient privilege: run the administrative command with
sudoand confirm that your account is authorized to use it. - Read-only filesystem: an
EROFSresult means the mounted filesystem cannot accept metadata changes. Check the mount state before retrying. - Immutable or append-only attributes: filesystem flags can prevent ownership or content changes even for an administrator. Inspect and remove such attributes only when you understand why they were set.
- NFS UID/GID mapping: network filesystems may map numeric IDs differently between the client and server. Verify identity mapping on both sides rather than relying on local usernames.
Do not repeatedly run chown -R until an error disappears. A recursive ownership change can alter files deliberately owned by another service and can hide the underlying mount or identity problem.
Diagnose a denial that persists after the mode change
Check the exact path used by the application
Configuration may point to a different directory from the one you inspected, such as a release-specific path, a symlink target or a nested cache directory. Run namei -l against the exact absolute path shown in the application configuration and repeat the service-account test there.
Best Value
Check the parent execute bits again
A destination can show drwxrwxr-x and still be unreachable if /var, /var/www or the site directory denies search permission to the service identity. The denial is attached to the first path component that cannot be traversed, not necessarily to the final directory.
Check ACLs and their effective mask
An ACL entry can grant a named user access, while its mask limits the effective result. Compare getfacl output before and after the change, and look for default ACLs that apply to newly created directories or files.
Check group membership in the running service
Adding www-data to a group does not necessarily alter an already-running process. Restart the relevant service after a group-membership change, then repeat the sudo -u test. If the service is configured to drop privileges to another account, use that account instead.
Check filesystem behavior
If permissions look correct but creation still fails, investigate a read-only mount, immutable or append-only flags, or NFS identity mapping. These conditions are distinct from ordinary mode bits and require a filesystem or deployment fix.
Security and maintenance checklist
- Identify the account that performs the upload; do not infer it from your SSH username.
- Inspect every directory component with
namei -land verify ownership and modes withlsorstat. - Use a deploy-owner/web-group layout or a narrowly scoped ACL.
- Make only upload, cache or generated-content directories writable by the service.
- Apply directory and file modes separately; never use a blanket recursive mode that gives files execute bits or removes directory traversal.
- Use setgid or default ACLs when newly created entries must retain the intended group or service access, then verify inheritance on the actual filesystem.
- Test creation and deletion as the service account, not only as an administrator.
- Inspect ACLs whenever ordinary mode bits do not explain the result.
- Record intentional ACLs and group memberships so a later deployment does not silently remove them.
- Reject
chmod 777: it gives every local user and compromised process write access and conceals the real identity or path problem.
Quick repair recipe
For a standard Debian or Ubuntu host where www-data is confirmed as the service account, the shortest safe sequence is:
- Inspect with
id,namei -l,ls -ldandgetfacl. - Set the deployment owner and web group:
sudo chown -R deploy:www-data /var/www/example. - Set directories to
2755, regular files to644, and the upload directory to2775. - Test with
sudo -u www-data touch /var/www/example/uploads/.perm-test, then remove the file. - If ownership must remain unchanged, replace the group change with a targeted ACL and verify it using
getfacl.
This sequence addresses the two requirements an upload needs: traversal through every parent directory and write permission on the directory where the new entry is created.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsQuick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




