Users, Groups, and Permissions
Introduction
Every file on Linux has an owner, a group, and permission bits for user/group/others. Misconfigured permissions cause Permission denied during deploys and security incidents when everything is 777. This chapter reads ls -l output and fixes access with chmod and chown.
Prerequisites
Users and Groups
# Current user
whoami
# User id, primary group, all groups
id
# Switch user (needs password)
su - anotheruser
# Root shell (use carefully)
sudo -iSystem accounts live in /etc/passwd; groups in /etc/group. You rarely edit those files by hand—use adduser on servers.
Add a deployment user (example):
# Interactive user creation on Ubuntu
sudo adduser deploy
# Add to sudo group if admins required
sudo usermod -aG sudo deployRun apps as a dedicated non-root user in production—not as root.
Read ls -l Permission String
Example line:
-rwxr-xr-- 1 deploy deploy 4096 May 20 10:00 app.jar| Field | Meaning |
|---|---|
- | File type (- file, d directory, l symlink) |
rwx | Owner permissions |
r-x | Group permissions |
r-- | Others permissions |
deploy deploy | Owner user and group |
app.jar | Name |
Letters: r read, w write, x execute. For directories, x means you may cd into it.
chmod: Symbolic and Numeric
Symbolic:
# Add execute for owner
chmod u+x script.sh
# Read/write for owner, read for group/others
chmod u=rw,go=r config.propertiesNumeric (common in tutorials and deploy docs):
| Mode | Meaning | Typical use |
|---|---|---|
755 | rwxr-xr-x | Directories, executable scripts |
644 | rw-r--r-- | Regular files, configs |
600 | rw------- | Secrets (SSH keys, .env) |
700 | rwx------ | Private directories (~/.ssh) |
# Make script executable
chmod 755 deploy.sh
# Private key file
chmod 600 ~/.ssh/id_ed25519Warning
chmod -R 777 fixes permission errors temporarily and opens files to everyone. Never use 777 on servers—find the real owner/group issue instead.
chown and chgrp
Change owner (root or sudo):
# Change owner and group
sudo chown deploy:deploy /opt/myapp/app.jar
# Recursive for directory tree
sudo chown -R deploy:deploy /opt/myapp# Change group only
sudo chgrp www-data /var/www/htmlNginx or Apache often need www-data group on web roots; Java apps often run as deploy or a service user.
umask: Default Permissions for New Files
# Show current umask
umaskDefault 022 on many systems yields 755 for new directories and 644 for new files (subtract from 777). Developers rarely change umask; know it exists when new files look “too open” or “too closed”.
Special Permissions (Awareness)
| Bit | Name | One-line idea |
|---|---|---|
| setuid | s on user x | Run as file owner (e.g. passwd) |
| setgid | s on group x | Run as file group |
| sticky | t on dir x | Only owner deletes own files in /tmp |
# Sticky bit visible on /tmp
ls -ld /tmpYou will not set these often; recognize them in ls -l.
Deploy Scenario: Spring Boot JAR
# App owned by deploy user
sudo mkdir -p /opt/myapp
sudo chown deploy:deploy /opt/myapp
# JAR readable, not world-writable
sudo cp app.jar /opt/myapp/
sudo chown deploy:deploy /opt/myapp/app.jar
chmod 644 /opt/myapp/app.jarLogs directory writable by app user only:
sudo mkdir -p /opt/myapp/logs
sudo chown deploy:deploy /opt/myapp/logs
chmod 755 /opt/myapp/logsMini Example: Fix Script Not Executable
# Script fails with Permission denied
./run.sh
# Add execute bit
chmod +x run.sh
./run.shFAQ
Why Permission denied on a script I own?
Missing x bit, or filesystem mounted noexec. Run ls -l script.sh and mount | grep mountpoint.
Should I run Java as root?
No—use a service user and systemd (covered in a later chapter).
sudo chmod vs chmod?
Changing another user’s files requires root/sudo. Your own files: plain chmod.
Groups and Docker?
Docker daemon often requires docker group membership—adds privileges; understand security trade-offs.