Web Development Tutorials

Server Administration

Set File and Directory Permissions With chmod

Set file and directory permissions with chmod and you control exactly who can read, write, or execute anything on a Linux server. Permissions come in three trios — owner, group, others — and chmod sets them either as octal digits like 755 or as symbols like u+x. First, this tutorial decodes the ls -l permission string. Next, it applies the three numeric modes that cover most real work. Then it makes targeted symbolic tweaks, recurses over a directory, and hands ownership to the web user with chown. Everything below is a real run on Ubuntu 24.04.

Requirements to set file permissions with chmod:

  • Any Linux (tested on Ubuntu 24.04 LTS) or macOS terminal. chmod and chown are core utilities; only chown needs sudo.
  • A scratch directory to practice in — the examples use /tmp/permdemo, so nothing important is ever touched.

How To Set the File Permissions With chmod.

The objective is to give three files the permissions their jobs demand: a script the owner can run (755), a config file nobody else can read (600), and a web page the server may serve but not change (644).

Step 1.

First, read what is already there. Create the practice files, then list them — the first column is the permission string.

mkdir -p /tmp/permdemo/site && cd /tmp/permdemo
echo "backup"   > backup.sh
echo "secret=1" > config.ini
echo " site/index.php
ls -l backup.sh config.ini site/index.php
-rw-rw-r-- 1 ubuntu ubuntu  7 Aug  7 11:34 backup.sh
-rw-rw-r-- 1 ubuntu ubuntu  9 Aug  7 11:34 config.ini
-rw-rw-r-- 1 ubuntu ubuntu 14 Aug  7 11:34 site/index.php

Read -rw-rw-r-- in chunks of three after the file-type dash: owner rw-, group rw-, others r--. Each letter is worth a number — read 4, write 2, execute 1 — so rw- is 6 and this string is 664.

Step 2.

Next, set the three classic modes numerically. One digit per trio, owner-group-others: 755 means the owner has everything and everyone else may read and execute; 600 locks a file to its owner; 644 is the standard for content the web server serves.

chmod 755 backup.sh
chmod 600 config.ini
chmod 644 site/index.php
ls -l backup.sh config.ini site/index.php
-rwxr-xr-x 1 ubuntu ubuntu  7 Aug  7 11:34 backup.sh
-rw------- 1 ubuntu ubuntu  9 Aug  7 11:34 config.ini
-rw-r--r-- 1 ubuntu ubuntu 14 Aug  7 11:34 site/index.php

Step 3.

Then, adjust single bits symbolically when you do not want to restate the whole mode. The letters pick who (u owner, g group, o others, a all) and the operator adds or removes (+, -) a right. For example, stripping the group write bit and others’ read bit:

chmod u+x,g-w backup.sh
chmod o-r config.ini

To see any file’s mode as a number rather than a string, ask stat:

stat -c "%a %n" backup.sh config.ini site/index.php
755 backup.sh
600 config.ini
644 site/index.php

Step 4.

Now handle directories. A directory needs the execute bit just to be entered, so directories take 755 where files take 644. The -R flag applies a mode down the whole tree.

chmod -R 755 site
ls -ld site site/index.php
drwxr-xr-x 2 ubuntu ubuntu 4096 Aug  7 11:34 site
-rwxr-xr-x 1 ubuntu ubuntu   14 Aug  7 11:34 site/index.php

Notice the catch: recursion gave the file execute rights it should not have. The clean fix on a real tree is two passes — find site -type d -exec chmod 755 {} + for directories, then find site -type f -exec chmod 644 {} + for files.

Step 5.

Finally, set the owner. Web servers run as their own account, so deployed files belong to that user — here the site user is nd-web. chown user:group sets both at once, and chgrp changes just the group.

cp site/index.php app.php && chmod 644 app.php
sudo chown nd-web:nd-web app.php
ls -l app.php
-rw-r--r-- 1 nd-web nd-web 14 Aug  7 11:34 app.php

Result of setting the file permissions with chmod.

Each file now carries exactly the rights its role needs — and the same ls -l string that started as -rw-rw-r-- everywhere now reads differently per file. This is the real output from Ubuntu 24.04:

-rwxr-xr-x 1 ubuntu ubuntu  backup.sh       (755: owner runs it)
-rw------- 1 ubuntu ubuntu  config.ini      (600: owner only)
-rw-r--r-- 1 nd-web nd-web  app.php         (644: server-owned, world-readable)
drwxr-xr-x 2 ubuntu ubuntu  site            (755: enterable directory)

Set file and directory permissions with chmod: ls -l shows 755 on the script, 600 on the config, 644 on the web file, and nd-web ownership after chown

Notes on file permissions with chmod:

  • New files are born from the umask. This shell’s umask of 0002 is why every file in Step 1 started as 664 — the umask’s bits are subtracted from 666 (files) and 777 (directories).
  • Never reach for chmod 777 to fix a web error — it lets any local process rewrite your code. The real fix is almost always ownership: give the files to the server’s user, as in Step 5, and keep 644/755.
  • Only the file’s owner or root may change its permissions, and changing ownership always needs root — hence sudo on chown.
  • Wrong permissions are the classic reason a PHP file upload cannot write its target directory. Similarly, your key file must be 600 before you can connect to a remote server using SSH keys — SSH refuses a world-readable key outright.

References:

//

Featured tutorial

Leave a comment

Your email address will not be published. Required fields are marked *