Permissions

Permissions are one of the most common reasons things break on Linux servers. A script will not run. A service cannot read its config file. An application cannot write to its log directory. A cron job fails silently at 3 AM and nobody knows why. Nine times out of ten, the answer is permissions.

After this page, you should be able to:

  • Read and interpret Linux permission strings like -rwxr-xr--
  • Use chmod to change file permissions using both symbolic and numeric modes
  • Use chown to change file and directory ownership
  • Apply the permission troubleshooting pattern to diagnose and fix access issues
  • Recognize common permission requirements for real-world scenarios (SSH keys, web servers, scripts)

Why Permissions Matter

Every file and directory on a Linux system has permissions that control who can read it, who can modify it, and who can execute it. This is not academic — it is the security model that keeps a multi-user system from being chaos.

Here are real-world problems caused by incorrect permissions:

  • Script will not execute — you wrote a bash script but forgot to add execute permission. You run it and get "Permission denied."
  • Service cannot read its config — the config file is owned by your user account, but the service runs as a different user (like www-data or nginx). It cannot read the file.
  • Application cannot write logs — the log directory exists, but the application user does not have write permission to it. Logs silently fail.
  • Cron job fails silently — a scheduled task runs as root but tries to access files owned by another user, or vice versa.
  • SSH refuses to connect — your private key file has permissions that are too open. SSH will not use a key that other users can read.

When something mysteriously does not work on Linux, checking permissions should be one of the first things you do. Understanding this system will save you hours of confused debugging.

Reading Permission Strings

When you run ls -la, you see something like this at the beginning of each line:

-rwxr-xr--  1 jake  staff  2048 Jan 15 10:30 script.sh
drwxr-xr-x  3 jake  staff    96 Jan 15 09:00 projects/
-rw-r--r--  1 jake  staff   512 Jan 15 08:45 config.txt

That first column is the permission string. It looks like gibberish until you know the pattern — then it becomes instantly readable.

Breaking It Down: Character by Character

A permission string is exactly 10 characters. Here is what each position means:

- rwx r-x r--
│ │││ │││ │││
│ │││ │││ └── Others (everyone else): read only
│ │││ └── Group: read + execute
│ └── Owner: read + write + execute
└── File type: - = file, d = directory, l = symlink

The first character tells you what kind of thing it is:

  • - — regular file
  • d — directory
  • l — symbolic link

The remaining 9 characters are three groups of three, each representing permissions for a different audience:

  • Characters 2-4: Owner — the user who owns the file
  • Characters 5-7: Group — members of the file's group
  • Characters 8-10: Others — everyone else on the system

Within each group of three, the characters are always in the same order:

  • r — read (or - if not granted)
  • w — write (or - if not granted)
  • x — execute (or - if not granted)

Practice Reading Permissions

-rwxr-xr--   Owner: read, write, execute | Group: read, execute | Others: read
-rw-r--r--   Owner: read, write          | Group: read          | Others: read
-rwx------   Owner: read, write, execute | Group: nothing       | Others: nothing
drwxr-xr-x   Directory | Owner: full     | Group: read, execute | Others: read, execute

Run ls -la in your home directory and practice reading the permission strings on your own files. After a few minutes it becomes second nature.

chmod — Changing Permissions

chmod (change mode) modifies the permissions on a file or directory. There are two ways to use it: symbolic mode and numeric mode. Both do the same thing — you will use whichever feels more natural for the situation.

Symbolic Mode

Symbolic mode uses letters to add or remove specific permissions. It is intuitive for quick changes.

chmod +x script.sh       # Add execute permission for everyone
chmod -w file.txt        # Remove write permission for everyone
chmod u+x script.sh      # Add execute for the owner (u = user/owner)
chmod g+w file.txt       # Add write for the group (g = group)
chmod o-r secret.txt     # Remove read for others (o = others)
chmod u+rwx,g+rx,o+r file.txt  # Set specific permissions for each

