Skip to main content
RunBook Academy

LinuxV · sudo and Privileged Accesssudoers

sudoers syntax — rules, aliases, and defaults

Intermediate⏱ ~12 minbashvisudosudo

What you'll learn

  • Read and write sudoers rules with the correct grammar
  • Use User_Alias, Runas_Alias, Host_Alias, and Cmnd_Alias
  • Apply Defaults selectively
  • Validate sudoers with visudo before saving

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09

Not yet marked complete on this device.

The sudoers file format is unusual: it is not a simple INI or YAML. It has its own grammar, its own reserved words, and rules about how to combine them. Mistakes are silent until production breaks.

The basic rule

A sudoers rule has the form:

WHO WHERE=(AS_WHOM) [NOPASSWD:] WHAT
FieldMeaning
WHOUser, group (with %), or User_Alias
WHEREHost, Host_Alias, or ALL
(AS_WHOM)Target user (default: root). Optional.
[NOPASSWD:]Skip the password prompt
WHATCommand, Cmnd_Alias, or ALL
Read-only / Safetwo rules per user
$ sudo -l -U alice
User alice may run the following commands on host01:
(ALL) ALL
(root) /usr/bin/systemctl status ssh, /usr/bin/systemctl restart ssh

Illustrative output

Aliases

For fleets, listing every user or every command in every file is unmaintainable. sudoers has four alias types:

User_Alias  OPS = alice, bob, carol
Runas_Alias APP = root, www-data
Host_Alias  PROD = host01, host02, host03
Cmnd_Alias  RESTART = /usr/bin/systemctl restart ssh, /usr/bin/systemctl restart nginx

OPS PROD = (APP) RESTART
AliasResolves to
User_AliasA list of users, groups (with %), or other User_Aliases
Runas_AliasA list of target users (root, %group, etc.)
Host_AliasA list of hosts, IPs, netgroups, or other Host_Aliases
Cmnd_AliasA list of commands, with optional arguments

Defaults

The Defaults directive sets options globally or per-rule:

Read-only / Safedefaults
$ sudo -l | head -10
Matching Defaults entries for alice on host01:
env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin, use_pty

User alice may run the following commands on host01:
...

Illustrative output

Common Defaults:

DefaultEffect
env_resetClear the user’s environment, set a clean one
secure_pathPATH the elevated command uses
use_ptyAllocate a pseudo-terminal for the command
log_input, log_outputLog stdin/stdout of elevated commands
iolog_dirWhere input/output logs are written
timestamp_timeout=0Always require re-authentication
timestamp_timeout=5Default — 5 minute grace
mail_badpassEmail root on bad password attempts
passwd_tries=3Three attempts before sudo gives up
insultsInsult the user on bad password (humorous, but rarely enabled)

Per-rule defaults

A Defaults can be scoped to a specific rule:

Defaults:ops !log_input, !log_output
ops ALL=(ALL) ALL

The Defaults line applies only to the rules that match the user list ops.

Least privilege: enumerate positively

Write the commands you intend to permit, one at a time, with absolute paths. Never start from ALL and carve pieces out.

Cmnd_Alias SSH_OPS = /usr/bin/systemctl restart ssh, \
                     /usr/bin/systemctl status ssh
alice ALL=(root) SSH_OPS

This is the only model that actually constrains what alice can do, because sudo grants exactly what is listed and nothing else. Every addition is a deliberate, reviewable line.

Last match wins

sudo does not stop at the first matching rule. It evaluates every entry that matches and applies the last one.

%ops ALL=(ALL) !/usr/bin/su      # intended as a deny
%ops ALL=(ALL) ALL               # this wins - the deny above is dead

Negation and exceptions

The ! operator removes a command from a list:

alice ALL=(ALL) ALL, !/usr/bin/sudo, !/usr/bin/su

Read literally, this allows alice to run anything except sudo and su. It parses cleanly. It is also not a security control.

Editing sudoers safely

Configuration changevisudo -c
$ sudo visudo -c -f /etc/sudoers.d/myapp
/etc/sudoers.d/myapp: parsed OK

Illustrative output

Drop-in files

Place service-specific rules in /etc/sudoers.d/<name>. Each file must be owned by root, mode 0440. Files are parsed in lexical order; place general rules early, specific rules late.

Read-only / Safedrop-in files
$ ls -l /etc/sudoers.d/
-r--r----- 1 root root  450 Aug  9 11:11 /etc/sudoers.d/myapp
-r--r----- 1 root root  270 Aug  9 11:11 /etc/sudoers.d/operators
-r--r----- 1 root root  180 Aug  9 11:11 /etc/sudoers.d/breakglass

Illustrative output

Knowledge check

Knowledge check · 5 questions

  1. Q1. What does the rule `alice ALL=(root) /usr/bin/systemctl restart ssh` mean?

  2. Q2. It is acceptable to specify a Cmnd_Alias entry without the absolute path.

  3. Q3. Which of the following sudoers practices are correct? Select all that apply.

  4. Q4. An auditor flags a broad grant. You add /etc/sudoers.d/10-deny-su containing `%ops ALL=(ALL) !/usr/bin/su`. The existing broad grant lives in /etc/sudoers.d/50-ops. visudo reports parsed OK. What have you actually achieved?

  5. Q5. man 5 sudoers describes subtracting a command from ALL, as in `ALL, !/usr/bin/su`, as advisory at best rather than a real control.

Passing score: 75%. Answers are checked in this browser.