Guide

Every file has an owner, a group, and nine permission bits. Every process runs as a user. When a service gets "permission denied", the question is which of those bits blocked it. Root skips these checks entirely, which is why teams try to avoid running services as root.

Walking through it

Take a config file that holds secrets:

-rw-r----- 1 orders orders 2048 Mar 14 09:26 /etc/orders-api/env
 owner rw-, group r--, others ---   =  6 4 0  =  mode 640

Each group of three bits is a sum: read is 4, write is 2, execute is 1. So 640 means the owner can read and write, the group can read, and everyone else gets nothing. That is the right setting for a file with secrets. Typical values are 755 for directories and programs, and 600 for SSH private keys, which SSH refuses to use otherwise.

A directory's execute bit means "may enter". A file can be mode 644 and still be unreadable if a parent directory is 700 and owned by someone else. That is the most common cause of a permission error that looks wrong.

Bash
namei -l /var/lib/orders-api/data/db.sqlite

namei -l prints the owner and mode of every directory on the path. The culprit is usually a parent.

The umask sets default permissions for new files by masking bits off. The common 022 turns a requested 666 into 644, and 777 into 755.

Narrow grants, not root

sudo lets permitted users run specific commands as root, and logs each one. Edit the rules only with visudo, which checks the syntax first. A broken sudoers file can lock everyone out of root. Grant one command:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart orders-api

Root's power is split into about 40 capabilities. A web server that only needs port 443 can get that one capability instead of full root. Ports below 1024 are privileged, so:

Bash
sudo setcap 'cap_net_bind_service=+ep' /opt/orders-api/bin/server
getcap /opt/orders-api/bin/server

In a systemd unit, the same grant is AmbientCapabilities=CAP_NET_BIND_SERVICE. In Kubernetes, the safer default is to drop all capabilities and add back only what the container needs. CAP_SYS_ADMIN is so broad it is close to root, and granting it to a container mostly defeats isolation.

Common mistakes

  • Fixing "permission denied" with chmod 777. It opens the file to everyone on the host. Find the blocking bit first.
  • Checking only the file. Look at every parent directory with namei -l.
  • Running a service as root so it can bind a low port. Grant the single capability instead.

Check yourself

  1. A file is mode 644, but the service still cannot read it. What do you check? The parent directories. One of them probably lacks execute (traverse) permission for that user.
  2. A service must bind port 443 without root. What do you grant? The CAP_NET_BIND_SERVICE capability, using setcap or AmbientCapabilities.

Key takeaways

  • Permissions are owner, group and others, with read, write and execute bits. Read them as sums: 640 means rw-r-----.
  • Directories need execute to be entered, so a bad parent can block a good file.
  • Grant narrow sudo rules and single capabilities instead of root.

Further learning

Identity and access across cloud accounts is in IAM and least privilege. For the next idea, see how disks fill up in disk space and mounts.

The Linux Command Line (William Shotts)Linux Command Line Books by William Shottslinuxcommand.org