How to Create Users and Manage Permissions in Linux: The Complete Guide
Linux user management forms the backbone of system security. Every file, process, and service runs under a specific user context. Proper user and permission management prevents unauthorized access, data breaches, and system compromises.
This guide teaches you how to:
- Create and manage users efficiently
- Configure file permissions correctly
- Implement access control lists
- Automate user provisioning
- Troubleshoot permission issues
Table of Contents
Understanding Linux User Types and System Architecture
Types of Users in Linux
Linux systems contain four main user types:
- Root User (UID 0): Has complete system control. Can modify any file and execute any command.
- System Users (UID 1-999): Run system services and daemons. Cannot login interactively.
- Regular Users (UID 1000+): Human users who login and perform tasks.
- Service Accounts: Special-purpose accounts for running specific applications.
User Database Files
Linux stores user information in four critical files:
/etc/passwd Structure
Contains user account information. Each line represents one user with seven colon-separated fields:
username:x:1000:1000:Full Name:/home/username:/bin/bash
Fields breakdown:
- Username: Login name
- Password: ‘x’ indicates password stored in /etc/shadow
- UID: User ID number
- GID: Primary group ID
- GECOS: User description or full name
- Home directory: User’s home path
- Shell: Default shell program
/etc/shadow Structure
Stores encrypted passwords and aging information. Only root can read this file:
username:$6$hash:19000:0:99999:7:::
/etc/group Structure
Defines system groups:
groupname:x:1000:user1,user2,user3
/etc/gshadow Structure
Contains encrypted group passwords (rarely used).
Creating and Managing Linux Users
Essential User Management Commands
Creating Users with useradd
The useradd command creates new user accounts:
# Basic user creation
sudo useradd john
# Create user with home directory
sudo useradd -m sarah
# Create user with specific UID
sudo useradd -u 2000 mike
# Create user with comment
sudo useradd -c "John Doe - DevOps" -m john
# Create user with specific shell
sudo useradd -s /bin/zsh -m alice
# Create user with multiple options
sudo useradd -m -d /custom/home/bob -s /bin/bash -c "Bob Smith" -u 2001 bob
useradd vs adduser
Key differences:
- useradd: Low-level utility, requires manual configuration
- adduser: Interactive Perl script (Debian/Ubuntu), user-friendly wrapper
# Using adduser (Debian/Ubuntu)
sudo adduser jane
# Prompts for password and user information
Modifying Users with usermod
# Change username
sudo usermod -l newname oldname
# Change home directory
sudo usermod -d /new/home/path username
# Add user to supplementary groups
sudo usermod -aG docker,sudo username
# Lock user account
sudo usermod -L username
# Unlock user account
sudo usermod -U username
# Change user shell
sudo usermod -s /bin/zsh username
# Set account expiration
sudo usermod -e 2024-12-31 username
Deleting Users with userdel
# Delete user (keeps home directory)
sudo userdel username
# Delete user and home directory
sudo userdel -r username
# Force deletion (even if user logged in)
sudo userdel -f username
Advanced User Creation Options
Create system users for services:
# Create system user (no home, no login)
sudo useradd -r -s /usr/sbin/nologin mysqluser
# Create user with specific primary group
sudo useradd -g developers -m developer1
# Create user with password
sudo useradd -m -p $(openssl passwd -6 password123) user1
# Create user with account expiration
sudo useradd -e 2024-06-30 contractor1
Batch User Creation
Create multiple users efficiently:
Using a Shell Script
#!/bin/bash
# batch_users.sh
users=("user1" "user2" "user3" "user4" "user5")
for user in "${users[@]}"; do
sudo useradd -m -s /bin/bash "$user"
echo "$user:TempPass123!" | sudo chpasswd
sudo chage -d 0 "$user" # Force password change on first login
echo "Created user: $user"
done
Using newusers Command
Create a file users.txt:
john:password:1001:1001:John Doe:/home/john:/bin/bash
jane:password:1002:1002:Jane Smith:/home/jane:/bin/bash
bob:password:1003:1003:Bob Johnson:/home/bob:/bin/bash
Import users:
sudo newusers users.txt
Linux Group Management Fundamentals
Creating and Managing Groups
Group Creation Commands
# Create a new group
sudo groupadd developers
# Create group with specific GID
sudo groupadd -g 2000 admins
# Create system group
sudo groupadd -r systemgroup
Modifying Groups
# Rename group
sudo groupmod -n newname oldname
# Change GID
sudo groupmod -g 2001 groupname
Deleting Groups
# Delete group
sudo groupdel groupname
Group Membership Management
Manage user group memberships:
# Add user to group
sudo usermod -aG groupname username
# Set user's primary group
sudo usermod -g groupname username
# Remove user from group (edit /etc/group manually or use gpasswd)
sudo gpasswd -d username groupname
# View user's groups
groups username
# View group members
getent group groupname
# Add multiple users to group
sudo gpasswd -M user1,user2,user3 groupname
Linux File Permissions: The Foundation
Understanding Permission Structure
Linux uses three permission types:
- Read (r=4): View file contents or list directory
- Write (w=2): Modify file or create/delete in directory
- Execute (x=1): Run file or access directory
Permissions apply to three entities:
- User (u): File owner
- Group (g): Group owner
- Others (o): Everyone else
Reading Permission Output
ls -la
-rwxr-xr-- 1 john developers 4096 Jan 15 10:30 script.sh
Breakdown:
- First character: File type (- = regular file, d = directory, l = link)
- Next 9 characters: Permissions (user, group, others)
- Owner: john
- Group: developers
Using chmod Command Effectively
Numeric Method
# Give owner full permissions, group read/execute, others nothing
chmod 750 file.sh
# Common permissions
chmod 755 script.sh # rwxr-xr-x
chmod 644 document.txt # rw-r--r--
chmod 600 private.key # rw-------
chmod 777 public.tmp # rwxrwxrwx (avoid this!)
# Recursive permission change
chmod -R 755 /var/www/html
Symbolic Method
# Add execute for owner
chmod u+x script.sh
# Remove write for group
chmod g-w file.txt
# Set exact permissions
chmod u=rwx,g=rx,o=r file.sh
# Add read for all
chmod a+r document.txt
# Remove all permissions for others
chmod o-rwx sensitive.dat
# Multiple changes
chmod u+x,g+w,o-r file.txt
File Ownership with chown and chgrp
# Change file owner
sudo chown john file.txt
# Change owner and group
sudo chown john:developers file.txt
# Change only group
sudo chown :developers file.txt
# or
sudo chgrp developers file.txt
# Recursive ownership change
sudo chown -R www-data:www-data /var/www/html
# Copy ownership from another file
sudo chown --reference=template.txt target.txt
Advanced Linux Permissions and Special Bits
Special Permission Bits
SUID (Set User ID)
Executes file with owner’s privileges:
# Set SUID
chmod u+s /usr/local/bin/program
# or
chmod 4755 /usr/local/bin/program
# Find SUID files
find / -perm -4000 -type f 2>/dev/null
SGID (Set Group ID)
Files execute with group privileges. Directories inherit group ownership:
# Set SGID on directory
chmod g+s /shared/folder
# or
chmod 2775 /shared/folder
# Find SGID files
find / -perm -2000 -type f 2>/dev/null
Sticky Bit
Only file owner can delete files in directory:
# Set sticky bit
chmod +t /tmp
# or
chmod 1777 /tmp
# Verify sticky bit
ls -ld /tmp
# drwxrwxrwt 10 root root 4096 Jan 15 10:30 /tmp
Default Permissions with umask
The umask determines default permissions for new files:
# View current umask
umask
# Set umask (removes permissions)
umask 022 # Default: 755 for directories, 644 for files
umask 027 # Secure: 750 for directories, 640 for files
# Set permanently for user
echo "umask 027" >> ~/.bashrc
# Set system-wide
echo "umask 027" >> /etc/profile
Umask calculation:
- Maximum permissions: 777 (directories), 666 (files)
- Subtract umask value to get default permissions
- Example: 666 – 022 = 644 for files
Access Control Lists (ACLs) in Linux
When and Why to Use ACLs
ACLs provide fine-grained permissions beyond traditional Unix permissions. Use ACLs when:
- Multiple users need different access levels
- Traditional permissions are too restrictive
- Temporary access is required
Check ACL Support
# Verify filesystem supports ACLs
mount | grep acl
# Install ACL tools
sudo apt-get install acl # Debian/Ubuntu
sudo yum install acl # RHEL/CentOS
Managing ACLs
Setting ACLs with setfacl
# Grant user specific permissions
setfacl -m u:john:rwx file.txt
# Grant group permissions
setfacl -m g:developers:rx file.txt
# Set default ACL on directory
setfacl -d -m u:alice:rwx /shared/folder
# Remove specific ACL entry
setfacl -x u:john file.txt
# Remove all ACLs
setfacl -b file.txt
# Copy ACLs from one file to another
getfacl file1.txt | setfacl --set-file=- file2.txt
Viewing ACLs with getfacl
# View ACLs
getfacl file.txt
# View ACLs recursively
getfacl -R /shared/folder
# Backup ACLs
getfacl -R /data > acl_backup.txt
# Restore ACLs
setfacl --restore=acl_backup.txt
ACL Examples
# Create shared project directory
sudo mkdir /projects/webapp
sudo chgrp developers /projects/webapp
sudo chmod 2770 /projects/webapp
# Set default ACLs for new files
setfacl -d -m u::rwx /projects/webapp
setfacl -d -m g::rwx /projects/webapp
setfacl -d -m o::--- /projects/webapp
# Grant specific user read access
setfacl -m u:auditor:rx /projects/webapp
# Grant temporary access
setfacl -m u:contractor:rwx /projects/webapp
# Later remove it
setfacl -x u:contractor /projects/webapp
Sudo Configuration and Privilege Escalation
Configuring sudo Access
Understanding /etc/sudoers
Always edit sudoers using visudo:
# Edit sudoers file
sudo visudo
# Check syntax without editing
sudo visudo -c
Basic sudoers Syntax
# User privilege specification
username ALL=(ALL:ALL) ALL
# Allow user to run specific commands
john ALL=(ALL) /usr/bin/systemctl, /usr/bin/journalctl
# Allow group
%admin ALL=(ALL) ALL
# No password required
alice ALL=(ALL) NOPASSWD: ALL
# Specific host and commands
bob workstation=(root) /sbin/shutdown, /sbin/reboot
Creating sudoers.d Entries
# Create dedicated file
sudo visudo -f /etc/sudoers.d/developers
# Content example:
# Allow developers group to manage services
%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx
%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl status nginx
Advanced sudo Techniques
Command Aliases
# Define command aliases in sudoers
Cmnd_Alias SERVICES = /usr/bin/systemctl start *, \
/usr/bin/systemctl stop *, \
/usr/bin/systemctl restart *
Cmnd_Alias NETWORKING = /sbin/ifconfig, /sbin/route, \
/bin/ping, /sbin/iptables
# Use aliases
%netadmins ALL=(ALL) NETWORKING
%sysadmins ALL=(ALL) SERVICES
User and Host Aliases
# User aliases
User_Alias ADMINS = john, jane, bob
User_Alias DBADMINS = alice, charlie
# Host aliases
Host_Alias WEBSERVERS = web01, web02, web03
Host_Alias DBSERVERS = db01, db02
# Combine aliases
ADMINS ALL=(ALL) ALL
DBADMINS DBSERVERS=(postgres) ALL
Logging sudo Commands
# Enable sudo logging in sudoers
Defaults logfile="/var/log/sudo.log"
Defaults log_input
Defaults log_output
# View sudo logs
sudo cat /var/log/sudo.log
sudo journalctl -u sudo
Password Policies and Security Hardening
Implementing Password Policies
Password Aging with chage
# View password aging information
sudo chage -l username
# Set password expiration
sudo chage -M 90 username # Maximum 90 days
# Set minimum days between changes
sudo chage -m 7 username
# Set warning days
sudo chage -W 14 username
# Force password change on next login
sudo chage -d 0 username
# Set account expiration date
sudo chage -E 2024-12-31 username
# Interactive mode
sudo chage username
PAM Password Quality
Install and configure password quality tools:
# Install password quality library
sudo apt-get install libpam-pwquality # Debian/Ubuntu
sudo yum install pam_pwquality # RHEL/CentOS
# Configure /etc/security/pwquality.conf
minlen = 12
dcredit = -1 # Require digit
ucredit = -1 # Require uppercase
lcredit = -1 # Require lowercase
ocredit = -1 # Require special character
minclass = 3 # Require 3 character classes
Account Lockout Policy
Configure PAM to lock accounts after failed attempts:
# Edit /etc/pam.d/common-auth (Debian/Ubuntu)
auth required pam_tally2.so deny=5 unlock_time=1800
# Reset failed login counter
sudo pam_tally2 --user=username --reset
Security Best Practices
Disable Unnecessary Accounts
# Lock system accounts
sudo passwd -l daemon
sudo passwd -l bin
sudo passwd -l sys
# Find accounts with no password
sudo awk -F: '($2 == "" || $2 == "!" || $2 == "*") {print $1}' /etc/shadow
# Find accounts with UID 0 (root privileges)
awk -F: '($3 == 0) {print $1}' /etc/passwd
Monitor User Activity
# Last login information
last
lastlog
# Currently logged in users
who
w
# User command history
sudo cat /home/username/.bash_history
# Failed login attempts
sudo grep "Failed password" /var/log/auth.log
sudo aureport -au # If using auditd
User Environment and Profile Management
Shell Configuration Files
Understanding initialization file hierarchy:
- /etc/profile: System-wide login shell settings
- /etc/bash.bashrc: System-wide bash settings
- ~/.profile: User login shell settings
- ~/.bashrc: User bash-specific settings
- ~/.bash_profile: User bash login settings
Setting Environment Variables
# System-wide environment variable
echo "export JAVA_HOME=/usr/lib/jvm/java-11" >> /etc/profile
# User-specific environment variable
echo "export PATH=$PATH:/home/user/bin" >> ~/.bashrc
# Temporary environment variable
export TEMP_VAR="value"
# View all environment variables
env
printenv
Custom User Environment
# Create default files for new users
sudo mkdir -p /etc/skel/.config
sudo cp custom_bashrc /etc/skel/.bashrc
# Set custom prompt
echo 'PS1="\u@\h:\w\$ "' >> ~/.bashrc
# Add aliases
cat >> ~/.bashrc << 'EOF'
alias ll='ls -la'
alias gs='git status'
alias dc='docker-compose'
EOF
# Apply changes
source ~/.bashrc
Resource Limits
Configure limits.conf
# Edit /etc/security/limits.conf
# Format: domain type item value
# User limits
john soft nproc 1000
john hard nproc 2000
john soft nofile 4096
john hard nofile 8192
# Group limits
@developers soft nproc 2000
@developers hard nproc 4000
# All users
* soft core 0
* hard core 0
Set User Quotas
# Install quota tools
sudo apt-get install quota
# Enable quotas on filesystem (edit /etc/fstab)
/dev/sda1 /home ext4 defaults,usrquota,grpquota 0 2
# Remount filesystem
sudo mount -o remount /home
# Create quota database
sudo quotacheck -cug /home
# Enable quotas
sudo quotaon /home
# Set user quota
sudo setquota -u username 100M 200M 0 0 /home
# View quota report
sudo repquota -a
Troubleshooting Common Permission Issues in Linux
Diagnostic Commands and Tools
Essential Diagnostic Commands
# Check file permissions and ownership
ls -la file.txt
stat file.txt
# Check user identity and groups
id
whoami
groups
# Check effective permissions
namei -l /path/to/file
# Test file access
test -r file.txt && echo "Readable" || echo "Not readable"
test -w file.txt && echo "Writable" || echo "Not writable"
test -x file.txt && echo "Executable" || echo "Not executable"
# Find files with specific permissions
find /path -perm 777 -type f
find /path -user username
find /path -group groupname
Common Problems and Solutions
Permission Denied Errors
Problem: Cannot access file despite being owner:
# Check for immutable attribute
lsattr file.txt
# Remove immutable attribute if set
sudo chattr -i file.txt
Problem: Cannot execute script:
# Add execute permission
chmod +x script.sh
# Check shebang line
head -1 script.sh
# Verify interpreter exists
which bash
Group Membership Not Working
Problem: Added to group but permissions not working:
# Logout and login, or use:
newgrp groupname
# Verify group membership
groups
# Check group ID
id -Gn
Web Server Permission Issues
# Standard web directory permissions
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# For upload directories
sudo chmod 775 /var/www/html/uploads
sudo chown www-data:developers /var/www/html/uploads
SSH Key Permissions
# Fix SSH directory permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 600 ~/.ssh/authorized_keys
chmod 644 ~/.ssh/id_rsa.pub
Automation and Scripting User Management
Shell Scripts for User Management
Automated User Provisioning Script
#!/bin/bash
# provision_user.sh
create_user() {
local username=$1
local fullname=$2
local groups=$3
# Check if user exists
if id "$username" &>/dev/null; then
echo "User $username already exists"
return 1
fi
# Create user
sudo useradd -m -c "$fullname" -s /bin/bash "$username"
# Set temporary password
echo "$username:ChangeMe123!" | sudo chpasswd
# Force password change on first login
sudo chage -d 0 "$username"
# Add to groups
if [ -n "$groups" ]; then
sudo usermod -aG "$groups" "$username"
fi
# Create SSH directory
sudo -u "$username" mkdir -p /home/"$username"/.ssh
sudo chmod 700 /home/"$username"/.ssh
echo "User $username created successfully"
}
# Usage
create_user "john" "John Doe" "developers,docker"
Bulk Permission Change Script
#!/bin/bash
# fix_permissions.sh
fix_directory_permissions() {
local dir=$1
local dir_perms=${2:-755}
local file_perms=${3:-644}
echo "Fixing permissions in $dir"
# Set directory permissions
find "$dir" -type d -exec chmod "$dir_perms" {} \;
# Set file permissions
find "$dir" -type f -exec chmod "$file_perms" {} \;
echo "Permissions fixed"
}
# Usage
fix_directory_permissions "/var/www/html" 755 644
User Audit Script
#!/bin/bash
# audit_users.sh
echo "User Audit Report - $(date)"
echo "================================"
# List users with UID >= 1000 (regular users)
echo -e "\nRegular Users:"
awk -F: '$3 >= 1000 {print $1 " (UID: " $3 ")"}' /etc/passwd
# Find users with no password expiry
echo -e "\nUsers with no password expiry:"
for user in $(awk -F: '$3 >= 1000 {print $1}' /etc/passwd); do
chage -l "$user" | grep -q "Password expires.*never" && echo "$user"
done
# Find users with sudo access
echo -e "\nUsers with sudo access:"
grep -Po '^[^#]*\K^[^:]+' /etc/group | grep sudo
# Last login information
echo -e "\nLast login times:"
lastlog | grep -v "Never logged in"
Configuration Management Tools
Ansible User Management
# ansible_users.yml
---
- name: Manage Linux users
hosts: all
become: yes
vars:
users:
- name: john
groups: ['developers', 'docker']
shell: /bin/bash
password: "{{ 'password123' | password_hash('sha512') }}"
- name: jane
groups: ['admins']
shell: /bin/zsh
tasks:
- name: Create users
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: "{{ item.shell }}"
password: "{{ item.password }}"
create_home: yes
state: present
loop: "{{ users }}"
- name: Add SSH keys
authorized_key:
user: "{{ item.name }}"
key: "{{ lookup('file', 'keys/{{ item.name }}.pub') }}"
state: present
loop: "{{ users }}"
Best Practices and Enterprise Considerations
Security Guidelines
Principle of Least Privilege
- Grant minimum permissions required for tasks
- Use groups for role-based access
- Regular permission audits
- Document permission changes
# Example least privilege setup
# Create role-based groups
sudo groupadd web-developers
sudo groupadd database-admins
sudo groupadd deployment-users
# Assign specific permissions
sudo setfacl -R -m g:web-developers:rwx /var/www/dev
sudo setfacl -R -m g:database-admins:r-x /var/lib/mysql
sudo setfacl -R -m g:deployment-users:r-x /opt/applications
Regular User Audits
# Schedule regular audits with cron
# Add to root's crontab
0 2 * * 1 /usr/local/bin/audit_users.sh > /var/log/user_audit.log 2>&1
# Check for inactive users
lastlog -b 90 # Users inactive for 90+ days
# Review sudo usage
sudo grep sudo /var/log/auth.log | tail -50
Compliance and Auditing
Audit Configuration with auditd
# Install auditd
sudo apt-get install auditd
# Monitor user/group changes
sudo auditctl -w /etc/passwd -p wa -k passwd_changes
sudo auditctl -w /etc/shadow -p wa -k shadow_changes
sudo auditctl -w /etc/group -p wa -k group_changes
# Monitor sudo commands
sudo auditctl -w /usr/bin/sudo -p x -k sudo_commands
# View audit logs
sudo aureport -au # Authentication report
sudo aureport -m # Modifications report
sudo ausearch -k passwd_changes # Search specific events
Quick Reference and Cheat Sheet
Essential Commands Quick Reference
| Task | Command |
|---|---|
| Create user | sudo useradd -m username |
| Delete user | sudo userdel -r username |
| Change password | sudo passwd username |
| Add to group | sudo usermod -aG groupname username |
| Create group | sudo groupadd groupname |
| Change permissions | chmod 755 filename |
| Change ownership | sudo chown user:group filename |
| Set ACL | setfacl -m u:username:rwx filename |
| View permissions | ls -la filename |
| Check user info | id username |
Common Permission Combinations
| Numeric | Symbolic | Use Case |
|---|---|---|
| 755 | rwxr-xr-x | Executable files, directories |
| 644 | rw-r–r– | Regular files |
| 600 | rw——- | Private files |
| 700 | rwx—— | Private directories |
| 775 | rwxrwxr-x | Shared directories |
| 664 | rw-rw-r– | Shared files |
Troubleshooting Flowchart
- Permission Denied?
- Check file ownership:
ls -la - Check user groups:
groups - Check ACLs:
getfacl filename - Check parent directory permissions
- Check file ownership:
- Cannot Execute?
- Check execute bit:
ls -la - Verify shebang:
head -1 script - Check interpreter:
which interpreter
- Check execute bit:
- Group Permissions Not Working?
- Verify group membership:
id username - Re-login or use:
newgrp groupname - Check primary vs supplementary groups
- Verify group membership:
Conclusion and Next Steps
This guide covered essential Linux user management and permission concepts. You learned how to:
- Create and manage users and groups effectively
- Configure file permissions and ownership
- Implement ACLs for fine-grained access control
- Set up sudo access and privilege escalation
- Automate user provisioning with scripts
- Troubleshoot common permission issues
Next Steps for Learning
- Practice in a lab environment: Set up a virtual machine to test commands safely
- Implement automation: Create scripts for your common tasks
- Study advanced topics:
- SELinux/AppArmor for mandatory access control
- LDAP/Active Directory integration
- Kerberos authentication
- PAM module configuration
- Security certifications: Consider Linux+ or RHCSA certification
Remember: Always test permission changes in a development environment before applying them to production systems. Document all changes and maintain regular backups.
If you have MikroTik network equipment, feel free to check our list of MikroTik guides.