Linux file permissions explained
Permissions are the first line of defense on any Linux system. Every file and directory has an owner, a group, and a set of permissions that control who can read, write, or execute it. Getting this wrong means either locking yourself out or letting anyone poke around your stuff.
The basics
Run ls -l and you’ll see something like this:
-rw-r--r-- 1 upi developers 4096 Mar 12 10:30 config.yaml
That first column is the permission string. Break it down:
-— file type (-for file,dfor directory,lfor symlink)rw-— owner permissions (read, write, no execute)r--— group permissions (read only)r--— everyone else (read only)
Each position is a bit: read (4), write (2), execute (1). Add them up to get the numeric mode.
chmod: changing permissions
Numeric mode is the shorthand most people use:
chmod 644 config.yaml # rw-r--r--
chmod 755 deploy.sh # rwxr-xr-x
chmod 600 id_rsa # rw-------
The three digits map to owner, group, and others. So 755 means the owner can read/write/execute (7), and everyone else can read/execute (5).
Symbolic mode is more explicit:
chmod u+x deploy.sh # add execute for owner
chmod go-w config.yaml # remove write for group and others
chmod a+r readme.txt # add read for everyone
Use whichever you find clearer. I usually use numeric for setting exact modes and symbolic for tweaking one bit.
Directories need execute
A common gotcha: on a directory, execute permission means “can enter this directory.” Without it, you can’t cd into it or access files inside, even if you know the filenames.
chmod 755 /home/upi/projects # must have +x to traverse
Read without execute on a directory lets you list filenames but not access them. Execute without read lets you access files if you know their names but not list the directory.
chown and chgrp
chown changes file ownership. chgrp changes the group.
chown upi:developers config.yaml
chown -R upi:developers /opt/app/ # recursive
chgrp developers /opt/app/logs/
Only root can change file ownership. Any user can change the group of files they own, but only to groups they belong to.
The sticky bit
On shared directories like /tmp, you’ll see a t at the end:
drwxrwxrwt 10 root root 4096 Mar 12 10:30 /tmp
The sticky bit means users can only delete their own files in that directory, even if the directory is world-writable. Set it with:
chmod +t /shared/uploads
# or numerically: chmod 1777 /shared/uploads
setuid and setgid
setuid (4) makes a file execute as its owner. setgid (2) makes it execute as the group, or on a directory, makes new files inherit the directory’s group.
chmod 4755 /usr/bin/passwd # setuid — runs as root
chmod 2775 /opt/team/shared/ # setgid — new files get the team group
The passwd command needs setuid because it has to write to /etc/shadow, which only root can access. This is one of the few legitimate uses of setuid. Be cautious with it otherwise.
umask: default permissions
New files get their permissions from the umask. The default umask is usually 022, which means files are created with 644 (666 - 022) and directories with 755 (777 - 022).
Check your current umask:
umask
Set it for the current session:
umask 027 # files: 640, directories: 750
For a shared system where you want stricter defaults, put umask 027 in /etc/profile or ~/.bashrc.
Common mistakes
Setting 777 on everything. It fixes permission errors fast because it gives everyone full access. It also means any user on the system can read, modify, or delete the files. Don’t do this. Figure out who needs access and grant it specifically.
Forgetting -R on recursive operations. chown upi /opt/app changes the top directory but not the files inside. Use -R when you mean the whole tree.
Confusing file and directory execute. chmod 644 on a directory means nobody can enter it. Directories almost always need execute.
Remarks
Permissions are simple once the model clicks: owner/group/others, read/write/execute. The numeric shorthand becomes second nature after a few uses. Start restrictive (600 for private files, 755 for scripts) and open up only what you need. When something says “Permission denied,” ls -l tells you why.
Related Posts
Vim survival guide for Linux admins
The minimum vim knowledge you need to survive on a Linux server. Editing config files without wanting to throw your keyboard.
Linux memory management: free, vmstat, and /proc
Understanding how Linux uses memory. Reading free correctly, using vmstat, and what /proc/meminfo actually tells you.
tmux: terminal multiplexing made simple
Using tmux to manage terminal sessions. Panes, windows, and why your SSH sessions should survive disconnects.