Linux7 min readPublished: 19 Oct 2024Updated: 29 Jul 2026

Linux Users, Groups and Permissions Explained

How Linux users, groups and file permissions fit together: UIDs, primary and secondary groups, chmod and chown, umask and the special permission bits.

G7Cloud Engineering
Platform team
Share:
Abstract illustration representing linux users, groups and permissions explained.
  • Linux checks permissions in order: are you the owner, then are you in the group, then everyone else. The first match wins and it stops there.
  • Because the first match wins, a file set to 604 denies the group read access while granting it to everyone else.
  • Every user has one primary group, which owns the files they create, plus any number of secondary groups that grant access.
  • umask subtracts from the default permissions on new files. 022 gives 644 files and 755 directories.
  • setgid on a directory makes new files inherit its group, which is what keeps a shared document root consistent.

How does Linux decide who can access a file?

Linux checks three things in a fixed order. Are you the owner? If yes, the owner permissions apply and the check stops. If not, are you in the owning group? If yes, the group permissions apply and the check stops. Otherwise the other permissions apply. The first match wins, and nothing later can grant more.

The first match wins, which produces one genuinely odd result

A file set to 604 (owner read-write, group nothing, others read) means a member of the group cannot read it, while a complete stranger can. Linux matched on group, found no permission, and stopped. It never falls through to the other bits. This trips people up the first time they see it.

Seeing the three sets
$ ls -l /var/www/example.com/wp-config.php
-rw-r----- 1 deploy www-data 3021 Jul 29 09:14 wp-config.php

# -    rw-        r--        ---
# |    |          |          |
# |    |          |          +-- others: nothing
# |    |          +------------- group www-data: read
# |    +------------------------ owner deploy: read and write
# +----------------------------- file type

# That is 640. Exactly what a config file holding a password should be.
Owner deploy can edit it, the web server can read it, and no other account on the machine can see the database password.

What is the difference between a user and a UID?

The username is for humans. The kernel only ever deals in numeric user IDs. Everything about ownership and access is decided on the number, and the name is looked up from /etc/passwd for display. That distinction matters more than it sounds when you move files between machines.

Names are a display layer
# Your numeric identity, and every group you are in
id
# uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),33(www-data)

# Show numeric IDs instead of names
ls -ln /var/www/example.com

# Files whose owner has no matching account (orphaned UIDs)
sudo find /var/www -nouser -o -nogroup 2>/dev/null
Orphaned UIDs appear after restoring a backup from another server, or after deleting a user who owned files. Listing users on Linux covers finding the accounts behind them.

This is why tar archives change ownership

A tar archive stores numeric IDs. Restore it on a server where UID 1001 belongs to a different person and the files now belong to that person. Use tar --numeric-owner when you want the numbers preserved deliberately, and always check ownership after a cross-server restore.

UID rangePurpose
0root: every permission check is skipped entirely
1 to 999Service accounts: www-data, mysql, sshd
1000 and aboveHuman accounts
65534nobody: the deliberately powerless fallback

root is not privileged because of its permissions. The kernel simply does not check them for UID 0.

How do primary and secondary groups differ?

Every user has exactly one primary group, recorded in /etc/passwd, and it is the group applied to any file they create. Secondary groups, recorded in /etc/group, grant access to things but never affect ownership of anything new.

The distinction in practice
$ id deploy
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),33(www-data),1005(webdev)
#                ^^^^^^^^^^^^^^^^ primary        ^^^^^^^^^^^^^^^^^^^^^ secondary

# deploy is in www-data, so it can READ what www-data can read.
# But new files it creates are owned by group deploy, not www-data,
# so the web server cannot read them.

$ sudo -u deploy touch /var/www/example.com/new.php
$ ls -l /var/www/example.com/new.php
-rw-r--r-- 1 deploy deploy 0 Jul 29 10:02 new.php
#                   ^^^^^^ not www-data: this is the classic surprise
This is why a deploy that appeared to work leaves the web server unable to read the new files.

There are two fixes. Change the user's primary group, which affects everything they create everywhere, or set the setgid bit on the directory, which affects only that tree. The second is almost always the right one.

setgid: the directory decides the group
# Set the group on the tree, then make it inherit
sudo chgrp -R www-data /var/www/example.com
sudo find /var/www/example.com -type d -exec chmod g+s {} \;

# Now anything created inside belongs to www-data automatically
sudo -u deploy touch /var/www/example.com/another.php
ls -l /var/www/example.com/another.php
# -rw-r--r-- 1 deploy www-data 0 Jul 29 10:05 another.php
The s in the group position of drwxr-sr-x is setgid. It survives, so the arrangement holds without anyone maintaining it.

How do chmod and chown actually work?

chmod changes what can be done. chown changes who it belongs to. chmod accepts either octal numbers, which set everything at once, or symbolic notation, which adjusts one thing and leaves the rest alone.

Octal and symbolic
# Octal: sets all three sets at once
chmod 644 file.txt      # rw- r-- r--
chmod 755 script.sh     # rwx r-x r-x
chmod 600 ~/.ssh/id_ed25519

# Symbolic: changes one thing, leaves the rest
chmod u+x script.sh     # add execute for the owner
chmod g+w shared/       # add write for the group
chmod o-rwx private/    # remove everything for others
chmod a+r public.txt    # add read for all three sets