The letters: u = user/owner, g = group, o = others, a = all (everyone). + adds a permission, - removes it.

Numeric Mode

Numeric mode uses a three-digit number where each digit represents the permissions for owner, group, and others respectively. Each permission has a numeric value:

  • Read (r) = 4
  • Write (w) = 2
  • Execute (x) = 1

You add the values together to get each digit:

7 = 4 + 2 + 1 = rwx   (read + write + execute)
6 = 4 + 2     = rw-   (read + write)
5 = 4     + 1 = r-x   (read + execute)
4 = 4         = r--   (read only)
0 =           = ---   (no permissions)

Common Permission Sets

You do not need to memorize every combination. In practice, you will use the same handful of permission sets over and over:

chmod 755 script.sh    # Owner: full | Others: read + execute
                       # Use for: executable scripts, directories

chmod 644 config.txt   # Owner: read + write | Others: read only
                       # Use for: config files, HTML files, most regular files

chmod 600 id_rsa       # Owner: read + write | Others: nothing
                       # Use for: SSH private keys, secrets, credentials

chmod 700 private/     # Owner: full | Others: nothing
                       # Use for: private scripts, personal directories
ℹ️

Memorize 755, 644, and 600

These three cover the vast majority of real-world situations. 755 for things that need to be executable. 644 for files that should be readable but not executable. 600 for files that only the owner should see. If you know these three, you can handle most permission problems.

Recursive Permissions: chmod -R

Need to change permissions on a directory and everything inside it? Use the -R flag for recursive.

chmod -R 755 /var/www/html/

Be careful with recursive chmod — it applies to every file and subdirectory. Make sure you are targeting the right directory before running this.

chown — Changing Ownership

chown (change owner) changes who owns a file or directory. Every file on Linux has an owner (a user) and a group. Sometimes the permissions are fine but the wrong user owns the file, which means the right user cannot access it.

chown jake file.txt              # Change owner to jake
chown jake:staff file.txt        # Change owner to jake and group to staff
chown :staff file.txt            # Change only the group to staff
chown -R jake:staff /var/www/    # Recursive — change everything inside

When You Need chown

  • Files created by the wrong user — you copied files as root, but the web server runs as www-data and cannot read them
  • Deployment scripts — your deployment process creates files as one user, but the application runs as another
  • Service accounts — a service like Nginx or PostgreSQL needs to own its data and config directories
  • After extracting archives — unpacking a tar file can preserve the original ownership, which might not match your system

Note: chown usually requires sudo because changing ownership of files is a privileged operation. Only root can give files to other users.

The Permission Troubleshooting Pattern

There is a consistent pattern you will follow every time something fails due to permissions. Internalize this workflow — you will use it constantly.

When something fails on Linux, check permissions FIRST

Before you start debugging code, checking network settings, or reinstalling packages — run ls -la on the file or directory in question. The answer is often right there in the permission string.

The pattern:

  1. Something fails — you get "Permission denied," a service will not start, or a script will not run
  2. Check the file — run ls -la on the file or directory to see permissions and ownership
    ls -la /path/to/the/file
  3. Identify the problem — is the owner wrong? Is the execute bit missing? Does the group not have read access?
  4. Fix it — use chmod to fix permissions or chown to fix ownership
    chmod 755 script.sh          # Fix permissions
    sudo chown appuser:appgroup config.txt  # Fix ownership
  5. Verify — run ls -la again to confirm the change, then test if the original problem is resolved

Try It — Permission Debugging

