chmod and chown are the bread and butter of managing file access on Linux, but get them wrong and you’ll find yourself locked out of your own system or, worse, exposing sensitive data. The core issue isn’t just about setting permissions; it’s about understanding the intent behind them and how they interact with the Linux security model.

Let’s see chmod in action. Imagine you have a script, deploy.sh, that needs to be executable by the owner and readable by everyone else.

# Initial state
ls -l deploy.sh
-rw-r--r-- 1 user user 1234 Oct 26 10:00 deploy.sh

# Make it executable by the owner
chmod u+x deploy.sh

# Verify
ls -l deploy.sh
-rwxr--r-- 1 user user 1234 Oct 26 10:00 deploy.sh

Now, let’s say you have a directory, /var/www/html, that should be owned by the web server user (www-data) and group, and the web server process needs to write to it.

# Initial state
ls -ld /var/www/html
drwxr-xr-x 2 root root 4096 Oct 26 09:30 /var/www/html

# Change ownership to www-data user and group
sudo chown www-data:www-data /var/www/html

# Verify
ls -ld /var/www/html
drwxr-xr-x 2 www-data www-data 4096 Oct 26 09:30 /var/www/html

The mental model for chmod revolves around three entities: the owner (u), the group (g), and others (o). For each, you can grant or deny three permissions: read ®, write (w), and execute (x). These are often represented numerically: r=4, w=2, x=1. Summing these gives you the octal representation: rwx=7, rw-=6, r-x=5, r--=4, -wx=3, -w-=2, --x=1, ---=0.

So, chmod 755 deploy.sh means: owner gets rwx (7), group gets r-x (5), and others get r-x (5). This is common for scripts and directories. chmod 644 config.conf means: owner gets rw- (6), group gets r-- (4), and others get r-- (4). This is typical for configuration files.

chown is simpler: it changes the user owner and optionally the group owner of a file or directory. chown user:group file sets both. chown user file sets only the user owner. chown :group file sets only the group owner.

The real power comes when you combine these with the -R (recursive) flag for directories. chmod -R 755 /var/www/html will set the execute bit on all files and directories within /var/www/html for owner, group, and others. Be very careful with this; you usually don’t want to execute arbitrary files as root. A more common scenario is changing ownership recursively: sudo chown -R www-data:www-data /var/www/html.

The most surprising thing about chmod and chown is how often the execute bit (x) is misunderstood or misused. For directories, the execute bit doesn’t mean you can run the directory itself (you can’t). Instead, it means you can enter the directory (e.g., cd into it) and access its contents. Without the execute bit on a directory, even if you have read permissions, you won’t be able to list the files within it or cd into it. This is why 755 is so common for directories: owner can do anything, group and others can enter and list contents.

When you encounter a "Permission denied" error, it’s almost always one of these:

  1. You’re trying to read a file or list a directory where you don’t have r permission.
  2. You’re trying to write to a file or create/delete files in a directory where you don’t have w permission.
  3. You’re trying to cd into a directory or execute a file where you don’t have x permission.

If you’re debugging chmod issues, the first step is always ls -l or ls -ld to see the current permissions and ownership. Then, compare that to what you expect based on who you are (check whoami) and what you’re trying to do.

The next problem you’ll run into is understanding the setuid and setgid bits, which dramatically change how permissions are inherited and executed.

Want structured learning?

Take the full Linux & Systems Programming course →