sudoers Configuration Basics - Delegating Privileges Safely
What is /etc/sudoers?
/etc/sudoers defines who can run what as whom — it controls all privilege delegation for the sudo command. Never edit it directly; always use visudo.
Quick Summary
- Only edit sudoers via
visudo(syntax errors with direct editing can lock you out of sudo entirely) - Restrict permissions to specific commands whenever possible (
ALLis a last resort) - Use NOPASSWD only for CI/CD pipelines and trusted automation
Target Environment
- OS: Ubuntu 22.04 / 24.04 (applies to Debian-based distros in general)
- sudo must be installed (installed by default)
Why must you use visudo?
visudo is an editor wrapper with syntax validation — it checks for errors before saving and refuses to write a broken file. This prevents sudo from being locked in a broken state.
$ sudo visudo
On Ubuntu, the default editor is nano. Override it with the EDITOR variable:
$ sudo EDITOR=vim visudo
Editing with sudo vi /etc/sudoers or sudo nano /etc/sudoers directly bypasses all safety checks. A syntax error saved this way completely disables sudo. Recovery requires root shell access (or a live rescue environment if the root password is not set).
sudoers Syntax
Basic form
user host=(run-as) command
The most common example:
alice ALL=(ALL:ALL) ALL
What each field means:
| Field | Example | Meaning |
|---|---|---|
| User | alice |
Who this rule applies to |
| Host | ALL |
Valid on all hosts |
| Run-as | (ALL:ALL) |
May run as any user/group including root |
| Command | ALL |
All commands |
Group delegation
Prefix with % to specify a group:
%sudo ALL=(ALL:ALL) ALL %wheel ALL=(ALL) ALL
On Ubuntu, the %sudo group gets sudo access by convention. On CentOS/RHEL, it is %wheel.
Restricting to Specific Commands
Listing only the commands you actually need is the safest approach.
# Allow only nginx restart bob ALL=(root) /usr/bin/systemctl restart nginx # Multiple commands, comma-separated carol ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx
Commands must be written as full absolute paths (check with which nginx).
Granting access to editors like /usr/bin/vim is effectively full root access — a user can escape to a shell with :!sh. Editors should never be in sudoers.
NOPASSWD Configuration
Allows running commands without entering a password. Common in CI/CD pipelines and deploy scripts.
# NOPASSWD for a specific command only deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp # NOPASSWD for an entire group (use with caution) %automation ALL=(ALL) NOPASSWD: ALL
NOPASSWD risks
- If a script is compromised, root commands run without any password prompt
- Always scope to specific commands.
NOPASSWD: ALLshould be rare and well-justified - Monitor sudo usage in
/var/log/auth.log
The sudoers.d Include Directory (Recommended)
For multi-service or multi-team environments, drop individual rule files into /etc/sudoers.d/ instead of editing the main file.
# Create a new file with syntax checking $ sudo visudo -f /etc/sudoers.d/deploy-user
Example file content:
# /etc/sudoers.d/deploy-user deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp, /usr/bin/systemctl status myapp
The main /etc/sudoers ends with #includedir /etc/sudoers.d, which auto-loads all files there. Files must be owned by root:root with mode 0440 or they are silently ignored.
$ sudo chmod 0440 /etc/sudoers.d/deploy-user $ sudo chown root:root /etc/sudoers.d/deploy-user
Checking and Testing Permissions
List your own sudo permissions
$ sudo -l
User alice may run the following commands on server:
(ALL : ALL) ALLRun a command as another user
$ sudo -u www-data whoami www-data
Check another user's permissions without running anything
$ sudo -l -U bob
Tuning Behavior with Defaults
The Defaults entry changes sudo's default behavior globally or per user.
# Require password every time (disable caching) Defaults timestamp_timeout=0 # Do not inherit the user's PATH (default — safe) Defaults env_reset # Apply only to a specific user Defaults:bob timestamp_timeout=5
| Option | Meaning |
|---|---|
timestamp_timeout=N |
Credential cache lifetime in minutes. 0 = always prompt |
env_reset |
Reset environment variables (enabled by default) |
logfile=/var/log/sudo.log |
Write sudo activity to a dedicated log file |
passwd_tries=N |
Password attempt limit (default 3) |
Common Mistakes and Fixes
"sudo: /etc/sudoers is world writable"
$ sudo chmod 0440 /etc/sudoers
The file must be readable only by root (0440).
Changes not taking effect after visudo
- Run
sudo -kto clear the credential cache, then retry - After adding a user to the sudo group, they must log out and back in (or run
newgrp sudo)
"sudo: command not found" for a known binary
env_reset strips the PATH. Make sure the command's directory is in secure_path:
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"