Skip to content
Linux Tutorials

How to Fix Permission Denied Errors in Linux

A practical guide to diagnosing and fixing Linux permission errors on Ubuntu, Debian, Fedora, RHEL, Arch and openSUSE.

How to Fix Permission Denied Errors in Linux
How to Fix Permission Denied Errors in Linux

You type a command, press Enter, and Linux answers with two words every user meets sooner or later: Permission denied. It can appear when you run a script, edit a config file, mount a drive, log in over SSH, or start a container.

The error is never random. Some layer of the Linux security model said no, and your job is to find which one. This guide shows How to Fix Permission Denied Errors in Linux by diagnosing the cause first, instead of reaching for chmod 777 and hoping.

The steps cover Ubuntu, Debian 13, Fedora, RHEL 10 and its rebuilds (Rocky, AlmaLinux), Arch, and openSUSE. Where distros behave differently, I say so.

Why Linux Says “Permission Denied”

Before a process touches a file, Linux checks several layers, roughly in this order:

  1. Standard permissions: owner, group and others, each with read, write and execute.
  2. Directory traversal: you need execute (x) on every folder in the path.
  3. ACLs: extra per-user or per-group rules.
  4. Attributes and mount options: immutable flag, read-only mount, noexec.
  5. Mandatory access control: SELinux or AppArmor.
  6. Service sandboxing: systemd restrictions and containers.

Most guides stop at layer 1. The stubborn cases usually live in layers 2 to 6, so work through them in order.

Step 1: Read the Error Message Closely

The exact wording tells you where to look.

  • bash: ./script.sh: Permission denied means the file isn’t executable, or sits on a noexec mount.
  • cat: /etc/shadow: Permission denied means you need elevated rights.
  • mkdir: cannot create directory: Permission denied points at the parent directory.
  • Permission denied (publickey) is an SSH authentication problem, not a file problem.
  • Operation not permitted is a different error. It usually means an immutable flag, a missing capability, or a root-only action.

Note the full path and the command before you change anything.

Step 2: Check Ownership and Permissions

ls -l /path/to/file
id

Sample output:

-rw-r----- 1 root adm 4821 Oct 18 09:12 app.log

Read it like this: owner root can read and write, group adm can read, everyone else gets nothing. If your id output doesn’t list adm, you can’t open this file.

Check the whole path

People skip this, and it’s behind a lot of confusing cases. If you can’t enter a parent folder, the file’s own permissions are irrelevant. namei shows every component:

namei -l /var/www/site/uploads/photo.jpg

The directory that blocks you stands out immediately.

Reading the permission numbers

OctalSymbolicMeaning
7rwxread, write, execute
6rw-read, write
5r-xread, execute
4r–read only
0—no access

On a directory, x means “allowed to enter.” Without it you can’t cd in or reach anything inside, even with r. The Linux man-pages entry for chmod documents the full syntax, including the special setuid, setgid and sticky bits.

Step 3: Fix It with chmod

If the mode bits are wrong for the job, change them.

chmod +x script.sh      # make a script executable
chmod 644 file.txt      # owner read/write, others read
chmod 755 mydir/        # owner full, others enter and read
chmod 600 secret.key    # owner only

To fix a whole project tree without marking every text file executable:

find /path/to/project -type d -exec chmod 755 {} +
find /path/to/project -type f -exec chmod 644 {} +

A blanket chmod -R 755 makes all your files executable, which is messy and confuses some tools. The two find commands avoid that.

Why chmod 777 is a bad habit

chmod 777 “works” because it lets everyone do everything, including any other local user or a compromised service. When a tutorial recommends it, the author usually never found the real cause. A specific owner, group or ACL is almost always the better answer.

Step 4: Fix It with chown and Groups

If the mode bits are fine but the wrong account owns the file:

sudo chown youruser:yourgroup file.txt
sudo chown -R www-data:www-data /var/www/site

Web server account names differ by distro:

Distro familyTypical web server user
Debian, Ubuntuwww-data
RHEL, Fedora, openSUSE (Apache)apache
RHEL, Fedora (nginx)nginx
Arch (Apache)http

Join the right group instead

Often group membership is cleaner than changing ownership:

sudo usermod -aG groupname youruser

Keep the -a. Without it, you replace all your supplementary groups, which can remove your sudo access.

Group changes don’t reach sessions that are already open. Log out and back in, or start a shell with the group:

newgrp groupname

Common real-world cases:

  • Serial devices like /dev/ttyUSB0 need dialout on Debian and Ubuntu, and uucp on Arch.
  • The Docker socket needs the docker group, which is effectively root-equivalent. Add only trusted users, or use rootless Docker or Podman.
  • System logs without sudo usually mean joining adm (Debian, Ubuntu) or systemd-journal.

Step 5: Use sudo Correctly

If the task truly needs admin rights, sudo is the right tool. Watch for these traps.

Redirection runs before sudo

This fails:

sudo echo "setting=1" > /etc/myapp.conf

Your own shell opens the file before sudo starts. Use tee instead:

echo "setting=1" | sudo tee /etc/myapp.conf

Add -a to append rather than overwrite.

Your account may not be allowed to use sudo

