Why do we need sudo?
The word sudo is an abbreviation for "superuser do" and is used to run commands as the root user. Commands that require elevated privileges like installing or updating packages or changing services can be run by an unprivileged user through this tool, allowing convenient administrative access without being permanently logged into a privileged account.
It also helps operators make an educated guess at the potential security issues and blast radius of running commands or scripts, as not running them through sudo ensures that the entire script will run with use privileges only, cut off from deeper system access.
Basic usage
The sudo command comes preinstalled on almost every linux distribution. The configuration is stored in /etc/sudoers, but you should always edit it using the visudo command instead:
sudo visudoUsing visudo ensures the file is validated when exiting, and only saved if it is syntactically correct. A typo could lock you out of your system or break the sudo command altogether, so this much caution is warranted. If you are not happy with the default editor, you can change it, for example to nano if you prefer:
sudo EDITOR=nano visudoMost popular linux systems come with a fully privileged administrative group preconfigured, called sudo on debian-like systems or wheel for the RHEL family. Adding users to this group automatically gives them permissions to run any command they want as root through sudo:
sudo usermod -aG sudo my_user # Debian/Ubuntu
sudo usermod -aG wheel my_user # RHEL/ArchThis adds user my_user to the respective administrator group, letting them run any command they like as root.
Running privileged commands
If your current user has access to privileged commands via sudo, you can execute them by prefixing the sudo command:
sudo whoamishould print
rootSince the whoami program is run as root by sudo, that's what it will print instead of your current user.
You can also run commands as other users if allowed:
sudo -u postgres psqlThis would run the psql command as the postgres user, common for postgresql installations.
Your account may have complete access to all commands or only a restricted subset of them. You can check the exact type of access using
sudo -llThis should provide a verbose listing of all allowed sudo usages configured for your user:
Matching Defaults entries for my_user on my_host:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User my_user may run the following commands on my_host:
Sudoers entry:
RunAsUsers: ALL
Options: !authenticate
Commands:
ALLYou can also refer to this command for debugging if you run into issues when setting up custom sudo permissions.
Controlling allowed commands
The commands allowed to run for a user or group are defined in /etc/sudoers using this syntax:
<user or group> <host>=(<user to run as>:<optional group to run as>) <options, if any> <command with full path and optionally flags/params>The user can be either a literal username, or a group name prefixed with %:
my_user ALL=(ALL) ALL
%my_group ALL=(ALL) ALLThe special keyword ALL accepts any possible values in its position, so the above example gives my_user and users in my_group access to all commands on all hosts and allow them to be run as any user or any group ownership.
The command at the end gets special handling if it contains parameters; for example:
my_user ALL=(ALL) /usr/bin/pingwould allow my_user to ping any target with any configuration options they like, while
my_user ALL=(ALL) /usr/bin/ping example.comwould restrict them to this exact command, only being able to ping example.com. If a command contains flags or parameters it can only be run with those, if not then any parameters are allowed for the command.
There are multiple options that can be granted per-command, most notably NOPASSWD: to exclude them from the password prompt and NOEXEC: to prevent the command from running other commands:
my_user ALL=(ALL) NOEXEC: /usr/bin/env # can only view/change environment, not run other commands
my_user ALL=(ALL) NOPASSWD: /usr/bin/ping # does not prompt for password when running pingThese options can also be combined:
my_user ALL=(ALL) NOEXEC: NOPASSWD: /usr/bin/env # program "env" can be run without password prompt, but not used to invoke other commandsSetting NOEXEC: is a good idea for most programs to harden the system against privilege escalation, while setting NOPASSWD: should be done with care, preferably only for specific commands with arguments to reduce the potential attack surface for abuse. See man 5 sudoers for a complete list of options and pay attention to their security disclaimers.
The same target user or group can have multiple lines allowing the access to specific commands, overriding each other in the order they were specified. For example:
my_user ALL=(ALL) ALL
my_user ALL=(ALL) NOPASSWD: /usr/bin/pingGives access to all commands through sudo, but only ping is excluded from the password prompt. If you reverse their order:
my_user ALL=(ALL) NOPASSWD: /usr/bin/ping
my_user ALL=(ALL) ALLthen the NOPASSWD: option is overridden, because ALL includes /usr/bin/ping, so overrides it's previous options.
It is reasonable to restrict untrusted users with minimal privileges, for example to allow a staff user to administrate the local postgresql database, a permission may look like
staff ALL=(postgres:postgres) NOEXEC: psqlThis will give them access to run the psql command as the postgres user, but prevent that command from invoking other executables.
Using command aliases
Commands needed for a specific task can be turned into an alias, think of it like a group or category. For example maintenance staff may need access to commands used to update packages or remove old ones, but shouldn't have access to installing arbitrary new software. The required commands might be:
apt update
apt upgrade
apt autoremoveThese can be grouped into a single alias:
Cmnd_Alias PKG_MAINTENANCE = /usr/bin/apt update, /usr/bin/apt upgrade, /usr/bin/apt autoremoveThe alias can be used in place of a command to provide access to all the commands inside it:
my_staff_user ALL=(ALL) NOPASSWD: PKG_MAINTENANCEThis can be handy if multiple users need access to the same commands, for example to provide access for both staff members and an automated deployment job's user.
Changing default sudo behavior
While sudo comes with default settings that work for most users, this behavior can be altered, either globally or per user / group, or even per command alias. You can use the Defaults keyword to define how exactly sudo behaves:
Defaults env_reset # resets env vars for all users/groups/aliases
Defaults:my_user env_reset # resets env vars for my_user
Defaults:%my_group env_reset # resets env vars for users in my_group
Defaults!PKG_MAINTENANCE env_reset # resets env vars for commands in alias group PKG_MAINTENANCEThere are many options to change, for example:
env_reset to strip most environment variables before running commands with elevated privileges. This is an essential security mechanism, as environment variables like EDITOR or LD_PRELOAD can be used to escape the confinement of sudo and break into an unrestricted privileged shell, or run arbitrary commands with root permissions. Only remove this or use settings like env_keep if you are confident that you understand the risk it poses.
timestamp_timeout=N to set the number of minutes sudo will wait before prompting for the user's password again. Remember that adjusting this is always a tradeoff between usability and security.
log_input and log_output to record the input and output of all commands ran with elevated privileges, useful for auditing or spotting misbehaving users early on.
use_pty to force sudo to only work with pseudo-terminals (aka interactive sessions), preventing most types of automated background privilege escalation.
There are many more settings available, see man 5 sudoers for a complete list with explanations.