Linux File Permissions Explained: chmod, chown & Octal Notation
How to understand and fix Linux file permissions without running risky shortcuts like chmod 777. Explains read, write, and execute rights, octal numbers (755 vs 644), and how to use chown properly.
Encountering a stubborn "EACCES: permission denied" message inside a terminal window frequently tempts junior administrators to run chmod -R 777 to force their code to execute. While making an entire tree world-readable and world-writable eliminates the immediate error, it exposes the operating system to severe vulnerabilities. A compromised background daemon or unprivileged user account can overwrite configuration files, inject backdoors into binaries, or wipe databases. Configuring POSIX permissions correctly preserves both uptime and security posture.
Quick Reference Summary
Use 644 (-rw-r--r--) for regular application files and web assets. Use 755 (drwxr-xr-x) for executable binaries and directories. Use 600 (-rw-------) for sensitive credentials like SSH private keys and .env files. Use chown user:group filename to assign ownership, and never grant world-writable 777 permissions in production environments.
Understanding the rwx Permission Matrix
When you execute the command ls -la inside any Linux directory, the terminal prints a ten-character file mode string preceding every file or folder name.
Consider the string -rwxr-xr--:
Position 1 (Node Type): The initial character identifies filesystem object type. A hyphen (-) denotes a standard regular file; d represents a directory; l indicates a symbolic link pointing elsewhere; c denotes a character device; and s signifies a local Unix domain socket.
Positions 2 through 4 (Owner / User Permissions): These three slots govern what actions the individual user account that owns the file can perform. The triplet rwx indicates read, write, and execute capabilities.
Positions 5 through 7 (Group Permissions): These three slots specify access rights for any user belonging to the file assigned group. The triplet r-x indicates group members can read and execute, but cannot modify the file.
Positions 8 through 10 (Others / World Permissions): These final slots define permissions for every other user account on the operating system. The triplet r-- means unprivileged third-party accounts can only view file contents.
Linux file permissions represent three-bit binary numbers. Each permission flag corresponds to a specific base-2 bit:
Permission Right
Symbol
Binary Representation
Octal Value
Functional Meaning on Files vs Directories
Read
r
100
4
Files: View contents. Directories: List directory contents (run ls).
Write
w
010
2
Files: Save changes or truncate. Directories: Create, rename, or delete files inside.
Execute
x
001
1
Files: Launch as executable script/binary. Directories: Enter/traverse into folder (run cd).
No Rights
-
000
0
Access explicitly denied for this scope.
To calculate a target octal permission number, simply add the numerical values together for each category. For example, read (4) plus write (2) equals 6. Read (4) plus execute (1) equals 5. Read (4) plus write (2) plus execute (1) equals 7. A permission string of 755 corresponds to Owner=7, Group=5, and Others=5.
Direct command line file modification configures read, write, and execute bits.
Standard Production Permission Presets
Rather than guessing arbitrary numbers, adhere to these four established production presets used across cloud environments:
Static web server assets (HTML, CSS, JavaScript, images), source code files, Nginx/Caddy configuration files
700
drwx------
User personal SSH directories (~/.ssh), root backup folders, private administrative staging directories
755
drwxr-xr-x
Web root directories (/var/www/html), system binaries (/usr/local/bin), custom administrative shell scripts
Notice that files never require execute permissions unless they are compiled binaries or scripts containing a proper shebang line (such as #!/usr/bin/env bash).
Modifying Access with the chmod Command
The chmod (change mode) utility modifies permission flags using either octal numbers or symbolic syntax:
Octal Mode Assignment
Octal mode sets all three permission scopes (owner, group, other) explicitly in a single command:
# Lock down an SSH key so OpenSSH client allows authentication
chmod 600 ~/.ssh/id_ed25519
Restricting private key permissions to 600 is an absolute requirement when connecting to remote cloud servers across AWS EC2 instance types, where SSH daemons automatically reject overly permissive key files.
# Set public web server permissions on an HTML document
chmod 644 /var/www/html/index.html
Symbolic Mode Modification
Symbolic notation lets you add or subtract specific permissions without altering existing bits. Syntax follows [who][operator][permission], where who is u (user), g (group), o (others), or a (all); operator is + (add), - (remove), or = (set exactly):
# Add execute permission for the file owner only
chmod u+x run-deploy.sh
# Remove write permissions for both group and world
chmod go-w application.conf
# Grant read and execute to everyone
chmod a+rx /usr/local/bin/custom-cli
Recursive Fixes for Directories vs Files
Running chmod -R 755 /var/www/html is an unsafe anti-pattern because it marks every single text file, image, and style sheet as an executable binary. The proper method separates folders from files via shell commands:
# Recursively set directories to 755 so daemons can traverse them
find /var/www/html -type d -exec chmod 755 {} +
# Recursively set regular files to 644 so daemons can read them safely
find /var/www/html -type f -exec chmod 644 {} +
Managing Ownership and Groups with chown and chgrp
Permissions are meaningless if a file belongs to the wrong user account. If Nginx runs as service user www-data, but your web files are owned by root:root with permissions 600, Nginx will return HTTP 403 Forbidden errors.
The chown (change owner) command manages ownership associations:
# Assign both user and group ownership simultaneously
sudo chown -R www-data:www-data /var/www/html
# Change owner only, leaving group untouched
sudo chown deployer /opt/apps/backend-api
# Change group ownership only (alternative to chgrp)
sudo chown :developers /opt/apps/backend-api
Always use caution when running chown -R as the root superuser. Accidentally running chown -R user / will brick your operating system by stripping root ownership from critical PAM authentication files and sudoer configurations.
Group ownership settings isolate system files from standard user accounts.
Understanding umask and Default Creation Modes
Whenever you generate a new file via touch or create a directory via mkdir, the Linux kernel determines its initial permissions by applying the system umask (user file creation mask).
The kernel starts with a theoretical base mode: 666 for files (read and write, never execute by default) and 777 for directories. It then subtracts the active umask value:
If your current umask is 022: New files receive 666 - 022 = 644 (Owner: rw, Group: r, Other: r). New folders receive 777 - 022 = 755.
If your umask is 027: New files receive 666 - 027 = 640 (Owner: rw, Group: r, Other: none). Others are denied all access.
If your umask is 077: New files receive 600 and directories receive 700, creating completely private environments.
Check your current shell mask by typing umask. You can set persistent defaults inside /etc/profile or ~/.bashrc by adding the directive umask 022.
Special Permissions: SUID, SGID, and the Sticky Bit
Beyond standard read, write, and execute flags, Linux includes three specialized permission bits:
Special Mode
Octal Prefix
Symbolic Character
Behavioral Impact
SetUID (SUID)
4000
s in owner execute slot
Executes the binary with the permissions of the file owner (usually root), not the calling user. Example: /usr/bin/passwd.
SetGID (SGID)
2000
s in group execute slot
On directories, newly created files automatically inherit the directory group rather than the creator primary group. Ideal for team folders.
Sticky Bit
1000
t in others execute slot
On shared directories (like /tmp), users can create files, but only the file creator or root can delete or rename them.
To enable group inheritance on a collaborative engineering directory, apply the SGID bit: chmod 2775 /opt/shared-repo. Any files created by individual engineers inside that folder will instantly belong to the parent group.
Diagnostic Playbook for Permission Denied Errors
When your application logs throw EACCES or web servers return 403 Forbidden, follow this systematic diagnostic flow:
1. Check Parent Directory Traverse Rights
Even if a file is set to 644 or 777, if any parent folder in the path (e.g., /home/deployer/project) lacks the execute (x) bit for the executing user, the Linux kernel cannot enter the directory to access the target file. Test directory path traversal using namei -l /path/to/target/file to inspect permission bits on every ancestor directory.
2. Inspect Extended Attributes and the Immutable Flag
If even the root user cannot modify or delete a file, someone may have set the immutable filesystem flag. Run lsattr filename. If you see the letter i, clear the immutable bit using:
sudo chattr -i filename
3. Check SELinux or AppArmor Security Contexts
On distributions like RHEL, CentOS, AlmaLinux, or Ubuntu, mandatory access control systems can block file operations despite valid POSIX permissions. Check audit logs with sudo ausearch -m avc -ts recent or temporarily check SELinux mode with getenforce. Restore default file contexts using restorecon -Rv /var/www/html. These permission models are equally critical when configuring volume mounts in Docker container architecture, where host UID and GID mapping issues frequently trigger permission denied errors.
Frequently Asked Questions
chmod 755 grants the file owner read, write, and execute permissions (7), while group and other users get read and execute permissions (5). It is standard for executable scripts and directories. chmod 644 gives the owner read and write (6), while everyone else only gets read (4). It is standard for regular non-executable files like HTML, configuration files, and images.
Evan Mitchell• Cloud Infrastructure Specialist & Systems Administrator3+ Years Industry Experience
Systems administrator with 3+ years managing enterprise Linux servers, AWS EC2 instances, and Docker containers. Evan focuses on practical bash scripting and secure network configurations.