Linux Users, Groups & Permissions
Learn the Unix permission model: ownership, groups, chmod/chown, and practical patterns for running services safely.
In DevOps, permissions are the difference between:
- a service that starts and writes logs correctly
- and a service that crashes silently (or can’t read configs / can’t access volumes)
This tutorial focuses on the practical mental model and the most common commands.
Learning outcomes
By the end, you’ll be able to:
- interpret
ls -loutput - use
chownandchgrp - use
chmod(symbolic + numeric) - avoid common permission pitfalls for services and deployment artifacts
Ownership and groups (who “owns” the file)
Every file/directory has:
- owner (user)
- group
- permission bits
Check it:
ls -l /etc/nginx/nginx.conf
# -rw-r--r-- 1 root root 1234 Jan 01 00:00 nginx.conf
Interpretation:
root root→ owner and group-rw-r--r--→ permissions
Permission bits: what each triplet means
- rwx r-x r--
- owner:
rw- - group:
r-x - others:
r--
Where:
r= readw= writex= execute/search (for directories)
chmod: change permissions
Symbolic mode (human-friendly)
# add read permission for group
chmod g+r file.txt
# remove write permission for others
chmod o-w file.txt
# set exact permissions (symbolic)
chmod u=rwx,g=rx,o=r file.txt
Numeric mode (common in scripts)
Numeric mapping:
4= read2= write1= execute
So:
7= rwx5= r-x4= r—
Examples:
# rwxr-xr-x = 755
chmod 755 /usr/local/bin/myapp
# rw-r--r-- = 644
chmod 644 ./config.yml
chown / chgrp: change owner and group
# change owner only
sudo chown myuser: /var/log/myapp
# change owner and group
sudo chown myuser:mygroup /var/log/myapp
# change group recursively
sudo chgrp -R mygroup /srv/myapp
Practical patterns for running services safely
1) Create a dedicated user
Instead of running as root, create an app user and chown the directories it needs.
2) Use restrictive defaults for secrets
- config files containing credentials:
640or600 - directories for app logs:
750
3) Prefer group-based sharing
If multiple processes need shared read access:
- set a common group
- set group read perms
Example:
# shared directory
sudo chown -R appuser:appgroup /srv/myapp
sudo chmod -R g+rX /srv/myapp
Special bits (when you must share safely)
Sticky bit (t = on directory)
Useful for world-writable temp dirs like /tmp.
- non-owners can’t delete each other’s files
Check:
ls -ld /tmp
# drwxrwxrwt
setuid/setgid
Advanced but occasionally needed (rare in modern service deployments).
Troubleshooting checklist
If your service can’t read/write:
- verify the process user/group
ps aux | grep myapp - verify permissions on the target paths
ls -l /path/to/config /path/to/logs - confirm group membership and ownership
- re-check mounted volumes and deployment steps
Next steps
Continue with:
- Linux networking fundamentals
- shell scripting patterns for repeatable ops
- processes + systemd logs
Frequently Asked Questions
Why do services fail after changing file permissions?
Because the service runs under a specific user/group; read/write/execute bits (and sometimes SELinux/AppArmor) must match what the process needs for configs, logs, and mounted volumes.
What’s the purpose of the setuid/setgid/sticky bits?
They modify how permissions behave. setuid/setgid run executables with the file’s owner/group; sticky prevents non-owners from deleting others’ files in a shared directory.