Walk through this exercise step by step on your Linux VM. You are going to create a script, break it with permissions, and fix it — the exact workflow you will follow on the job.

  1. Create a bash script. Run these two commands to create a simple script file:
    echo '#!/bin/bash' > test.sh
    echo 'echo "Hello from the script!"' >> test.sh
  2. Check the permissions. Run ls -la test.sh and read the permission string. Notice there is no x (execute) permission.
  3. Try to run it. Run ./test.sh and observe the "Permission denied" error. This is the exact error that trips up beginners.
  4. Fix it. Run chmod +x test.sh to add execute permission.
  5. Verify the fix. Run ls -la test.sh again — you should now see x in the permission string.
  6. Run it. Run ./test.sh — it works. That single missing permission was the entire problem.
  7. Change ownership to root. Run sudo chown root:root test.sh to make root the owner.
  8. See what changes. Run ls -la test.sh and notice the owner and group columns now say root.
  9. Try to edit it. Run nano test.sh and try to save a change. Depending on the permissions, you may get a warning or be unable to save. This is ownership in action — even if the permissions say writable, the owner is now root, not you.
  10. Try to delete it. Run rm test.sh. Depending on your directory permissions, you might be able to delete it or you might get "Permission denied." Note that deletion depends on the directory permissions, not the file permissions.
  11. Clean up. If rm did not work, use sudo rm test.sh to remove the file.
  12. Bonus: Try numeric permissions. Create the script again and experiment with different numeric modes:
    echo '#!/bin/bash' > test2.sh
    echo 'echo "Testing permissions"' >> test2.sh
    chmod 644 test2.sh    # Try to run it — fails (no execute)
    chmod 755 test2.sh    # Try to run it — works
    chmod 000 test2.sh    # Try to read it — fails (no permissions)
    chmod 644 test2.sh    # Restore read/write
    rm test2.sh           # Clean up

Common Permission Scenarios on the Job

Here are specific situations you will encounter in real IT work and the permissions that go with them. These are worth committing to memory.

SSH Key Permissions

SSH is extremely strict about key file permissions. If your private key is readable by anyone other than you, SSH will refuse to use it and print a warning about "unprotected private key file."

chmod 600 ~/.ssh/id_rsa           # Private key: owner read/write only
chmod 644 ~/.ssh/id_rsa.pub       # Public key: readable by everyone
chmod 700 ~/.ssh/                 # .ssh directory: owner only

This is one of the most common "why can't I SSH in?" problems. If you copy your key to a new machine and SSH does not work, check the permissions first.

Web Server Files

A web server (like Nginx or Apache) needs to read your website files but should never need to write to them. The web server process typically runs as a user like www-data.

sudo chown -R www-data:www-data /var/www/html/
chmod -R 755 /var/www/html/       # Directories: read + execute
find /var/www/html -type f -exec chmod 644 {} \;  # Files: read only

Log Directories

Application log directories need to be writable by the service user. If an application cannot write to its log directory, it may fail silently or crash.

sudo mkdir -p /var/log/myapp
sudo chown appuser:appuser /var/log/myapp
chmod 755 /var/log/myapp

Executable Scripts

Any script you want to run directly (with ./script.sh) needs execute permission. This is the most common permission issue for people new to Linux.

chmod +x deploy.sh       # Quick: add execute for everyone
chmod 755 deploy.sh      # Explicit: owner full, others read + execute

Sensitive Configuration Files

Files containing passwords, API keys, or database credentials should be locked down so only the owner (or service account) can read them.

chmod 600 /etc/myapp/secrets.conf
sudo chown appuser:appuser /etc/myapp/secrets.conf

Never leave sensitive files world-readable (644). Anyone on the system could read them. Use 600 so only the owner has access.

Checkpoint

Before moving on, make sure you can do all of the following:

  • Read a permission string like -rwxr-xr-- and explain what each part means
  • Identify the owner, group, and others sections in a permission string
  • Explain the numeric values: what does 755 mean? What about 644? And 600?
  • Use chmod +x to make a script executable
  • Use chmod with a numeric mode to set specific permissions
  • Use chown to change the owner of a file
  • Follow the troubleshooting pattern: something fails, check ls -la, identify the problem, fix with chmod or chown, verify
  • Explain why SSH keys need 600 permissions
  • Create a script, observe "Permission denied," and fix it

Permissions are one of those things that come up on every single Linux system you will ever touch. The concepts on this page will serve you for your entire career. If something does not work and you cannot figure out why — check the permissions.