All articles
39 articles · updated weekly See our Tools
All articles
Tutorials

Linux for Beginners: Directories, Users, and Permissions

Linux filesystem hierarchy, users, groups, and rwx permissions explained with real commands — no hand-waving, no memorization required.

COVER · Tutorials

You just got SSH access to a server and the first ls -la returns a column of letters and numbers that looks like morse code. Or you're trying to run a script and the terminal throws Permission denied with no further explanation. Linux permissions have that reputation — intimidating at first glance. But the logic behind them is consistent and, once you see it, obvious.

This post covers what you actually need: directory structure, users and groups, and the rwx permission model — with the commands you'll use in real life.


The Filesystem Hierarchy Standard — and why it matters

On Linux, everything is a file. Devices, processes, network connections — all exposed as files. And all of them live in a single directory tree, with / (root) at the top. There's no C:\ or D:\ — there are partitions and devices mounted as subdirectories within that tree.

The Filesystem Hierarchy Standard (FHS) defines where each type of thing should live:

Directory What it contains
/bin Essential binaries (ls, cp, mv) — available before /usr is mounted
/sbin System binaries for root (fdisk, iptables)
/etc Configuration files — never binaries
/home User home directories (/home/alice, /home/bob)
/root Root user's home (separate from /home for historical reasons)
/var Variable data — logs (/var/log), databases, mail queues
/tmp Temporary files (cleared on reboot in most distros)
/usr User programs and libraries (/usr/bin, /usr/lib)
/opt Third-party software installed manually
/proc Virtual filesystem — live kernel and process state
/dev Devices as files (/dev/sda, /dev/null, /dev/random)

You don't need to memorize this in the first week. But when you see a No such file or directory error pointing to /etc/nginx/nginx.conf, you'll know exactly where to look.

# See what's mounted and where
df -h

# Explore the structure
ls /
ls /etc | head -20

Users, groups, and who root actually is

Linux is multiuser by design. Every process runs as a user. Every file belongs to a user and a group. That combination is the foundation of the security model.

root

The root user (UID 0) has unrestricted power over the system — no permission checks apply. Running as root all the time is the equivalent of handing your master key to anyone who asks. In practice, you use a regular user account and escalate privileges only when needed via sudo.

Creating and managing users

# Create user with home directory
sudo useradd -m alice

# Create with specific shell
sudo useradd -m -s /bin/bash bob

# Set password
sudo passwd alice

# View user information
id alice
# uid=1001(alice) gid=1001(alice) groups=1001(alice)

# Delete user (keep home)
sudo userdel alice

# Delete user and home
sudo userdel -r alice

The /etc/passwd file lists all users. No real password there — that lives in /etc/shadow, which is unreadable by regular users. Each line looks like:

alice:x:1001:1001::/home/alice:/bin/bash

The x where the password would be means "real password is in /etc/shadow".

Groups

Groups let you share permissions across multiple users without granting unrestricted access. A user has a primary group (set at creation) and can belong to additional supplementary groups.

# Create group
sudo groupadd devs

# Add user to group
sudo usermod -aG devs alice
# -a = append (without this, you replace all existing groups)
# -G = supplementary groups

# View a user's groups
groups alice
# alice : alice devs

# View all members of a group
cat /etc/group | grep devs
# devs:x:1002:alice,bob

The -a flag in usermod -aG is critical. Omitting it replaces all existing group memberships with just the new one — I've seen this cause loss of sudo access in production.


How the rwx permission model works

Every file and directory on Linux has three sets of permissions: for the owner (user), for the owning group (group), and for everyone else (others).

ls -la /home/alice/script.sh
# -rwxr-xr-- 1 alice devs 1234 Jun 13 10:00 script.sh

Breaking it down:

- rwx r-x r--
│ │   │   └── others: read only
│ │   └────── group: read + execute
│ └────────── user (owner): read + write + execute
└──────────── type: - = file, d = directory, l = symlink

Each set has three bits:

  • r (read, 4): read file contents
  • w (write, 2): modify the file
  • x (execute, 1): run the file (or enter/list for directories)

The octal value for each set is the sum of active bits: rwx = 4+2+1 = 7, r-x = 4+0+1 = 5, r-- = 4+0+0 = 4. That's where chmod 754 comes from.

chmod — changing permissions

# Octal mode — direct and unambiguous
chmod 755 script.sh   # rwxr-xr-x
chmod 644 config.txt  # rw-r--r--
chmod 600 key.pem     # rw------- (SSH keys require this)

# Symbolic mode — useful for targeted changes
chmod +x script.sh          # add execute for everyone
chmod u+x,g-w file          # user +execute, group -write
chmod o-rwx file            # remove everything from others
chmod a=r file              # set read-only for all (a = all)