DistroAdmin group
Ubuntu, Linux Mint, Debiansudo
Fedora, RHEL family, Arch, openSUSEwheel

On Debian, setting a root password during install can leave your user without sudo. Run su -, then usermod -aG sudo youruser. On Arch, installing sudo isn’t enough. Run visudo and uncomment the %wheel line.

For protected files, prefer sudoedit over opening an editor as root. It edits a copy as you and writes it back with privileges.

Step 6: Check ACLs

If ls -l looks fine but access still behaves oddly, look for a + at the end of the permission string, such as -rw-r--r--+. That marks an ACL.

getfacl file.txt
setfacl -m u:alice:rw file.txt
setfacl -R -m u:alice:rwX /srv/shared

For a shared folder where new files should inherit access, add a default ACL:

setfacl -d -m g:devs:rwX /srv/shared

ACLs work on ext4, XFS and Btrfs with default mount options on current distros. They beat widening “others” permissions.

Step 7: Check Attributes and Mount Options

Immutable files

If even root gets “Operation not permitted”:

lsattr file.txt
sudo chattr -i file.txt

An i in the lsattr output means the file is immutable, and chattr -i clears it.

Read-only and noexec mounts

If scripts won’t run from a USB drive, or writes fail on a mounted disk:

findmnt -T /path/to/file
sudo mount -o remount,rw /mnt/data

Look for ro or noexec in the options. For a permanent change, edit /etc/fstab carefully and test with sudo mount -a before rebooting. A disk can also flip to read-only after filesystem errors, so check dmesg before blindly remounting.

FAT, exFAT and NTFS drives

These filesystems don’t store Unix permissions, so chmod and chown do nothing useful. Ownership is set at mount time with the uid=, gid= and umask= options.

Step 8: Check SELinux

This is the classic “everything looks right and it still fails” case. SELinux is enforcing by default on Fedora and the RHEL family. It’s also the default on new installs of openSUSE Leap 16 and Tumbleweed, a change from the AppArmor default in Leap 15.x. Upgraded Leap systems can keep AppArmor.

getenforce
sudo ausearch -m avc -ts recent

If setroubleshoot-server is installed, sudo journalctl -t setroubleshoot prints plain-English suggestions. Fedora’s guide on troubleshooting problems related to SELinux notes that labeling mistakes are the most common cause, so check labels before touching policy.

Fix the label first

Files moved with mv keep their old label. Restore the correct one:

sudo restorecon -Rv /var/www/html

Custom directories

If a service legitimately uses a non-standard path, define the rule and apply it:

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mysite(/.*)?"
sudo restorecon -Rv /srv/mysite

Booleans

getsebool -a | grep httpd
sudo setsebool -P httpd_can_network_connect on

Test, don’t disable

sudo setenforce 0 is a fine diagnostic. If the error disappears, SELinux was the cause. Switch back with setenforce 1 and fix the label or boolean. Turning SELinux off permanently removes a real protection layer.

Step 9: Check AppArmor

Ubuntu and Debian ship AppArmor enabled, and so do openSUSE Leap 15.x and upgraded systems that kept it. A confined program can be blocked from a path even when Unix permissions allow access.

sudo aa-status
sudo journalctl -k | grep -i apparmor

Look for apparmor="DENIED" lines naming the profile and path. Typical fixes:

  • Add a rule to the local override file under /etc/apparmor.d/local/ for that profile.
  • Reload it with sudo apparmor_parser -r /etc/apparmor.d/profile.name.
  • To test, put one profile in complain mode with sudo aa-complain /path/to/binary, then restore it with aa-enforce.

A common example is MariaDB failing after you move its data directory. The profile only allows the default location, so the new path has to be added. Ubuntu’s official AppArmor documentation covers profile modes, reloading and customization.

Step 10: Check systemd Sandboxing and Containers

Service hardening

A service can run as the right user and still be blocked by its unit file. Options like ProtectHome=, ProtectSystem= and PrivateTmp= restrict what it can see. The systemd.exec documentation explains each one. Inspect the unit:

systemctl cat myservice

Then grant a specific writable path with a drop-in:

sudo systemctl edit myservice
[Service]
ReadWritePaths=/srv/data

Finish with sudo systemctl restart myservice.

Docker and Podman volumes

Bind mounts fail for two reasons: the container’s user ID doesn’t match the host file owner, or SELinux blocks access. For the second, add a relabel flag:

docker run -v /srv/data:/data:Z image

Use :z for a volume shared between containers and :Z for a private one. Never apply these to system directories such as /home or /etc.

Step 11: SSH “Permission denied (publickey)”

This looks like a file problem but usually isn’t. First, tighten permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519

Your home directory also shouldn’t be group-writable, because OpenSSH’s strict checks reject it. Run ssh -v user@host to see which key was offered and why it failed.

One more case: on a fresh openSUSE Leap 16 install, sshd accepts key-based login only and password login is off by default. If you never set up keys, you’ll see this exact error.

Quick Diagnostic Table

