Linux systems 26 entries 22 run in the sandbox

Linux permissions and users cheat sheet

Modes, ownership, sudo, groups and ACLs without reaching for 777. Each entry has a worked example and the flags worth knowing, and where one is easy to get wrong, the gotcha.

Read permissions

ls -l <file>

Read the mode string: a type character, then read/write/execute triplets for the owner, the group and everyone else.

ls -l deploy.sh
-rwxr-x--- 1 deploy deploy 812 Sep 23 10:02 deploy.sh
r = 4
Read a file; list a directory's names.
w = 2
Modify a file; create, rename or delete entries in a directory.
x = 1
Execute a file; enter (traverse) a directory.
trailing +
An ACL adds rules beyond the mode bits; check getfacl.

Gotcha Deleting a file needs write permission on the directory, not on the file.

namei -l <path>

Show owner and mode for every component of a path. Finds the one parent directory that blocks traversal.

namei -l /var/www/app/static/logo.png
f: /var/www/app/static/logo.png
drwxr-xr-x root     root     /
drwxr-xr-x root     root     var
drwxr-xr-x root     root     www
drwx------ deploy   deploy   app
drwxr-xr-x deploy   deploy   static
-rw-r--r-- deploy   deploy   logo.png
-l
Long listing with owner, group and mode.
-m
Show only the mode bits.

Gotcha A 403 from nginx on a world-readable file usually means a parent directory lacks x for the nginx user. Here app is 700.

id [user]

Print a user's uid, primary gid and every supplementary group.

id
uid=1000(user) gid=1000(user) groups=1000(user),27(sudo),998(docker)
-u
Print only the effective uid.
-Gn
Print group names only.

Gotcha A shell that was open before usermod -aG still has the old group list. Log out and back in, or run newgrp.

groups [user]

List the groups a user belongs to.

groups

getent passwd <user>

Look up an account through NSS (local files, LDAP, SSSD), including its home directory and login shell.

getent passwd root
root:x:0:0:root:/root:/bin/bash
passwd
User accounts: name:x:uid:gid:gecos:home:shell.
group
Groups and their members.
hosts
Resolve a name the way applications do, including /etc/hosts.

Change modes & owners

chmod <mode> <file>

Set permissions with an octal mode. Each digit is the sum of r=4, w=2, x=1 for owner, group and others.

chmod 640 app.env
644
Regular files: owner writes, everyone reads.
755
Directories and executables others may run.
640
Config the owner edits and a service group reads.
600
Private keys and secrets: owner only.
-R
Apply recursively.

Gotcha chmod 777 is never the fix. Find which user needs access and grant exactly that with ownership, a group or an ACL.

chmod u+x <file>

Adjust individual bits without restating the whole mode.

chmod u+x deploy.sh
u g o a
Owner, group, others, or all three.
+ - =
Add, remove or set exactly.
X
Execute only for directories and files already executable by someone.
o=
Remove every permission for others.

chmod -R u=rwX,g=rX,o= <dir>

Fix a whole tree in one pass: directories stay traversable, files only become executable if they already were.

chmod -R u=rwX,g=rX,o= /srv/app
-R
Recurse into the directory.
X
Grant x to directories but not to plain data files.

Gotcha chmod -R 755 marks every data file executable. Use capital X, or find -type d and -type f separately.

chown <user>:<group> <path>

Change the owner and group of files. Usually needs sudo.

sudo chown -R webapp:webapp /var/log/webapp
user:group
Set both; use :group alone to change only the group.
-R
Recurse into directories.
--reference=FILE
Copy the owner and group from FILE.
-h
Change a symlink itself, not its target.

Gotcha A service that runs as its own user must own the directories it writes. Wrong ownership is a top cause of services failing right after deploy.

umask [mask]

Show or set the bits removed from the permissions of newly created files and directories.

umask 027
022
Common default: new files 644, new directories 755.
027
Stricter: files 640, directories 750, nothing for others.
-S
Print the mask symbolically, for example u=rwx,g=rx,o=.

Gotcha umask only affects the current shell and its children. For a service, set UMask= in the systemd unit.

chmod 2775 <dir>

Special bits: setgid on a directory makes new files inherit its group; sticky stops users deleting each other's files.

chmod 2775 /srv/shared
4xxx setuid
An executable runs as its owner. Audit: find / -perm -4000 -type f.
2xxx setgid
A directory's new files inherit its group.
1xxx sticky
Only a file's owner may delete it; /tmp is 1777.

chattr +i <file>

Set filesystem attributes. The immutable bit blocks every write, rename and delete, even by root.

lsattr /etc/resolv.conf
----i---------e------- /etc/resolv.conf
+i / -i
Set or clear immutable.
+a
Append-only, useful for audit logs.
lsattr
List attributes.

Gotcha 'Operation not permitted' as root on a plain file? Check lsattr before anything else.

Users & sudo

whoami

