Learn to create and manage Linux users and groups with proper sudo access control, security hardening, and monitoring. This comprehensive guide covers account creation, group membership management, sudo configuration, and security best practices for production environments.
Prerequisites
- Root or sudo access
- Basic Linux command line knowledge
- Understanding of file permissions
What this solves
Proper user and group management is fundamental to Linux security and system administration. This tutorial shows you how to create users, manage group memberships, configure sudo access with granular permissions, and implement security monitoring to maintain a secure multi-user environment.
Step-by-step configuration
Update system packages
Start by updating your package manager to ensure you have the latest security patches and user management tools.
sudo apt update && sudo apt upgrade -y
sudo apt install -y sudo passwd shadow-utils
Create user accounts with proper settings
Create users with home directories, shell access, and appropriate initial groups. The useradd command provides comprehensive user creation options.
# Create a standard user account
sudo useradd -m -s /bin/bash -c "John Developer" jdeveloper
Create a system service account (no home directory, no shell)
sudo useradd -r -s /usr/sbin/nologin -c "Application Service User" appuser
Create user with specific UID and primary group
sudo useradd -m -u 1500 -g users -s /bin/bash -c "Database Admin" dbadmin
Set initial passwords (will prompt for password)
sudo passwd jdeveloper
sudo passwd dbadmin
Create and manage groups
Create groups to organize users by function and simplify permission management. Groups enable you to assign permissions to multiple users efficiently.
# Create functional groups
sudo groupadd developers
sudo groupadd webadmins
sudo groupadd dbadmins
sudo groupadd monitoring
Create group with specific GID
sudo groupadd -g 2000 contractors
View all groups
cat /etc/group | grep -E "developers|webadmins|dbadmins|monitoring|contractors"
Add users to groups
Assign users to appropriate groups using usermod. Users can belong to multiple groups to inherit different sets of permissions.
# Add user to primary and secondary groups
sudo usermod -g developers -G webadmins,monitoring jdeveloper
sudo usermod -g dbadmins -G monitoring dbadmin
Add existing user to additional group (preserves existing groups)
sudo usermod -a -G sudo jdeveloper
Remove user from a group
sudo gpasswd -d jdeveloper webadmins
View user's group memberships
groups jdeveloper
id jdeveloper
Configure sudo access with granular permissions
Configure sudo to provide controlled administrative access. Use visudo to safely edit the sudoers file and prevent syntax errors that could lock you out.
# Always use visudo to edit sudo configuration
sudo visudo
Add these configurations to the sudoers file:
# Group-based sudo access
%developers ALL=(ALL:ALL) ALL
%webadmins ALL=(www-data) /usr/sbin/nginx, /bin/systemctl restart nginx, /bin/systemctl reload nginx
%dbadmins ALL=(postgres) /usr/bin/psql, /bin/systemctl restart postgresql, /usr/bin/pg_dump
%monitoring ALL=(ALL) NOPASSWD: /usr/bin/systemctl status *, /usr/bin/journalctl, /bin/ps aux
User-specific permissions
jdeveloper ALL=(ALL) /usr/bin/docker, /usr/bin/docker-compose
dbadmin ALL=(ALL) NOPASSWD: /usr/bin/mysqldump, /usr/bin/mysql
Restrict dangerous commands
%contractors ALL=(ALL) ALL, !/bin/su, !/usr/bin/passwd root, !/usr/bin/visudo
Command aliases for easier management
Cmnd_Alias WEBSERVER = /usr/sbin/nginx, /bin/systemctl restart nginx, /bin/systemctl reload nginx, /bin/systemctl status nginx
Cmnd_Alias MONITORING = /usr/bin/systemctl status *, /usr/bin/journalctl, /bin/ps aux, /usr/bin/top, /usr/bin/htop
%webadmins ALL=(www-data) WEBSERVER
%monitoring ALL=(ALL) NOPASSWD: MONITORING
Create sudo configuration drop-in files
Use separate configuration files in /etc/sudoers.d/ for better organization and easier management of sudo rules.
# Create directory if it doesn't exist
sudo mkdir -p /etc/sudoers.d
# Developers group sudo configuration
%developers ALL=(ALL:ALL) ALL
%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart docker, /usr/bin/systemctl status docker
Allow password-less sudo for docker commands
jdeveloper ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/docker-compose
# Web administrators sudo configuration
Cmnd_Alias WEBSERVER_CMDS = /usr/sbin/nginx, /bin/systemctl restart nginx, /bin/systemctl reload nginx, /bin/systemctl status nginx
Cmnd_Alias LOG_ACCESS = /usr/bin/tail /var/log/nginx/, /usr/bin/less /var/log/nginx/
%webadmins ALL=(www-data) WEBSERVER_CMDS
%webadmins ALL=(ALL) NOPASSWD: LOG_ACCESS
# Monitoring team sudo configuration
Cmnd_Alias MONITOR_CMDS = /usr/bin/systemctl status , /usr/bin/journalctl , /bin/ps aux, /usr/bin/top, /usr/bin/htop, /usr/bin/iotop
Cmnd_Alias LOG_READ = /usr/bin/tail /var/log/, /usr/bin/less /var/log/, /usr/bin/zcat /var/log/*
%monitoring ALL=(ALL) NOPASSWD: MONITOR_CMDS, LOG_READ
Set proper permissions on sudo configuration files:
sudo chmod 440 /etc/sudoers.d/*
sudo chown root:root /etc/sudoers.d/*
Configure password policies and account security
Implement password policies and account security settings to strengthen user account security.
sudo apt install -y libpam-pwquality
# Password quality requirements
minlen = 12
minclass = 3
maxrepeat = 2
maxclasschg = 0
maxsequence = 3
requpper = 1
reqlower = 1
reqdigit = 1
reqother = 1
dictcheck = 1
usercheck = 1
enforcing = 1
Configure account aging and login policies:
# Password aging controls
PASS_MAX_DAYS 90
PASS_MIN_DAYS 1
PASS_WARN_AGE 7
Account creation defaults
UID_MIN 1000
UID_MAX 60000
SYS_UID_MIN 201
SYS_UID_MAX 999
GID_MIN 1000
GID_MAX 60000
SYS_GID_MIN 201
SYS_GID_MAX 999
Home directory creation
CREATE_HOME yes
UMASK 022
Login timeout
LOGIN_TIMEOUT 60
Apply password policies to existing users:
# Set password expiration for specific users
sudo chage -M 90 -W 7 jdeveloper
sudo chage -M 90 -W 7 dbadmin
View password aging information
sudo chage -l jdeveloper
Configure user session limits
Set resource limits for users to prevent resource exhaustion and improve system stability. This is covered in detail in our Linux user session limits tutorial.
# User limits configuration
@developers soft nproc 100
@developers hard nproc 200
@developers soft nofile 1024
@developers hard nofile 2048
@webadmins soft nproc 50
@webadmins hard nproc 100
@webadmins soft nofile 1024
@webadmins hard nofile 4096
@monitoring soft nproc 200
@monitoring hard nproc 500
@monitoring soft nofile 2048
@monitoring hard nofile 8192
Prevent core dumps for contractors
@contractors hard core 0
Enable sudo logging and monitoring
Configure comprehensive logging for sudo activities to maintain security audit trails.
# Log all sudo activities
auth,authpriv.info /var/log/sudo.log
auth,authpriv.warning /var/log/sudo-warnings.log
Add sudo logging configuration to sudoers:
sudo visudo
Add these logging options:
# Sudo logging configuration
Defaults log_input,log_output
Defaults logfile=/var/log/sudo.log
Defaults log_year, loglinelen=0
Defaults timestamp_timeout=30
Defaults passwd_timeout=5
Defaults passwd_tries=3
Defaults insults
Restart rsyslog to apply logging changes:
sudo systemctl restart rsyslog
Set up security monitoring and alerts
Create scripts to monitor user activity and generate security alerts for suspicious behavior.
#!/bin/bash
User activity monitoring script
LOG_FILE="/var/log/user-activity.log"
ALERT_EMAIL="admin@example.com"
MAX_FAILED_LOGINS=5
TIME_WINDOW=300 # 5 minutes
Monitor failed login attempts
check_failed_logins() {
local current_time=$(date +%s)
local cutoff_time=$((current_time - TIME_WINDOW))
# Check failed logins in the last 5 minutes
failed_logins=$(journalctl --since "${TIME_WINDOW} seconds ago" -u ssh -p warning | grep -c "authentication failure")
if [ "$failed_logins" -gt "$MAX_FAILED_LOGINS" ]; then
echo "$(date): ALERT - $failed_logins failed login attempts in last 5 minutes" >> "$LOG_FILE"
echo "High number of failed login attempts detected: $failed_logins" | mail -s "Security Alert: Failed Logins" "$ALERT_EMAIL"
fi
}
Monitor sudo usage
check_sudo_activity() {
# Check for unusual sudo activity
sudo_count=$(journalctl --since "1 hour ago" | grep -c "sudo:")
if [ "$sudo_count" -gt 50 ]; then
echo "$(date): INFO - High sudo activity: $sudo_count commands in last hour" >> "$LOG_FILE"
fi
}
Monitor new user logins
check_new_logins() {
# Log current active sessions
who >> "$LOG_FILE"
# Check for root logins (should be rare)
root_logins=$(journalctl --since "1 hour ago" | grep -c "root.*session opened")
if [ "$root_logins" -gt 0 ]; then
echo "$(date): WARNING - Root login detected" >> "$LOG_FILE"
echo "Direct root login detected" | mail -s "Security Alert: Root Login" "$ALERT_EMAIL"
fi
}
Run checks
check_failed_logins
check_sudo_activity
check_new_logins
Make the monitoring script executable and set up automated execution:
sudo chmod +x /usr/local/bin/user-activity-monitor.sh
sudo chown root:root /usr/local/bin/user-activity-monitor.sh
Create a systemd timer for regular monitoring:
[Unit]
Description=User Activity Monitor
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/user-activity-monitor.sh
User=root
[Unit]
Description=Run User Activity Monitor every 5 minutes
Requires=user-activity-monitor.service
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the monitoring timer:
sudo systemctl daemon-reload
sudo systemctl enable --now user-activity-monitor.timer
sudo systemctl status user-activity-monitor.timer
Implement account lockout policies
Configure automatic account lockout after failed authentication attempts to prevent brute force attacks.
# Add account lockout after 3 failed attempts
auth required pam_tally2.so deny=3 unlock_time=900 audit even_deny_root
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
Check and unlock locked accounts:
# View locked accounts
sudo pam_tally2 --user jdeveloper
Unlock a specific user
sudo pam_tally2 --user jdeveloper --reset
View all users with failed attempts
sudo pam_tally2
Verify your setup
Test user creation, group membership, and sudo access to ensure everything works correctly:
# Verify user accounts
id jdeveloper
id dbadmin
groups jdeveloper
groups dbadmin
Test sudo access
sudo -l -U jdeveloper
sudo -l -U dbadmin
Check password policies
sudo chage -l jdeveloper
Verify group memberships
getent group developers
getent group webadmins
getent group monitoring
Test sudo functionality
sudo -u jdeveloper sudo -l
Check sudo logging
sudo tail -f /var/log/sudo.log
Verify monitoring timer
sudo systemctl status user-activity-monitor.timer
sudo journalctl -u user-activity-monitor.service
Security hardening best practices
Additional security measures to implement:
# Disable unused user accounts
sudo usermod -L olduser
sudo usermod -s /usr/sbin/nologin olduser
Remove users from sensitive groups
sudo gpasswd -d contractor_user sudo
Set proper home directory permissions
sudo chmod 750 /home/jdeveloper
sudo chmod 750 /home/dbadmin
Audit sudo access regularly
sudo grep -r "ALL=(ALL" /etc/sudoers*
For additional security hardening, consider implementing network security measures as described in our iptables security tutorial.
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| User can't sudo | Not in sudo group or sudoers | sudo usermod -a -G sudo username or add to sudoers |
| "sudo: command not found" | Sudo not installed | Install with package manager, add user to wheel group (RHEL/CentOS) |
| Syntax error in sudoers | Invalid sudoers syntax | Use sudo visudo always, check with visudo -c |
| Password policy not enforced | PAM not configured | Install libpam-pwquality, configure /etc/security/pwquality.conf |
| User locked after failed logins | PAM tally2 lockout | sudo pam_tally2 --user username --reset |
| Groups not taking effect | User needs to log out/in | Log out and back in, or use newgrp groupname |
| Home directory missing | Created user without -m flag | sudo mkhomedir_helper username or recreate with -m |
| Permission denied on files | Wrong ownership or permissions | Fix with chown user:group file and appropriate chmod |