SymptomLikely causeFirst command
Script won’t runMissing execute bit or noexec mountls -l, findmnt -T
Can’t edit a file in /etcNeeds rootsudoedit file
Fails deep in a folder treeMissing x on a parentnamei -l path
Works as root, fails as a serviceSELinux, AppArmor or systemd sandboxausearch, journalctl -k, systemctl cat
Root is denied tooImmutable flag or read-only mountlsattr, findmnt
Access breaks after mvWrong SELinux labells -Z, restorecon
New group has no effectSession not refreshedid, then log in again

Comparing the Fix Methods

MethodScopeRisk if misusedBest for
chmodOne file or treeOver-granting accessWrong mode bits
chownOne file or treeLocking out other usersWrong owner
Group membershipEverything the group can reachOver-broad access (e.g. docker)Shared folders, devices
ACLsNamed users or groupsHard to audit at a glanceOne-off extra access
sudoA single commandRoot-owned files left behindTrue admin tasks
SELinux or AppArmor editsA single confined serviceWeakened policy if rushedConfined services

A simple rule: fix the narrowest layer that solves the problem. If a group works, don’t touch “others.” If a label fix works, don’t disable the policy.

Pros and Cons of the Main Approaches

chmod

  • Pros: instant, built into every distro, easy to reverse.
  • Cons: only fixes the mode bits, so it does nothing for SELinux or mount problems.

ACLs

  • Pros: grant access to one person without changing ownership.
  • Cons: the + flag is easy to overlook, so they get forgotten during audits.

Group membership

  • Pros: one change covers many files and survives new file creation.
  • Cons: needs a fresh login, and some groups carry far more power than they seem.

Fixing SELinux or AppArmor properly

  • Pros: the service works while protection stays on.
  • Cons: a steeper learning curve than flipping a switch.

Mistakes That Make Things Worse

  • Running everything with sudo. Root-owned files in your home folder cause new errors later. Repair with sudo chown -R $USER:$USER ~/folder.
  • Recursive changes on system paths. chmod -R or chown -R on /, /etc, /usr or /var can break the system. Check the path twice.
  • Ignoring umask. New files get default modes from umask. Run umask to check; 022 is typical and 077 makes private files.
  • Skipping setgid on shared folders. chmod g+s /srv/shared makes new files inherit the folder’s group.

A Worked Example

Say Nginx returns 403 after you move a site to /srv/site on a Fedora server.

  1. namei -l /srv/site/index.html shows every permission is fine.
  2. getenforce returns Enforcing.
  3. ausearch -m avc -ts recent shows a denial against the default_t label.
  4. semanage fcontext plus restorecon -Rv /srv/site fixes it.

No chmod was needed. Checking the path first, then the policy layer, solves a large share of “mystery” errors.

FAQ

What does “Permission denied” mean in Linux?

Your user or process lacks the required rights, or a layer such as SELinux, AppArmor or a mount option blocked the action.

How do I fix “Permission denied” when running a script?

Run chmod +x script.sh and try again; if it still fails, check whether the filesystem is mounted noexec.

Is chmod 777 safe?

No, because it lets any user modify the file, so use a specific owner, group or ACL instead.

Why do I get “Permission denied” even as root?

Root is still blocked by immutable flags, read-only mounts and SELinux or AppArmor rules, which you can check with lsattr, findmnt and the audit logs.

Why isn’t my new group membership working?

Group changes apply only to new login sessions, so log out and back in or run newgrp groupname.

How do I fix “Permission denied (publickey)” on SSH?

Set ~/.ssh to 700 and your private key and authorized_keys to 600, then run ssh -v to see which key is being offered.

Conclusion

Permission errors are frustrating, but they follow a clear logic. Check ownership and the full directory path, then groups and ACLs, then mount options, SELinux or AppArmor, and finally service sandboxing. Fix the layer that is actually blocking you instead of loosening everything.

That is How to Fix Permission Denied Errors in Linux on any major distro: diagnose first, change as little as possible, and keep your security tools switched on. Bookmark the diagnostic table above, because it will save you time the next time those two words appear.


Disclaimer: This guide is for general informational purposes. Commands that change permissions, ownership, mounts or security policies can affect system stability and security. Test on a non-critical system first, keep backups, and check your distribution’s official documentation for release-specific behavior.


More Linux Troubleshooting Guides

Fix common Linux problems with these practical troubleshooting tutorials.

How to Fix Linux After a Failed System Update

Troubleshoot broken packages, update errors, and Linux systems that stop working after an upgrade.

Linux File Manager Not Opening? Here’s How to Fix It

Learn how to diagnose file manager crashes, launch failures, and problems accessing files and folders.

External Monitor Not Detected on Linux? Try These Fixes

Resolve display detection issues, check graphics drivers, and troubleshoot external monitor connections.

More Linux tips and tutorials at Techrefreshing.com.

Anup Yadav

About the Author

Anup Yadav

Anup Yadav is the founder and editor of TechRefreshing, where he writes practical Linux tutorials, troubleshooting guides, distro reviews, open-source software coverage, and Linux news. His work focuses on helping everyday users understand Linux problems, find the right fixes, and make better decisions about distributions, applications, and system updates. He prefers clear explanations, useful commands, and official documentation over unnecessary technical jargon.

View all posts →

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.