# Directories only, files only: the pattern that matters
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
Symbolic notation is safer on a live server: it cannot accidentally strip a permission you were not thinking about.
chown and chgrp
# Owner only
sudo chown deploy file.txt

# Owner and group
sudo chown deploy:www-data file.txt

# Group only (two equivalent forms)
sudo chown :www-data file.txt
sudo chgrp www-data file.txt

# Recursively across a tree
sudo chown -R deploy:www-data /var/www/example.com

# Copy ownership from an existing file, which avoids typos
sudo chown --reference=/var/www/example.com/index.php newfile.php
--reference is the one to use when you are unsure what the ownership should be: it copies from something already correct.

chmod -R 755 on a website is a mistake

It sets the execute bit on every file, including images, CSS and PHP source. Some server configurations will then treat executable files differently, and it makes a genuine executable impossible to spot. Always split directories and files with find, as shown above.

What is umask and why do my new files have the wrong permissions?

umask is a mask subtracted from the system defaults whenever a file is created: 666 for files and 777 for directories. The default umask of 022 removes write from group and others, which is where 644 and 755 come from.

umaskNew filesNew directoriesUse for
022644755Default: only the owner can write
002664775Team directories where the group must write
077600700Private: nothing visible outside the owner
027640750Owner writes, group reads, others excluded

Directories never get the execute bit removed by umask 022, which is why they end up 755 rather than 644.

Checking and setting umask
# Current value
umask

# In symbolic form, easier to read
umask -S

# Set for this shell only
umask 002

# Persist for one user
echo 'umask 002' >> ~/.bashrc

# Persist for a systemd service
# In the unit file, under [Service]:
#   UMask=0002
A service's umask comes from its unit file, not from any shell profile. That catches people out with PHP-FPM and deploy agents.
Pro Tip

If files created by a deploy script keep coming out unreadable by the web server, check the umask of the process running the script, not the interactive shell you tested in. They are frequently different.

What do setuid, setgid and the sticky bit do?

Three extra bits sit above the usual nine. You will use setgid regularly on shared directories, meet the sticky bit on /tmp, and should treat setuid as something to audit rather than something to set.

BitOctalOn a fileOn a directory
setuid4000Runs as the file's owner, not youNo effect on Linux
setgid2000Runs as the file's groupNew files inherit the directory's group
sticky1000No effectOnly the owner of a file can delete it

setgid on a directory is the useful one. The other two you mostly just need to recognise.

Where you meet them
# /tmp: anyone can write, only the owner can delete their own files
ls -ld /tmp
# drwxrwxrwt 12 root root 4096 Jul 29 10:14 /tmp
#          ^ the t is the sticky bit

# passwd is setuid root: it must edit /etc/shadow on your behalf
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 ... /usr/bin/passwd
#    ^ the s is setuid

# Audit every setuid binary on the system. Do this on any
# server you have inherited.
sudo find / -perm -4000 -type f -ls 2>/dev/null
That last command is a standard security check, worth running alongside a patching routine. An unexpected setuid binary in /tmp or a home directory is a serious finding.

Never set setuid on your own scripts

Linux ignores setuid on shell scripts anyway, for good reason, and a setuid binary that takes any user input is a route to root. If a task needs root privileges, grant a specific sudo rule for that exact command instead.

For the applied version of all this, with the exact numbers a WordPress install wants, see Linux file permissions for web servers and WordPress. If server accounts are not something you want to own at all, our managed WordPress hosting runs each site in its own isolated container with the permissions maintained for you.

Frequently asked questions

What is the difference between a primary and secondary group in Linux?

A user has exactly one primary group, and it becomes the group owner of every file they create. Secondary groups grant access to existing files but never affect ownership of new ones. That is why adding someone to www-data does not make their new files readable by the web server.

Why can't a group member read a file that others can read?

Because Linux stops at the first matching category. If you are in the owning group, the group bits apply and nothing falls through to the other bits. A file set to 604 denies group members while allowing everyone else, which looks wrong until you know the rule.

What does umask 022 mean?

It removes write permission from group and others on anything newly created. Files start from 666 and become 644; directories start from 777 and become 755. Use 002 instead when a team shares a directory and everyone needs to edit each other's files.

What does the setgid bit do on a directory?

New files and subdirectories created inside inherit the directory's group rather than the creating user's primary group. On a shared web root that keeps ownership consistent no matter who uploads what, which is what stops permissions drifting over time. Set it with chmod g+s.

Should I use chmod 777 to fix a permission problem?

No. 777 lets every account and every process on the machine rewrite the file. When something only works at 777 the actual problem is ownership: the process needs to be in the owning group. Fix it with chown and a 775 group-write directory.

How do I find files with unusual permissions?

sudo find / -perm -4000 -type f -ls lists every setuid binary, and find /var/www -perm -o+w -type f lists anything world-writable under your web root. Both are worth running on a server you have just taken over.

Put this into practice on G7Cloud

Every site runs in its own dedicated container behind ScaleShield, with daily backups that are restore-tested every night. Start on the free plan, no card needed.

About G7Cloud Engineering

Platform team

Articles written by the engineers who build and run G7Cloud: UK managed hosting and the AI Website Builder. We write about what we operate every day: containers, backups, databases, and the small-business websites that run on them.

More about G7Cloud →