sudo โ Superuser Do โ is the standard mechanism for granting
controlled, audited, elevated privileges on Linux. Rather than sharing the
root password or running services as root, sudo lets specific
users run specific commands as root (or any other user), with every action
logged to syslog and the audit trail.
Properly configured sudo is the
difference between "everyone knows the root password" and a system where
every privileged action is attributed to a named person and can be reviewed.
This page covers sudoers syntax, best practices, and the principle of
least privilege in practice.
Fields: WHO (user or %group) ยท WHERE (hostname, usually ALL) ยท
AS WHOM (runas user) ยท WHAT (command or ALL)
# Run a single command as root sudo dnf update sudo systemctl restart nginx sudo vi /etc/hosts # Run as a specific user (not root) sudo -u postgres psql sudo -u www-data php artisan migrate # Get an interactive root shell sudo -i # login shell โ loads root's environment sudo -s # non-login shell โ keeps current environment sudo su - # equivalent to sudo -i # Run a command with root's environment sudo -H vi /etc/nginx/nginx.conf # List what sudo you are allowed to run sudo -l sudo -l -U alice # check another user's sudo rights (as root) # Reset sudo timestamp (re-prompt for password next time) sudo -k # Extend sudo timeout without running a command sudo -v
sudo -l to see exactly what commands
you are permitted to run. It shows the full effective policy for
your account.
# ALWAYS use visudo โ never edit /etc/sudoers directly sudo visudo # visudo validates syntax before saving # A syntax error in /etc/sudoers can lock out all sudo access # Edit a specific drop-in file (preferred method) sudo visudo -f /etc/sudoers.d/webteam # Check syntax of a sudoers file without applying sudo visudo -c -f /etc/sudoers.d/webteam # List all sudoers files ls -la /etc/sudoers.d/
visudo validates syntax
before saving โ use it, always. If you must edit directly, keep a
root shell open as a safety net.
/etc/sudoers.d/ โ one per team or role. They are
automatically included. Easier to manage, easier to audit,
and a syntax error in one drop-in doesn't affect the others.
# /etc/sudoers.d/admins โ full admin access %wheel ALL=(ALL) ALL %admins ALL=(ALL) ALL # /etc/sudoers.d/webteam โ web team, specific commands only %webteam ALL=(root) NOPASSWD: \ /usr/bin/systemctl restart nginx, \ /usr/bin/systemctl reload nginx, \ /usr/bin/systemctl status nginx # /etc/sudoers.d/dbadmins โ database team %dbadmins ALL=(root) NOPASSWD: \ /usr/bin/systemctl restart postgresql, \ /usr/bin/systemctl restart mysqld %dbadmins ALL=(postgres) NOPASSWD: /usr/bin/psql # /etc/sudoers.d/monitoring โ read-only monitoring monitoring ALL=(root) NOPASSWD: \ /usr/bin/journalctl, \ /usr/bin/ss, \ /usr/bin/df, \ /usr/bin/top, \ /usr/bin/ps # Allow a user to edit specific files with sudoedit alice ALL=(root) sudoedit /etc/nginx/conf.d/*.conf # Command alias โ group commands under a name Cmnd_Alias SERVICES = /usr/bin/systemctl start *, \ /usr/bin/systemctl stop *, \ /usr/bin/systemctl restart * %sysadmin ALL=(root) SERVICES
NOPASSWD removes
the password prompt for that command. Good for service accounts and
automation scripts. Avoid it for interactive admin commands โ the
password prompt is a speed bump that makes accidental misuse less likely.
### RHEL / Rocky / AlmaLinux โ uses wheel group ### # Add user to wheel group sudo usermod -aG wheel alice # Verify wheel is enabled in sudoers (should be uncommented) grep wheel /etc/sudoers # Should show: %wheel ALL=(ALL) ALL # Remove from wheel group sudo gpasswd -d alice wheel ### Debian / Ubuntu โ uses sudo group ### # Add user to sudo group sudo usermod -aG sudo alice # Verify grep sudo /etc/sudoers # Should show: %sudo ALL=(ALL:ALL) ALL # On either system โ verify user's sudo access sudo -l -U alice su - alice -c "sudo -l"
wheel as the admin group. Debian/Ubuntu use
sudo. Both are configured in sudoers to allow full
root access. The group name is the only difference โ the concept
is identical.
# Every sudo command is logged โ view with journalctl sudo journalctl -t sudo sudo journalctl -t sudo --since today sudo journalctl -t sudo -n 50 # On systems with /var/log/secure or /var/log/auth.log sudo grep sudo /var/log/secure | tail -20 # RHEL sudo grep sudo /var/log/auth.log | tail -20 # Debian/Ubuntu # See who ran what sudo commands sudo journalctl -t sudo | grep "COMMAND" | tail -20 # Enhanced logging โ add to sudoers for detailed logs sudo visudo # Add these lines: # Defaults logfile=/var/log/sudo.log # Defaults log_input, log_output # Defaults iolog_dir=/var/log/sudo-io/%{user}journalctl sudo output example:
sudoedit (or sudo -e) lets a user edit a
privileged file safely โ it copies the file to a temp location, opens
it in the user's own editor, then copies it back. No root shell involved:
# User edits /etc/nginx/nginx.conf without getting a root shell sudoedit /etc/nginx/nginx.conf sudo -e /etc/nginx/nginx.conf # same thing # Grant sudoedit permission in sudoers (safer than NOPASSWD: /usr/bin/vi) # In /etc/sudoers.d/webteam: # alice ALL=(root) sudoedit /etc/nginx/conf.d/*.conf # sudoedit respects the user's EDITOR/VISUAL environment variable export EDITOR=vim sudoedit /etc/hosts
NOPASSWD: /usr/bin/vi
in sudoers โ a user with root vi access can run :!/bin/bash
from inside vi and get a root shell. sudoedit avoids
this entirely โ the editor runs as the user, not as root.
This is the correct way to grant file editing privileges.
# Useful Defaults settings to add to sudoers
sudo visudo
# Require password re-entry after 5 minutes (default is 15) Defaults timestamp_timeout=5 # Require password even for NOPASSWD commands when session is new Defaults timestamp_type=tty # Log all sudo commands to a dedicated file Defaults logfile=/var/log/sudo.log # Send mail on sudo failures (bad password etc.) Defaults mailto=sysadmin@example.com Defaults mail_badpass # Prevent environment variable injection attacks Defaults env_reset Defaults env_keep += "LANG LC_ALL LC_MESSAGES LC_CTYPE LC_COLLATE LC_TIME" # Secure PATH โ use only known-good directories Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" # Show a lecture to new sudo users Defaults lecture=always Defaults lecture_file=/etc/sudo_lecture
ALL unless they
are a full sysadmin. A developer who needs to restart their
application service should get exactly that:
NOPASSWD: /usr/bin/systemctl restart myapp โ
not full root.
# su โ switch user (requires target user's password) su alice # switch to alice, keep environment su - alice # switch to alice, load her full environment su - # switch to root (requires root password) # sudo su โ use sudo to become another user without their password sudo su - alice # become alice (requires YOUR sudo password) sudo -u alice -i # equivalent โ open alice's login shell sudo -u postgres psql # run a command as postgres user # runuser โ run a command as another user (root only, no PAM) sudo runuser -l postgres -c "pg_dump mydb > /backup/mydb.sql" sudo runuser -u www-data -- php artisan queue:work # Check who you are after switching id whoami # Exit back to original user exit # or Ctrl-D
| Command | Password needed | Environment | Logged? |
|---|---|---|---|
| su - alice | Alice's password | Alice's full env | Partially |
| sudo -u alice -i | Your sudo password | Alice's full env | Yes โ fully |
| sudo -i | Your sudo password | Root's full env | Yes โ fully |
| sudo -s | Your sudo password | Current env | Yes โ fully |
| runuser -l user | None (root only) | User's full env | Yes |
sudo logs every
action with your username attached. su - to root logs
the switch but not what you did afterward โ the audit trail stops.
On a well-managed system, the root password should be unknown to
everyone and all privileged work done via sudo.
| Command | What it does |
|---|---|
| sudo COMMAND | Run command as root |
| sudo -u USER COMMAND | Run command as specific user |
| sudo -i | Interactive root login shell |
| sudo -l | List your sudo permissions |
| sudo -l -U user | List another user's sudo permissions |
| sudo -k | Invalidate sudo timestamp (force re-auth) |
| sudo -v | Extend sudo timeout |
| sudo visudo | Edit sudoers safely with syntax check |
| sudo visudo -f /etc/sudoers.d/file | Edit a drop-in sudoers file |
| sudo visudo -c -f file | Check sudoers file syntax only |
| sudoedit FILE | Edit privileged file safely (no root shell) |
| sudo usermod -aG wheel user | Add user to wheel (RHEL admin group) |
| sudo usermod -aG sudo user | Add user to sudo (Debian admin group) |
| journalctl -t sudo | View all sudo log entries |
| sudo runuser -l user -c CMD | Run command as user (no PAM) |
| Rule | Effect |
|---|---|
| alice ALL=(ALL) ALL | alice has full root access everywhere |
| %wheel ALL=(ALL) ALL | wheel group has full root access |
| alice ALL=(root) /usr/bin/systemctl | alice can only run systemctl as root |
| alice ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx | No password needed for this specific command |
| alice ALL=(postgres) /usr/bin/psql | alice can run psql as postgres user |
| alice ALL=(root) sudoedit /etc/nginx/conf.d/*.conf | Safe file editing with wildcards |
| Defaults timestamp_timeout=5 | Re-prompt after 5 minutes |
| Defaults logfile=/var/log/sudo.log | Log all sudo to dedicated file |