Linux File Permissions Explained: chmod, chown, and umask
Read the permission string on any file, change who owns it, and understand what umask does to files you create.
Every file and directory on Linux has a permission set that controls who can read it, write to it, and execute it. Once you can read the permission string, the rest follows quickly.
Reading the permission string
Run ls -l on any file:
-rwxr-xr-- 1 alice devs 4096 Apr 28 09:14 deploy.sh
The first ten characters are the permission string:
- rwx r-x r--
ā ā ā āāā others: read only
ā ā āāā group: read and execute
ā āāā owner: read, write, execute
āāā type: - = file, d = directory, l = symlink
Each three-character block is the same: r (read), w (write), x (execute). A - means the permission is not granted.
chmod ā change permissions
Symbolic mode
chmod u+x deploy.sh # give the owner execute permission
chmod g-w config.yml # remove write from the group
chmod o= secrets.env # remove all permissions from others
chmod a+r README.md # give everyone read permission
Targets: u = owner, g = group, o = others, a = all three.
Operators: + = add, - = remove, = = set exactly (overrides existing).
Numeric (octal) mode
Each permission has a value: r=4, w=2, x=1. Add them per group.
chmod 755 deploy.sh # owner: rwx (7) | group: r-x (5) | others: r-x (5)
chmod 644 config.yml # owner: rw- (6) | group: r-- (4) | others: r-- (4)
chmod 600 secrets.env # owner: rw- (6) | group: --- (0) | others: --- (0)
chmod 700 private/ # owner: rwx (7) | group: --- (0) | others: --- (0)
755 is the standard for executables and directories that need to be traversable by everyone. 644 is standard for files that should be readable but only writable by the owner. 600 is for anything sensitive ā SSH keys, credentials, private config.
Recursive
chmod -R 755 public/
Applies to every file and subdirectory under public/. Use with care ā setting everything to 755 makes all files executable, which is rarely what you want. When you need different permissions for files and directories, use find:
find public/ -type f -exec chmod 644 {} \;
find public/ -type d -exec chmod 755 {} \;
chown ā change ownership
chown alice deploy.sh # change owner only
chown alice:devs deploy.sh # change owner and group
chown :devs deploy.sh # change group only
chown -R alice:devs /var/app # recursive
You need sudo to transfer a file to a different user. Changing the group to one you already belong to does not require it.
Special permission bits
Three extra bits sit above the standard rwxrwxrwx. They appear as a fourth octal digit or as modified characters in ls -l.
Setuid (4xxx / s on owner execute) ā the executable runs as its owner, not the user who launched it. /usr/bin/passwd uses this to let ordinary users modify /etc/shadow.
Setgid (2xxx / s on group execute) ā on a directory, new files inherit the directory's group instead of the creator's primary group. Standard practice for shared project directories where all team members need the same group ownership.
Sticky bit (1xxx / t on others execute) ā on a directory, only the file's owner can delete it even if others have write permission on the directory. /tmp uses this so users cannot delete each other's temporary files.
ls -ld /tmp
drwxrwxrwt 14 root root 4096 Apr 29 07:31 /tmp
# ^ t = sticky bit
umask ā the permission filter for new files
When you create a file or directory, the kernel starts with a base permission and subtracts the umask. The default on most Linux systems is 022.
For files, the base is 666 (no execute by default):
666 - 022 = 644 (rw-r--r--)
For directories, the base is 777:
777 - 022 = 755 (rwxr-xr-x)
Check your current umask:
umask
Change it for the session:
umask 027 # new files: 640, new directories: 750
A umask of 027 is common in environments where files should be hidden from users outside the group. Set it in ~/.bashrc or /etc/profile to apply it permanently.
Common gotchas
Script refuses to run. The execute bit is not set. chmod +x script.sh fixes it.
Permission denied when writing to a shared directory. Check ls -ld on the directory ā the group write bit (position 5 in the string) needs to be set, and you need to be a member of the owning group. groups shows your current group memberships.
SSH key ignored by sshd. Key permissions must be strict. ~/.ssh must be 700, private keys and authorized_keys must be 600. If they are too open, sshd silently skips the file and falls back to password auth. This is the most common reason for "my key doesn't work."
Ownership changes when copying files. cp creates a new file owned by you. Use rsync -a to preserve ownership, or rsync --chown=user:group to set ownership explicitly during the copy.
SysEmperor