# Recursive — use with care
chmod -R 755 /var/www/html

Permissions on directories have different semantics than on files:

  • r on a directory: list its contents (ls)
  • w on a directory: create and remove files inside it
  • x on a directory: enter it (cd) and access files by path

Without x on a directory, you can't navigate into it even if you have r.

chown — changing owner and group

# Change owner
sudo chown bob file.txt

# Change owner and group
sudo chown bob:devs file.txt

# Change group only
sudo chown :devs file.txt
# or
sudo chgrp devs file.txt

# Recursive
sudo chown -R www-data:www-data /var/www/html

Only root can transfer file ownership to another user. A regular user can change the group of their own files, but only to groups they belong to.


umask — the default you don't see

When you create a file, the initial permissions don't come from nowhere — they come from the umask. The umask defines which bits are subtracted from the maximum permission (666 for files, 777 for directories).

umask
# 0022

# With umask 022:
# file: 666 - 022 = 644 (rw-r--r--)
# directory: 777 - 022 = 755 (rwxr-xr-x)

umask 022 is the default on virtually every distro. It means groups and others only get read access by default.

# Change umask temporarily (current session only)
umask 027
# file: 666 - 027 = 640 (rw-r-----)
# directory: 777 - 027 = 750 (rwxr-x---)

For web servers where files need to be readable by www-data but not by others, umask 027 with www-data in the group is a reasonable setup.


SUID, SGID, and sticky bit — the special cases

Beyond rwx, there are three bits with special behavior:

SUID (Set User ID, 4xxx): when applied to an executable, it runs with the owner's permissions, not the caller's. The passwd command works this way — you need to write to /etc/shadow which belongs to root.

ls -la /usr/bin/passwd
# -rwsr-xr-x 1 root root ... /usr/bin/passwd
# 's' in place of user 'x' = SUID active

SGID (Set Group ID, 2xxx): on directories, files created inside inherit the directory's group rather than the creator's primary group. Essential for shared project directories.

chmod g+s /var/shared
# Any file created here inherits the directory's group

Sticky bit (1xxx): on directories, prevents users from deleting each other's files even when they have write permission on the directory. This is what protects /tmp.

ls -la /
# drwxrwxrwt ... tmp
# 't' in place of others 'x' = sticky bit active

chmod +t /tmp/shared

To work with these bits numerically, use four digits: chmod 1777 /tmp/folder (sticky + rwxrwxrwx), chmod 2755 /var/project (SGID + rwxr-xr-x).


Frequently asked questions

How do I check a file's exact permissions quickly?

stat file.txt
# Shows: File, Size, Blocks, IO Block, type, Device
# Access: (0644/-rw-r--r--)  Uid: (1001/alice)  Gid: (1001/alice)

ls -la gives the compact format. stat gives the octal directly — useful when you need to confirm the exact number without converting in your head.

Why is chmod -R 777 a bad idea?

Because it gives every user on the system full permission to read, modify, and execute every file in that tree. On shared servers, this lets other users — including compromised processes — overwrite your files. For web applications, it means an attacker who achieves code execution can modify your own scripts. 777 fixes the immediate problem and creates ten future ones.

What's the difference between su and sudo?

su switches completely to another user (root by default) — you need the target user's password. sudo runs a specific command with elevated privileges, authenticating with your own password, and access is controlled by /etc/sudoers. In modern practice, sudo is preferable: access is auditable per user, can be restricted to specific commands, and doesn't expose the root password.

What happens to permissions on symbolic links?

The symlink itself always shows lrwxrwxrwx — what matters are the permissions on the target file. chmod applied to a symlink changes the target, not the link.


Permission isn't an obstacle — it's access control

The Unix permission model is 50 years old and still runs on every Linux server in existence. Simple by design: three entities (user, group, others), three bits (r, w, x), and a few extensions (SUID, SGID, sticky) for specific cases.

The real learning curve isn't technical — it's building the habit of asking "who needs access and for what?" before running chmod. 644 for config files, 755 for binaries and public directories, 600 for private keys and credentials. Once you reason this way, Permission denied stops being a scare and starts being information.

For calculating permissions without doing octal math in your head, I use the CHMOD Calculator — click the bits, see octal and symbolic output simultaneously, and get a security warning when you mark something dangerous like 777.


Note: editorial content ends here. What follows is a pointer to a related tool.


The CHMOD Calculator on Quick Tools lets you visually configure owner, group, and others permissions, see the result in both octal and symbolic notation at the same time, supports SUID/SGID/sticky bit, and flags security warnings when the chosen combination has dangerous implications — all in the browser, nothing to install.

RD
Author
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
View profile