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.