Print the effective user name. Run it first when a script behaves differently under sudo or cron.

user

sudo -l

List the commands you are allowed to run with sudo, and as which users.

User deploy may run the following commands on web-01:
    (root) NOPASSWD: /usr/bin/systemctl restart webapp
-l
List allowed commands for the invoking user.
-U USER
With -l, list another user's privileges (needs rights).

sudo -u <user> <cmd>

Run one command as a specific user, usually a service account, to reproduce what it can see.

sudo -u webapp cat /etc/webapp/app.env
-u USER
Run as USER instead of root.
-i
Start a login shell as the target user.
-E
Preserve your environment (if the policy allows it).

Gotcha Reproduce permission bugs as the service user. Root can read everything, so testing as root hides the problem.

sudo -i

Open a root login shell for a run of admin commands: the prompt ends in # and exit comes back.

-i
Login shell: /root and root's environment.
-s
A root shell that stays in the current directory.
-iu USER
A login shell as USER.

Gotcha Everything typed in a root shell runs as root, and the log only shows that a shell was opened. Prefer sudo per command, and leave a root shell as soon as you are done.

su - <user> -c '<cmd>'

Become another user, starting like a fresh login in their home directory: for one command with -c, or as a shell that exit leaves. Through sudo no password is asked.

sudo su - alice -c 'id -un; pwd'
-
Start like a login: their home directory and only their environment.
-c CMD
Run one command and return.
-s SHELL
As root: use SHELL for an account whose shell is nologin.

Gotcha su asks for the other user's password, sudo for yours. Without the dash you keep your own directory and environment, and files end up in the wrong place.

visudo -f /etc/sudoers.d/<name>

Edit a sudoers file with a syntax check before it is saved.

sudo visudo -f /etc/sudoers.d/deploy
-f FILE
Edit a drop-in file instead of /etc/sudoers.
-c
Check every sudoers file for syntax errors.

Gotcha A syntax error in sudoers can remove sudo for everyone. Always use visudo, and make drop-ins mode 0440.

user HOST=(RUNAS) NOPASSWD: <cmd>

A least-privilege sudoers rule that allows exactly one command with exact arguments.

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart webapp
ALL (host)
The rule applies on every host that reads this file.
(root)
The user the command runs as.
NOPASSWD:
Skip the password prompt for this rule only.
full path
Always use absolute command paths; PATH lookups are not trusted.

Gotcha Granting a command that opens an editor, pager or shell (vim, less, bash) grants full root.

useradd -m -s <shell> <user>

Create a user account with a home directory and a login shell.

sudo useradd -m -s /bin/bash -G docker alice
-m
Create the home directory.
-s SHELL
Login shell; use /usr/sbin/nologin for service accounts.
-G g1,g2
Supplementary groups.
-r
Create a system account with a low uid and no aging.

usermod -aG <group> <user>

Add a user to a supplementary group without touching their other groups.

sudo usermod -aG docker alice
-a
Append; only valid together with -G.
-G
The supplementary group list.
-L / -U
Lock or unlock the account's password.

Gotcha -G without -a replaces every supplementary group, which can silently drop someone's sudo access.

echo '<user>:<password>' | chpasswd

Set passwords from NAME:PASSWORD lines on standard input: what scripts and provisioning tools use instead of typing into passwd.

echo 'alice:N3w-secret' | sudo chpasswd
-e
The passwords are already hashes, as made by openssl passwd -6.
passwd -e USER
Force a change at the next login.
chage -M 90 USER
Make the password expire after 90 days.

Gotcha A password on the command line ends up in the shell history. Read the lines from a file only root can read, and force a change at the first login.

passwd -l <user>

Lock an account's password during offboarding or an investigation.

sudo passwd -l alice
-l / -u
Lock or unlock the password.
-S
Show the account's password status.
chage -l USER
Show password aging and expiry.

Gotcha A locked password does not block SSH key logins. Also remove authorized_keys or set the shell to nologin.

who

Show who is logged in right now, on which terminal and from where.

w
Like who, plus what each session is running.
last -n 10
Recent logins from /var/log/wtmp.

ACLs

getfacl <path>

Show a file's ACL entries alongside its owner, group and mask.

getfacl /srv/reports
# file: srv/reports
# owner: root
# group: finance
user::rwx
user:alice:r-x
group::r-x
mask::r-x
other::---
-R
Recurse into directories.
-d
Show the default ACL only.

setfacl -m u:<user>:<perms> <path>

Grant one extra user or group access without changing the owner or loosening the mode for everyone.

setfacl -m u:alice:rX /srv/reports
-m
Modify or add entries.
-x
Remove an entry, for example -x u:alice.
-d
Set a default ACL that new files in a directory inherit.
-b
Remove all extended entries.

Gotcha The mask caps every named entry. A later chmod g-w can silently lower the mask and break ACL grants.

Your pager is ready.

Free, instant, and it works on your phone. No signup: start as a guest and save your progress later.