Post

Linux File Permissions, Explained Simply: chmod and chown

What rwx and 755 actually mean, and how to use chmod and chown without breaking things.

Linux File Permissions, Explained Simply: chmod and chown

Sooner or later everyone hits Permission denied on a script they wrote themselves. It’s your file. Why can’t you run it?

The answer is Linux permissions. Every file and folder has a small set of rules about who can do what with it. Once you understand how those rules are written, chmod 755 and rwxr-xr-x stop looking like secret codes.

I’ll use one file throughout this post: a script called deploy.sh.

Reading permissions

Run ls -l and you’ll see something like this:

1
2
$ ls -l deploy.sh
-rw-r--r-- 1 surya developers 812 Dec 11 14:55 deploy.sh

The interesting bits are -rw-r--r--, surya and developers.

surya is the owner of the file. developers is the group it belongs to. Everyone else on the system is just called others.

Now the permission string. Ignore the first character for now (- means it’s a normal file, d would mean a directory). The other nine characters are three groups of three:

1
2
3
 -   rw-     r--     r--
     ↑       ↑       ↑
   owner   group   others

Each group of three always means the same thing, in the same order:

  • r = read (open and look at the file)
  • w = write (change the file)
  • x = execute (run it as a program)

A - means “not allowed”. So rw- means read and write, but not execute.

Put together, -rw-r--r-- says:

  • the owner (surya) can read and write
  • the group (developers) can only read
  • everyone else can only read

Nobody can run it. That’s exactly why ./deploy.sh gives Permission denied.

For folders, the letters mean something slightly different. r lets you list what’s inside, w lets you add or delete files, and x lets you go into the folder at all. A folder without x is like a locked door, even if you can read the sign on it.

Changing permissions with chmod

chmod (change mode) is how you change those letters. There are two ways to write it, and both do the same thing.

The letters way

You say who, then add or remove, then what:

  • who: u (user/owner), g (group), o (others), a (all)
  • add or remove: + to add, - to remove, = to set exactly
  • what: r, w, x

So to fix the script:

1
chmod u+x deploy.sh

“Give the owner execute.” Now ls -l shows -rwxr--r--, and ./deploy.sh works.

A few more examples:

1
2
3
4
chmod +x deploy.sh        # let everyone run it
chmod g+w deploy.sh       # let the group edit it too
chmod o-r deploy.sh       # stop others from reading it
chmod go= secrets.txt     # group and others get nothing at all

The numbers way

This is where 755 and 644 come from. Each letter has a number:

  • r = 4
  • w = 2
  • x = 1

Add up the ones you want for each group. That gives you three digits: owner, group, others.

1
2
3
4
rwx = 4 + 2 + 1 = 7
r-x = 4 + 0 + 1 = 5
r-- = 4 + 0 + 0 = 4
--- = 0

So chmod 754 deploy.sh means:

1
2
3
  7      5      4
 rwx    r-x    r--
owner  group  others

The owner can do everything, the group can read and run it, others can only read.

You’ll see the same few numbers over and over:

  • 755 for scripts, programs and folders: owner can change it, everyone can use it
  • 644 for normal files: owner can edit, everyone can read
  • 600 for private stuff like .env files or SSH keys: only you, nobody else
  • 777 means everyone can do everything. You almost never want this.

Once the numbers click, they’re faster to type than the letters. But the letters are easier to get right when you only want to change one thing.

Changing a whole folder

-R applies the change to everything inside a folder:

1
chmod -R 755 public_html/

Be careful with this one. It gives execute to every file, including images and text files that should never be “runnable”. A cleaner way is to treat folders and files separately with find:

1
2
find project -type d -exec chmod 755 {} +   # folders
find project -type f -exec chmod 644 {} +   # files

Changing the owner with chown

Sometimes the permissions are fine, but the file belongs to the wrong person. That’s where chown (change owner) comes in.

1
2
3
4
sudo chown alex deploy.sh                  # owner becomes alex
sudo chown :developers deploy.sh           # only change the group
sudo chown alex:developers deploy.sh       # change both
sudo chown -R www-data:www-data /var/www   # a whole folder

You’ll usually need sudo for this. A normal user can’t just give their files away to someone else.

This comes up a lot with web servers. If your site’s files are owned by root but the web server runs as www-data, it can’t read them, and you get errors even though the permissions look fine.

chmod or chown?

The easiest way I remember the difference:

  • chown decides who the owner and group are
  • chmod decides what the owner, group and others are allowed to do

If the right person can’t do something, check both. First “is it theirs?” (chown), then “are they allowed?” (chmod).

Mistakes I’d avoid

Using chmod 777 to make an error go away. It works, but it lets anyone on the system change or replace that file. Find out who actually needs access and give it to them instead.

Forgetting about groups. If two people need to edit the same files, put them in a shared group and give the group write access. That’s much safer than opening it up to “others”. You can check which groups you’re in with id.

Running chmod -R on the wrong folder. Especially with sudo. Double-check the path before you hit enter.

Docker volumes. Files inside a container can show up with a different owner on the host, because the user IDs don’t match. If permissions look weird in a mounted folder, this is often why.

A setup I use as a starting point

For an app folder, this is a good, safe default:

1
2
3
4
sudo chown -R appuser:appgroup /srv/app        # the app's user owns everything
find /srv/app -type d -exec chmod 755 {} +     # folders: enter and list
find /srv/app -type f -exec chmod 644 {} +     # files: readable, not runnable
chmod 600 /srv/app/.env                        # secrets: owner only

Quick cheat sheet

You want to…Command
Let yourself run a scriptchmod u+x file
Make a file private to youchmod 600 file
Normal file, readable by allchmod 644 file
Script or folder, usable by allchmod 755 file
Change the ownersudo chown user file
Change owner and groupsudo chown user:group file
Do it for a whole folderadd -R

That’s most of what you need day to day. If you want me to cover the more unusual bits next, like setuid, sticky bits or ACLs, let me know in the comments.

This post is licensed under CC BY 4.0 by the author.