Understanding File Permissions
Every file and folder on a Linux server carries a small set of rules that decide who can read it, change it, or run it. These rules are called file permissions, and they are one of the most important security features in Linux. If you run a web server, a database, or any service on Ubuntu, getting permissions right is what stops one compromised account from reading or breaking everything else. This page teaches you how to read permissions confidently — the next page covers how to change them.
Why permissions matter
Linux is a multi-user system, meaning many people (and many programs) can use the same machine at the same time. On a real Ubuntu server you will have your own login, a root (administrator) account, and several service accounts — special non-human users like www-data (the user that runs the Nginx web server) or postgres (the user that runs the PostgreSQL database).
Permissions are the wall between all of them. They answer questions like: Can the web server read my SSL private key? Can a normal user delete the system logs? If you understand permissions, you can lock things down properly. If you ignore them, you leave doors open.
The three identities
Every permission is granted to one of three identities:
| Identity | Short name | Who it is |
|---|---|---|
| User | u | The single owner of the file — usually the person or service that created it. |
| Group | g | A named group of users. Everyone in the group shares this set of permissions. |
| Others | o | Everyone else on the system — any user who is not the owner and not in the group. |
A group is just a label that bundles users together. For example, you might add several developers to a developers group so they can all edit the same project folder without each needing to be the owner.
The three permission types
For each identity, Linux tracks three separate permissions, written as the letters r, w, x:
| Letter | Name | On a file | On a directory (folder) |
|---|---|---|---|
r | read | View the file’s contents. | List the names inside the folder. |
w | write | Change or delete the file’s contents. | Create, rename, or delete files inside. |
x | execute | Run the file as a program or script. | Enter the folder (use cd into it). |
The meaning of
xis the part beginners forget. On a file it means “this can be run.” On a directory it means “you are allowed to go into it.” A folder you can read but not execute lets you see file names but not actually open them.
Reading the permission string
The command ls -l (the -l means “long format”) shows permissions for every item in a folder. Try it on your home directory.
ls -l /var/www/html
Output:
total 12
-rw-r--r-- 1 www-data www-data 612 Jun 14 09:21 index.html
drwxr-xr-x 2 www-data www-data 4096 Jun 14 09:20 assets
-rwx------ 1 deploy deploy 248 Jun 13 17:55 deploy.sh
Look at the first column, for example -rw-r--r--. It is 10 characters broken into four parts:
- rw- r-- r--
| | | |
| | | others (everyone else)
| | group
| user (owner)
file type
- Character 1 is the file type:
-for a normal file,dfor a directory,lfor a symbolic link (a shortcut to another file). - Characters 2-4 are the user/owner permissions.
- Characters 5-7 are the group permissions.
- Characters 8-10 are the others permissions.
A letter means the permission is granted; a dash - means it is denied. So -rw-r--r-- reads as: it is a file; the owner can read and write; the group can read; others can read.
The two names after the number (www-data www-data) are the owner and the group. So index.html is owned by user www-data and group www-data.
Worked examples
| String | Type | Meaning |
|---|---|---|
-rw-r--r-- | file | Owner reads/writes; group and others read only. Typical for documents and web pages. |
-rwxr-xr-x | file | Owner has full control; group and others can read and run it. Typical for programs. |
drwxr-xr-x | directory | Owner full control; everyone can enter and list it. Typical for normal folders. |
-rwx------ | file | Only the owner can do anything. Everyone else is fully locked out. Use for secrets. |
-rw------- | file | Only the owner reads and writes. Correct for an SSH key or password file. |
Octal (numeric) notation
Typing rwx letters works, but Linux also lets you describe permissions with numbers. This is called octal notation (base-8), and you will see it everywhere — in documentation, scripts, and the chmod command.
The trick: each permission has a value, and you add them up for each identity.
| Permission | Value |
|---|---|
r (read) | 4 |
w (write) | 2 |
x (execute) | 1 |
- (none) | 0 |
You get one digit per identity, in order user, group, others. So:
rwx= 4 + 2 + 1 = 7rw-= 4 + 2 + 0 = 6r-x= 4 + 0 + 1 = 5r--= 4 + 0 + 0 = 4
Putting three digits together describes the whole file:
| Octal | String | Common use |
|---|---|---|
755 | rwxr-xr-x | Directories and executable scripts everyone may run. |
644 | rw-r--r-- | Regular files like HTML, configs, images. |
600 | rw------- | Private files — SSH keys, .env secrets. |
700 | rwx------ | Private folders or scripts only the owner uses. |
775 | rwxrwxr-x | Shared team folder where a group can write. |
Avoid
777(rwxrwxrwx). It lets anyone read, change, and run the file. Tutorials suggest it as a quick “fix,” but on a server it is a serious security hole — it means a hacked web process can rewrite your files. Find the correct owner instead.
Checking permissions precisely
The stat command shows both the string and the octal number for any file, so you never have to convert by hand.
stat -c "%A %a %n" /var/www/html/index.html
Output:
-rw-r--r-- 644 /var/www/html/index.html
Here %A prints the rwx string, %a prints the octal number, and %n prints the file name.
When to use which
- Use the rwx letter view (
ls -l,stat -c %A) when you are reading and understanding permissions — it is easier for humans. - Use octal numbers (
644,755) when you are setting permissions in commands and scripts — it is precise and unambiguous. - Keep secrets at
600and private folders at700. Keep public web files at644and folders at755. These four cover almost every real situation.
Best practices
- Read before you write. Always run
ls -lorstatto see current permissions before changing anything. - Give the least access needed. Start strict (
600/700) and only open up if something actually needs it. - Never use
777on a server. If a service can’t access a file, fix the owner, not by making it world-writable. - Protect secrets at
600. SSH keys, TLS private keys, and.envfiles must not be readable by group or others — most tools will even refuse to use a key that is too open. - Use groups for teams. Put collaborators in a shared group and use
775/664rather than handing out ownership. - Remember
xon directories. A folder needs execute permission to be entered, even if its files are readable.