sudoers Done Safely
Introduction¶
sudo grants specific elevated privileges without sharing the root password.
The rules live in /etc/sudoers and /etc/sudoers.d/. A syntax error there can
break sudo for everyone, so always edit with visudo — it validates
before saving.
Editing¶
sudo visudo # /etc/sudoers
sudo visudo -f /etc/sudoers.d/deploy # a drop-in (preferred)
Prefer drop-in files in /etc/sudoers.d/ — they survive package upgrades and
are easy to manage with config management. The file must not have a .
or ~ in the name and should be mode 0440.
Rule syntax¶
user host = (runas_user:runas_group) [tags]: command [, command ...]
# alice can run anything as root, with a password
alice ALL = (ALL:ALL) ALL
# the deploy user can restart one service without a password
deploy ALL = (root) NOPASSWD: /usr/bin/systemctl restart myapp.service
# members of group ops can run a specific set
%ops ALL = (root) /usr/bin/systemctl, /usr/bin/journalctl
# run as a non-root service account
ci ALL = (appuser) NOPASSWD: /usr/local/bin/deploy.sh
%group for a group. ALL in the host field matters when one sudoers file is
shared across machines.
Aliases¶
Cmnd_Alias SERVICES = /usr/bin/systemctl start *, /usr/bin/systemctl stop *, \
/usr/bin/systemctl restart *, /usr/bin/systemctl status *
User_Alias ADMINS = alice, bob, %sre
Host_Alias WEB = web01, web02, web03
ADMINS WEB = (root) SERVICES
The wildcard trap¶
# LOOKS narrow, IS full root:
deploy ALL = (root) NOPASSWD: /usr/bin/systemctl restart myapp*
myapp* matches myapp.service — and also myapp.service; rm -rf / is not
how it works (sudo doesn't invoke a shell), but:
deploy ALL = (root) /bin/chmod * # chmod any file, any mode -> trivially root
deploy ALL = (root) /usr/bin/find * # find has -exec -> arbitrary command
deploy ALL = (root) /usr/bin/vim /etc/myapp.conf # vim has :!sh -> root shell
deploy ALL = (root) /usr/bin/less /var/log/x # less can spawn a shell
deploy ALL = (root) /usr/bin/tar * # --checkpoint-action=exec -> root
Rules of thumb:
- No wildcards in arguments unless you've thought hard about it. Enumerate exact commands.
- No editors, pagers,
find,tar,awk,sed -ion arbitrary paths, language interpreters, orsystemctlwithout a specific unit — they all have shell-escape or arbitrary-write paths. - To let someone edit a file as root, use
sudoedit(sudo -e), notsudo vim— it copies the file, lets the user edit as themselves, then copies back.deploy ALL = (root) sudoedit /etc/myapp/config.yaml
Useful defaults¶
Defaults env_reset, timestamp_timeout=15
Defaults logfile="/var/log/sudo.log"
Defaults lecture="once"
Defaults:ci !requiretty # allow sudo from a non-tty (CI) for user ci
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
env_reset (default) scrubs the environment; keep it. secure_path prevents a
planted binary earlier in $PATH from running as root.
Verification and troubleshooting¶
sudo -l # what can I run?
sudo -l -U deploy # what can deploy run? (as an admin)
sudo -ll # verbose form
visudo -c # check syntax of all sudoers files
sudo -k # forget the cached timestamp (re-prompt)
sudo: /etc/sudoers is world writable/syntax error— you edited withoutvisudoand broke it. Recover via a root shell (pkexec, single-user mode,su, a container/rescue), fix permschmod 0440,visudo -c.- Rule not taking effect — a later file or line matches first? sudo uses the
last matching rule. Order in
sudoers.dis by filename (C locale sort) — name files10-,20-to control it. sudo: no tty present and no askpass program specified— a script/CI running sudo interactively. UseNOPASSWDfor that specific command, orDefaults:user !requiretty+ an askpass.- NOPASSWD ignored — another matching rule without NOPASSWD comes later, or
the command path/args don't match exactly (absolute path required;
systemctlvs/usr/bin/systemctl). - User can escalate beyond the rule — you granted a command with a
shell-escape (see the trap section). Audit every granted binary for
!,-e,--exec,:sh. - Group change not recognised — sudo reads group membership at login; the
user needs a fresh session after being added to
%ops.
Related tools and reading¶
- On-site: Linux commands reference.
- Related posts: SSH server hardening, Linux permissions and ACLs.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Linux & Sysadmin
resolv.conf and systemd-resolved
On modern distros /etc/resolv.conf points at a stub resolver managed by systemd-resolved. Editing it directly usually does nothing — here's the real model.
October 24, 2026Tuning Open File Limits on Linux
Four different limits control how many files a process can open. 'Too many open files' means you're hitting one specific one — here's how to find and raise it.
October 24, 2026ss and conntrack for Connection Debugging
ss shows you every socket and its send/receive queues; conntrack shows what the firewall is tracking. Together they explain most 'connection refused' and 'no buffer space' problems.
October 24, 2026