Linux File Permissions and chmod Command β Complete Guide
Linux File Permissions and chmod Command β Complete Guide
Master Linux file permissions with this comprehensive chmod guide. Learn octal notation, symbolic mode, and common permission patterns with examples.
Introduction
Every file and directory on a Linux system has a set of permissions that determines who can read, write, or execute it. Understanding these permissions is fundamental to working with Linux, whether you are managing a web server, deploying applications, or simply organizing files on your development machine.
The chmod command is the primary tool for modifying these permissions. Despite its apparent simplicity, chmod has enough depth that even experienced developers occasionally reach for a reference. This guide covers everything you need to know about Linux file permissions and the chmod command, from basic concepts to advanced special permissions.
Understanding Linux File Permissions
Linux file permissions are built around three types of access and three categories of users.
The Three Permission Types
- Read (r): View the contents of a file, or list the contents of a directory.
- Write (w): Modify or delete a file, or add and remove files within a directory.
- Execute (x): Run a file as a program or script, or enter a directory with
cd.
The Three User Categories
- Owner (u): The user who owns the file. By default, this is the user who created it.
- Group (g): The group assigned to the file. All users in this group share the group permissions.
- Others (o): Everyone else on the system who is not the owner and not in the file's group.
Every file on a Linux system has exactly one owner, belongs to exactly one group, and has a defined set of permissions for each of these three categories.
How to Read Permission Strings
When you run ls -l in a terminal, you see output like this:
ls -l
-rwxr-xr-- 1 alice developers 4096 Mar 22 10:30 deploy.sh
drwxr-x--- 2 alice developers 4096 Mar 22 10:30 config/
The first column is the permission string. It is ten characters long and breaks down as follows:
d rwx r-x r--
| | | |
| | | +-- Others permissions (read only)
| | +------ Group permissions (read + execute)
| +---------- Owner permissions (read + write + execute)
+------------- File type (d = directory, - = regular file, l = symlink)
Each position is either the permission letter or a dash (-) indicating that permission is not granted. Here are several examples:
| Permission String | Meaning |
|---|---|
-rw-r--r-- | Owner can read/write. Group and others can only read. |
-rwxr-xr-x | Owner has full access. Group and others can read and execute. |
drwx------ | Directory. Only the owner can read, write, and enter it. |
-rw------- | Only the owner can read and write. No access for anyone else. |
-rwxrwxrwx | Full access for everyone. Generally a security risk. |
Octal (Numeric) Notation
Octal notation represents permissions as a three-digit number, where each digit corresponds to the owner, group, and others respectively. Each digit is the sum of permission values:
| Value | Permission |
|---|---|
| 4 | Read (r) |
| 2 | Write (w) |
| 1 | Execute (x) |
| 0 | No permission |
You add these values together for each user category. For example:
- 7 = 4 + 2 + 1 = read + write + execute (rwx)
- 6 = 4 + 2 = read + write (rw-)
- 5 = 4 + 1 = read + execute (r-x)
- 4 = 4 = read only (r--)
- 0 = no permissions (---)
So when you see chmod 755, it means:
7 = rwx (owner: read + write + execute)
5 = r-x (group: read + execute)
5 = r-x (others: read + execute)
Here is a quick reference for all possible digit values:
0 = --- (no permissions)
1 = --x (execute only)
2 = -w- (write only)
3 = -wx (write + execute)
4 = r-- (read only)
5 = r-x (read + execute)
6 = rw- (read + write)
7 = rwx (read + write + execute)
If you need to quickly convert between permission strings and octal values, use our chmod Calculator for instant results.
Symbolic Notation
Symbolic notation uses letters and operators to modify permissions. It is often more intuitive for making targeted changes because you do not need to specify the entire permission set.
The Syntax
chmod [who][operator][permission] file
Who:
u-- owner (user)g-- groupo-- othersa-- all (owner + group + others)
Operator:
+-- add permission--- remove permission=-- set exact permission
Permission:
r-- readw-- writex-- execute
Symbolic Mode Examples
# Add execute permission for the owner
chmod u+x script.sh
# Remove write permission from group and others
chmod go-w config.yml
# Set read-only for everyone
chmod a=r readme.txt
# Add read and execute for group
chmod g+rx shared-tool
# Remove all permissions for others
chmod o= private.key
# Add execute for everyone, remove write for others
chmod a+x,o-w deploy.sh
# Set owner to rwx, group to rx, others to nothing
chmod u=rwx,g=rx,o= project-dir
Symbolic notation is particularly useful when you only want to change one aspect of the permissions without affecting the rest. For instance, chmod u+x script.sh adds execute permission for the owner without touching any other permissions.
Common chmod Patterns
Certain permission patterns appear repeatedly in real-world Linux administration. Here are the most important ones and when to use them.
644 -- Standard Files
chmod 644 index.html
# Owner: read + write | Group: read | Others: read
This is the default for most regular files. The owner can edit the file, and everyone else can read it. Use this for HTML files, configuration files that are not sensitive, and general documents.
755 -- Executable Files and Directories
chmod 755 deploy.sh
chmod 755 /var/www/html
# Owner: full access | Group: read + execute | Others: read + execute
The standard permission for scripts, binaries, and directories that need to be accessible. The owner has full control, while others can read and execute (or traverse, in the case of directories) but cannot modify.
700 -- Private Directories
chmod 700 ~/.ssh
# Owner: full access | Group: none | Others: none
Only the owner can access the file or directory. Essential for sensitive directories like ~/.ssh or private configuration directories.
600 -- Private Files
chmod 600 ~/.ssh/id_rsa
chmod 600 .env
# Owner: read + write | Group: none | Others: none
Only the owner can read and write the file. No one else has any access. Required for SSH private keys, environment files with secrets, and any file containing credentials.
444 -- Read-Only for Everyone
chmod 444 LICENSE
# Owner: read | Group: read | Others: read
No one can modify the file, including the owner (without changing permissions first). Useful for files that should never be accidentally edited, like license files or locked configuration.
777 -- Full Access for Everyone
chmod 777 /tmp/shared-workspace
# Owner: full | Group: full | Others: full
Every user can read, write, and execute. Avoid this in production. It is a significant security risk because any user or process on the system can modify or delete the file. Only use it in isolated development or temporary debugging scenarios.
Quick Reference Table
| Octal | String | Typical Use |
|---|---|---|
644 | -rw-r--r-- | Regular files (HTML, CSS, images) |
755 | -rwxr-xr-x | Scripts, binaries, web directories |
700 | -rwx------ | Private directories (~/.ssh) |
600 | -rw------- | Private keys, .env files, credentials |
444 | -r--r--r-- | Read-only files, licenses |
664 | -rw-rw-r-- | Group-collaborative files |
775 | -rwxrwxr-x | Group-collaborative directories |
777 | -rwxrwxrwx | Avoid in production |
chmod Command Syntax and Options
The full syntax of chmod is:
chmod [options] mode file...
Key Options
# Apply permissions recursively to directories and their contents
chmod -R 755 /var/www/html
# Show verbose output for each file changed
chmod -v 644 *.html
# Show output only when a change is made
chmod -c u+x scripts/*.sh
# Suppress error messages
chmod -f 600 missing-file
# Use a reference file to copy its permissions
chmod --reference=source.conf target.conf
Practical Examples
# Make a script executable
chmod +x backup.sh
# Secure an SSH directory and its contents
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 644 ~/.ssh/authorized_keys
# Set web server file permissions
chmod -R 644 /var/www/html/*.html
chmod -R 755 /var/www/html/cgi-bin/
# Restrict a configuration file
chmod 600 /etc/myapp/database.yml
# Make all shell scripts in a directory executable
chmod u+x scripts/*.sh
# Remove write access from a production config
chmod a-w /etc/nginx/nginx.conf
Combining with find for Granular Control
A common pattern is to set different permissions for files and directories within the same tree:
# Set directories to 755 and files to 644 recursively
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
# Make only shell scripts executable
find /opt/scripts -name "*.sh" -exec chmod u+x {} \;
# Remove world-readable permissions from all config files
find /etc/myapp -type f -exec chmod o-r {} \;
This approach is more precise than chmod -R because it lets you differentiate between files and directories, which often require different permission sets.
Special Permissions
Beyond the standard read, write, and execute bits, Linux supports three special permission types. These are represented as a fourth octal digit prepended to the standard three.
Setuid (4)
When set on an executable, the file runs with the permissions of the file's owner rather than the user executing it.
chmod 4755 /usr/bin/special-tool
chmod u+s /usr/bin/special-tool
The classic example is the passwd command. It needs to modify /etc/shadow, which is owned by root. The setuid bit allows any user to run passwd with root-level file access for that specific purpose.
In ls -l output, a setuid file shows an s in place of the owner's execute bit:
-rwsr-xr-x 1 root root 63960 Feb 10 12:00 /usr/bin/passwd
Setgid (2)
When applied to a directory, new files created within it inherit the directory's group rather than the creating user's primary group. On executables, it works like setuid but for group membership.
chmod 2775 /opt/team-project
chmod g+s /opt/team-project
This is invaluable for shared project directories. Without setgid, every file a team member creates would belong to their personal group, making collaboration difficult.
drwxrwsr-x 2 root developers 4096 Mar 22 10:30 /opt/team-project
Notice the s in the group execute position.
Sticky Bit (1)
When set on a directory, only the file's owner (or root) can delete or rename files within it, even if other users have write access to the directory.
chmod 1777 /tmp
chmod +t /tmp
The /tmp directory is the most common example. Everyone can create files in /tmp, but users cannot delete each other's files. In ls -l output, the sticky bit appears as a t in the others' execute position:
drwxrwxrwt 15 root root 4096 Mar 22 10:30 /tmp
Special Permissions Summary
| Permission | Octal | Symbol | Effect on File | Effect on Directory |
|---|---|---|---|---|
| Setuid | 4000 | u+s | Runs as file owner | No standard effect |
| Setgid | 2000 | g+s | Runs as file group | New files inherit group |
| Sticky Bit | 1000 | +t | No standard effect | Only owner can delete files |
Best Practices for Security
Following a few principles will keep your systems secure while remaining practical for day-to-day work.
Apply the Principle of Least Privilege
Grant only the minimum permissions required for a task. If a file only needs to be read, do not make it writable. If a script only needs to be run by the owner, do not grant execute to the group or others.
# Good: minimal permissions
chmod 600 .env
chmod 700 ~/.ssh
# Bad: overly permissive
chmod 777 .env
chmod 755 ~/.ssh
Never Use 777 in Production
There is almost never a legitimate reason to use chmod 777 on a production system. If something seems to require it, the underlying issue is usually a misconfigured user, group, or ownership rather than a permissions problem. Use chown or chgrp to fix ownership before loosening permissions.
Secure Sensitive Files Immediately
SSH keys, API tokens, environment files, and database credentials should always be 600 or 640 at most. Many tools, including OpenSSH, will refuse to work if key files have overly permissive settings.
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_ed25519
chmod 600 .env
chmod 600 /etc/myapp/secrets.yml
Use Groups for Collaboration
Instead of widening permissions for "others," create a dedicated group, add the relevant users, and use group permissions. Combine this with the setgid bit on shared directories so new files automatically inherit the correct group.
# Create a shared directory with proper group permissions
sudo groupadd webteam
sudo usermod -aG webteam alice
sudo usermod -aG webteam bob
sudo mkdir /var/www/project
sudo chown root:webteam /var/www/project
sudo chmod 2775 /var/www/project
Audit Permissions Regularly
On production servers, periodically check for files with dangerous permissions:
# Find all world-writable files
find / -type f -perm -o+w 2>/dev/null
# Find all setuid files (potential privilege escalation vectors)
find / -type f -perm -4000 2>/dev/null
# Find files with no owner (orphaned files)
find / -nouser -o -nogroup 2>/dev/null
Set a Secure umask
The umask defines the default permissions for newly created files and directories. A umask of 022 results in files with 644 and directories with 755. A more restrictive umask of 027 gives files 640 and directories 750, preventing "others" from accessing new files by default.
# Check current umask
umask
# Set a restrictive umask for the session
umask 027
# Make it permanent by adding to ~/.bashrc or ~/.zshrc
echo "umask 027" >> ~/.bashrc
chmod vs. chown vs. chgrp
These three commands are related but serve distinct purposes:
| Command | Purpose | Example |
|---|---|---|
chmod | Change file permissions | chmod 755 script.sh |
chown | Change file owner (and optionally group) | chown alice:devs file.txt |
chgrp | Change file group | chgrp webteam index.html |
When troubleshooting access issues, start by checking both ownership (ls -l) and permissions. Often the fix is changing ownership with chown rather than loosening permissions with chmod.
Using the chmod Calculator
Manually converting between symbolic and octal notation is straightforward once you have practiced, but it can be tedious when you are setting up a new server or reviewing complex permission sets. Use our chmod Calculator to visually toggle permissions and instantly see the corresponding octal value, symbolic notation, and the resulting chmod command. It is especially useful for verifying special permissions like setuid, setgid, and the sticky bit.
Conclusion
Linux file permissions are one of the foundational pillars of system security. The chmod command gives you precise control over who can access, modify, and execute every file and directory on your system. By understanding octal and symbolic notation, applying the principle of least privilege, and using groups effectively, you can maintain a secure environment without sacrificing usability.
Remember the key rules: keep sensitive files restricted to 600 or 700, use 755 for executables and public directories, avoid 777 entirely in production, and audit your permissions regularly. With these practices in place, your Linux systems will be both functional and secure.