15.2 The sudoers File: Location, Format, and Rules
Alright, let’s get our hands dirty with the sudoers file. This is the absolute nerve center of sudo, the sacred text that dictates who gets to do what. It’s a single file, /etc/sudoers, that holds all the power, and for that reason, you should treat it with the respect of a live explosive. One misplaced character and you could lock yourself out of your own system or, worse, create a gaping security hole. We never, ever edit this file directly with a regular text editor. We use visudo. This isn’t a suggestion; it’s the law. visudo locks the file to prevent simultaneous edits and, most importantly, it performs a syntax check on the file before saving it. If you mess up, it will politely (or not so politely) stop you from saving a broken configuration, saving you from a world of pain. Trust me, you want this safety net.
The visudo Command and Basic Syntax
So, how do we invoke this magic? Simply run:
sudo visudo
This will open the /etc/sudoers file in your default editor (usually nano or vi). If you prefer a different editor, like vim, you can set the EDITOR environment variable first:
sudo EDITOR=vim visudo
Now, let’s look inside. You’ll see a bunch of comments and some default entries. The syntax might look a bit arcane at first, but it’s logical. The basic building block is an alias, and the main event is a user specification.
There are four types of aliases:
- User_Alias: Groups of users or usernames.
- Runas_Alias: Groups of users that a command can be run as (not just root!).
- Host_Alias: Groups of hostnames (useful in large environments).
- Cmnd_Alias: Groups of commands (this is the big one).
Aliases are defined in ALL_CAPS and can contain lists of items, separated by commas.
# Define a group of admins
User_Alias SYSADMINS = alice, bob, %admin
# Define a set of software management commands
Cmnd_Alias SOFTWARE = /usr/bin/apt, /usr/bin/dpkg, /usr/bin/snap
# Define who a command can be run as (like the user 'deploy')
Runas_Alias DEPLOY_USER = deploy
Anatomy of a User Specification
This is the line that actually grants power. Its structure is deceptively simple:
user host = (runas_user) command
Let’s break that down:
user: This can be a username, a group (prefixed with%), or a User_Alias.host: This is the hostname of the machine where the rule applies. For a single machine, it’s almost alwaysALL. This is where Host_Alias would be used.(runas_user): This specifies which user(s) the command can be run as. This defaults torootif omitted. It can be a user, a group (prefixed with%), or a Runas_Alias.command: This is the absolute path to the command that is allowed. It can be a single command, a directory (with a trailing/), or a Cmnd_Alias. Using a directory is handy but dangerous—it allows every command in that directory.
Here’s a simple example that lets the user ‘alice’ update the package cache (a very safe command):
alice ALL = /usr/bin/apt update
To let a user run a command as another user, like the ‘deploy’ user we aliased earlier:
bob ALL = (DEPLOY_USER) /usr/bin/systemctl restart myapp
The Power of NOPASSWD and Tags
Here’s where things get spicy. By default, sudo asks for the invoking user’s password. This is a good security practice. But sometimes, for automation or specific scripts, you need to remove that prompt. Enter NOPASSWD:. Use it with extreme caution. It should be the exception, not the rule.
You can also use tags to modify behavior. The most common one is SETENV, which allows the user to pass their own environment variables to the command, which can be a huge security risk if the command is poorly written.
You apply these tags on a per-command basis within the specification.
# Let the 'automation' user restart a service without a password
automation ALL = (root) NOPASSWD: /usr/bin/systemctl restart nginx
# Let a user run apt-get update with a password, but apt-get upgrade without one (why? I don't know, but you could)
charlie ALL = (root) PASSWD: /usr/bin/apt update, NOPASSWD: /usr/bin/apt upgrade
Common Pitfalls and Best Practices
Never use
ALLas a command. Just don’t.username ALL = (ALL) ALLis handing over the keys to the kingdom. It’s the equivalent of making them root. Be specific. Grant only the permissions absolutely necessary for the task.Always use absolute paths. This is non-negotiable. If you specify
aptinstead of/usr/bin/apt, a user could manipulate theirPATHenvironment variable to point to a malicious script namedaptand run anything they want.sudois very paranoid about this by design, and for excellent reason.Leverage Cmnd_Alias for readability. Grouping related commands into an alias makes your
sudoersfile infinitely more manageable and less error-prone.SOFTWARE = /usr/bin/apt, /usr/bin/dpkg, /usr/sbin/dpkg-reconfigureis much better than a long, repetitive list of commands in every rule.Test thoroughly. After saving with
visudo, open a new terminal (so your environment is fresh) and test the exact command you just granted. Verify it works as expected and, just as importantly, that commands you didn’t grant are properly denied.
The sudoers file is a masterpiece of granular privilege control. It’s fussy and will punish you for sloppiness, but that’s what makes it secure. Tame it, respect it, and it will be the most powerful tool in your system administration arsenal.