Editing the /etc/sudoers
file is a critical task that directly impacts system security and user privilege management. Incorrect modifications can lock you out of administrative access or create vulnerabilities. The only safe and recommended way to edit this file is by using the visudo
command, which validates syntax before applying changes to prevent errors.
In this article, you will learn how to safely validate and modify the sudoers
file using visudo
, grant sudo privileges to users securely, troubleshoot common issues related to sudo configuration, and follow best practices to maintain system integrity. This guide builds on foundational knowledge such as the initial server setup and complements tutorials on creating sudo-enabled users to ensure you manage privileges effectively and securely.
Key Takeaways
visudo
to edit /etc/sudoers
or fragments under /etc/sudoers.d/
. visudo
locks the file and validates syntax on save, preventing lockouts.sudo visudo -c
, then functionally test with sudo -k && sudo -v && sudo -l
and a scoped command (for example, sudo /usr/bin/systemctl reload nginx
).sudo
; RHEL/CentOS/Fedora: wheel
) over per‑user ALL
rules to simplify audits and revocation./etc/sudoers.d/
and editing them with visudo -f
. Modular files are easier to review, roll back, and package.NOPASSWD:
only to low‑risk, well‑defined commands. Avoid wildcards and broad ALL
.secure_path
, and routinely review logs (/var/log/auth.log
or /var/log/secure
).pkexec visudo
; otherwise use single‑user/emergency mode, remount /
read‑write, and repair with visudo
.systemctl
with command -v
and adjust rules (e.g., /usr/bin/systemctl
vs /bin/systemctl
).Before you begin, ensure the following:
sudo
privileges or console/root access for recovery (serial/KVM/cloud console). Keep a break‑glass path available.nano
, vim
) and basic shell proficiency.visudo
, visudo -c
, sudo -k && sudo -v && sudo -l
, and journalctl
to verify behavior and logs.command -v systemctl
), and use those paths verbatim in sudoers.aiops
) and isolated directories under /var/aiops/
for logs/tmp. Only proceed with AI allowlists if you fully understand the security model.On Linux systems, the root account has unrestricted administrative access. You need root or equivalent privileges to install software, manage users, modify system configuration files, or perform emergency recovery. Because these actions can change system behavior or expose sensitive data, privilege elevation methods are deliberately controlled and auditable.
This section explains the three common ways to obtain root privileges, the security trade-offs of each, and recommended usage patterns.
Use sudo
for day‑to‑day administration. Avoid direct root login; use su
rarely on legacy systems or when sudo is not available. Keep a break‑glass path (console/root) for emergencies. Then enforce policy with visudo
and test with sudo -l
.
Task | Recommended Method | Primary Command(s) | Why | Risks / Notes | Logs to Check | Fallback / Recovery |
---|---|---|---|---|---|---|
Routine admin (packages, services) | sudo per command |
sudo apt install ... , sudo systemctl restart ... |
Least privilege; per‑command audit trail; easy to revoke | Typos in sudoers can deny commands; always validate policy | Debian/Ubuntu: /var/log/auth.log ; RHEL: /var/log/secure |
If denied, verify absolute path in rule; run sudo -l ; fix policy with visudo |
One‑off maintenance needing a root shell | sudo -i |
sudo -i |
Logged elevation using your identity; no root password sharing | Elevated shell can widen blast radius—exit promptly when done | Same as above | If shell not allowed, add temporary rule in /etc/sudoers.d/ then remove after task |
Legacy hosts without sudo configured | su |
su / exit |
Works without sudo setup; contiguous maintenance | Shared root password reduces accountability; easier to make mistakes in root shell | Shell history + system logs | Migrate to sudo ; create named admin user; move policy to /etc/sudoers.d/ |
Emergency recovery (sudo broken) | Direct root via console | Console/serial login; single‑user/emergency mode | Regain control when sudoers is invalid | Remote SSH root login should normally be disabled | Boot logs; recovery shell output | Use pkexec visudo if available; otherwise mount RW in single‑user mode and fix with visudo |
id && groups && sudo -l
sudo visudo -c || echo "Sudoers has errors — use console or pkexec visudo to repair."
command -v systemctl
Directly logging in as the root user grants immediate full privileges.
# SSH directly as root (only if root login is enabled)
ssh root@server_domain_or_ip
Harden immediately (recommended): disable remote root SSH to reduce attack surface.
# In /etc/ssh/sshd_config
PermitRootLogin no
# Then reload
sudo systemctl reload sshd
/var/log/auth.log
(Debian/Ubuntu) or /var/log/secure
(RHEL family). Review frequently:# Debian/Ubuntu
sudo grep -i "session opened for user root" /var/log/auth.log | tail -n 20
# RHEL/CentOS
sudo grep -i "session opened for user root" /var/log/secure | tail -n 20
su
to Become Rootsu
(substitute user) changes your shell to another account (commonly root).
# Become root (prompts for the root account password)
su
# Return to your normal shell
exit
su
?su
?su
?su
for Better Security?sudo
to Execute Commands as Root (Recommended)sudo
runs individual commands with elevated privileges and records who did what.
# Run a single command as root
sudo systemctl restart sshd
# Open an elevated login shell (uses root’s environment)
sudo -i
# List your effective privileges
sudo -l
sudo
?/etc/sudoers
and /etc/sudoers.d/*
sudo
?visudo
)sudo
?sudo
Securely?# Debian/Ubuntu
sudo usermod -aG sudo <username>
# RHEL/CentOS/Fedora
sudo usermod -aG wheel <username>
sudo
Configuration?# Validate sudoers syntax first
sudo visudo -c
# Force re‑auth then cache credentials
sudo -k && sudo -v
# Confirm what the user can do
sudo -l
sudo
Logs?# Debian/Ubuntu
sudo grep -i sudo /var/log/auth.log | tail -n 20
# RHEL/CentOS/Fedora
sudo grep -i sudo /var/log/secure | tail -n 20
See: How to Create a New Sudo-Enabled User on Ubuntu for quick setup.
The sudo
command is governed by policy stored in /etc/sudoers
. That file (and files under /etc/sudoers.d
) define which users can run what commands and under which conditions. Because a single syntax error in /etc/sudoers
can disable sudo
entirely, you must never edit /etc/sudoers
with a normal text editor.
visudo
is the safe editor for sudoers:
sudo visudo
Reference: See the
sudoers(5)
andvisudo(8)
man pages for authoritative syntax and safety guarantees.
-f
so you can edit fragments in /etc/sudoers.d
safely.To check the syntax of the current configuration without opening an editor:
sudo visudo -c
/etc/sudoers: parsed OK
/etc/sudoers: line 42: syntax error near 'ALL'
/etc/sudoers: parse error
When visudo -c
reports a parse error, it will include the file and approximate line number so you can correct the offending line with visudo
.
visudo
typically opens nano
by default for interactive simplicity.visudo
commonly opens vi
/vim
by default.Change the editor system-wide on Debian/Ubuntu with:
sudo update-alternatives --config editor
Or set a user-level preference in your shell rc file for any distro:
# Use vim for visudo and other editor-based commands
export EDITOR="$(command -v vim)"
# Reload your shell config
. ~/.bashrc
Editor | Pros | Cons |
---|---|---|
nano | Beginner-friendly; easy to use | Limited features and shortcuts |
vim/vi | Powerful editing, ubiquitous, supports macros | Steeper learning curve for new users |
ed | Extremely lightweight; available on minimal systems | Hard to use interactively; not recommended for most admins |
/etc/sudoers.d/
Best practice: keep custom policies in separate files under /etc/sudoers.d/
. This keeps /etc/sudoers
clean and makes it easier to audit or remove packages’ rules.
# Edit or create a fragment safely
sudo visudo -f /etc/sudoers.d/99-custom-ops
visudo
will validate the fragment the same as the main sudoers file.
Follow this repeatable workflow to change sudo policy safely and auditably.
Check syntax before touching anything:
sudo visudo -c
parsed OK
.Edit the main file or (preferably) a fragment:
# Main policy
sudo visudo
# Fragment (recommended)
sudo visudo -f /etc/sudoers.d/99-custom-ops
Why fragments? Easier audits, targeted rollbacks, cleaner diffs, and fewer merge conflicts.
Grant full admin via the distro’s admin group instead of adding per-user ALL
rules.
# Ubuntu/Debian
sudo usermod -aG sudo <username>
# RHEL/CentOS/Fedora
sudo usermod -aG wheel <username>
If needed on RHEL-family distros, ensure the %wheel
line is enabled in sudoers:
%wheel ALL=(ALL) ALL
Use aliases and absolute command paths. Keep rules specific and auditable.
# /etc/sudoers.d/webops (edit with visudo -f)
# Command alias for power actions
Cmnd_Alias POWER = /sbin/shutdown, /sbin/halt, /sbin/reboot
# Users allowed to run POWER
User_Alias GROUPTWO = brent, doris, eric
GROUPTWO ALL = POWER
Run-as aliases let you target service users:
Runas_Alias WEB = www-data, apache
GROUPTWO ALL = (WEB) /usr/bin/systemctl
Use NOPASSWD:
sparingly and only for narrow, low-risk commands:
GROUPTWO ALL = NOPASSWD: /usr/bin/updatedb
# Syntax check
sudo visudo -c
# Re-authenticate and list effective privileges
sudo -k && sudo -v && sudo -l
If a command is denied, confirm the absolute path, Runas target, and that no later rule overrides it.
# Debian/Ubuntu
sudo grep -i sudo /var/log/auth.log | tail -n 50
# RHEL/CentOS/Fedora
sudo grep -i sudo /var/log/secure | tail -n 50
Consider enabling sudo I/O logging where policy requires detailed audits.
sudo
Access for Nginx Reload (Best Practice)Granting users the minimum privileges required to perform their operational duties is a cornerstone of secure system administration. A common scenario is allowing a deployment user or automation process to reload the Nginx web server without granting full root access. This section provides a comprehensive, step-by-step guide to implementing this with maximum safety, auditability, and maintainability.
Allowing users or automation to reload Nginx is often necessary for zero-downtime deployments or configuration changes. However, giving blanket sudo
or root access is a major security risk. By crafting a precise sudoers rule, you:
Before proceeding, ensure the following:
systemctl reload nginx
to reload the service).Create the deploy group and user (if not already present):
sudo groupadd -f deploy
id -u deployer >/dev/null 2>&1 || sudo useradd -m -G deploy deployer
Use the exact path to systemctl
in your sudoers rule. Verify it on your host and substitute accordingly.
# Discover the resolved absolute path to systemctl
command -v systemctl
readlink -f "$(command -v systemctl)"
Distribution note: On most systems
systemctl
resides at/usr/bin/systemctl
, but some distributions or minimal images may expose it at/bin/systemctl
(or via a symlink). Always use the exact path printed by the command above in your sudoers fragment.
Use visudo -f
to author a fragment that allows only an Nginx reload as root (no restart/stop):
# /etc/sudoers.d/deploy-nginx (edit only with visudo -f)
%deploy ALL=(root) NOPASSWD: /usr/bin/systemctl reload nginx
Note: If your
systemctl
path differs (for example,/bin/systemctl
), replace/usr/bin/systemctl
in the fragment with the exact path discovered in Path Verification.
Validate both the fragment and the full policy:
sudo visudo -f /etc/sudoers.d/deploy-nginx
sudo visudo -c
Open a fresh session for the deploy user, confirm rights, and perform the action:
# Ensure no cached auth, then switch to the deployer account
sudo -k
sudo -u deployer -i
# List effective sudo privileges
aaa=$(sudo -l 2>&1); echo "$aaa"
# Functional check: reload Nginx with least privilege
sudo /usr/bin/systemctl reload nginx
Check service status and recent logs to confirm a reload rather than a restart.
# Show current status summary (no pager)
systemctl status nginx --no-pager | sed -n '1,12p'
# Inspect recent unit logs for "reloaded" entries
journalctl -u nginx -n 20 --no-pager
Optionally, confirm that the master PID did not change (reload keeps the master PID; restart replaces it):
before=$(pidof nginx | awk '{print $1}')
sudo /usr/bin/systemctl reload nginx
after=$(pidof nginx | awk '{print $1}')
if [ "$before" = "$after" ]; then echo "Reload successful (PID unchanged)"; else echo "PID changed; this was a restart"; fi
Expected log example:
<timestamp> <host> sudo: deployer : TTY=pts/0 ; PWD=/home/deployer ; USER=root ; COMMAND=/usr/bin/systemctl reload nginx
Remove the fragment and re-validate if you need to revert:
sudo rm -f /etc/sudoers.d/deploy-nginx
sudo visudo -c
/etc/sudoers.d/
for easier audits and safe rollbacks.NOPASSWD:
only to low-risk operational commands; review logs regularly.Symptom / Message | Likely Cause | Fix |
---|---|---|
user is not in the sudoers file |
User not in admin group | Add to sudo (Ubuntu) or wheel (RHEL) group and re-login |
parse error with line number |
Syntax error in file/fragment | Open with visudo and correct the indicated line; re-run visudo -c |
command not allowed |
Rule missing absolute path or wrong Runas | Use full path (e.g., /usr/bin/systemctl ); ensure (USER) or (GROUP) is correct |
NOPASSWD not taking effect |
Tag overridden later or scoped incorrectly | Move NOPASSWD: closer to the command or remove conflicting PASSWD: tag |
Fragment not applied | Bad filename (contains dot or ends with ~ ) |
Rename to a simple filename (e.g., 99-team-rules ) |
Sudo totally broken | Invalid sudoers; no sudo works | Use console/root, su - , or pkexec visudo to repair; as last resort boot single-user mode |
This playbook gives you fast, reproducible fixes. Start with the decision tree, then apply the relevant row from the table.
sudo
at all?pkexec visudo
. If unavailable, boot to single‑user/emergency mode, mount the root filesystem read‑write, then fix policy with visudo
.visudo -c
and list rights with sudo -l
..
) and doesn’t end with ~
. Keep simple names (e.g., 99-team-rules
). Re‑validate.Symptom | Quick Checks | Solution | Example Commands |
---|---|---|---|
Can’t run sudo at all |
Is pkexec available? Do you have console/ILO/serial access? |
Use pkexec visudo if available. If not, boot into single-user or emergency mode, remount / as read-write, and repair with visudo . |
pkexec visudo ; mount -o remount,rw / ; visudo |
“command not allowed” | Does the rule use the absolute path? Is the correct (USER) /(GROUP) specified? Any later rule overriding it? |
Use the full path; set the correct Runas; move the allow rule below any broad denies; re-validate. | which systemctl ; sudo -l ; sudo visudo -c |
Fragment ignored | Does the filename have a dot or end with ~ ? Is it in /etc/sudoers.d/ ? |
Rename to a simple name (no dots or tildes) in /etc/sudoers.d/ and re-validate. |
sudo ls -al /etc/sudoers.d/ ; sudo mv /etc/sudoers.d/team.rules /etc/sudoers.d/99-team-rules ; sudo visudo -c |
Parse error with line number | What file and line does visudo -c report? |
Open the file with visudo , fix the exact line, and re-validate. |
sudo visudo ; sudo visudo -c |
“user is not in the sudoers file” | Is the user in the admin group? (Ubuntu: sudo , RHEL: wheel ) |
Add the user to the appropriate group and have them log out and back in. | sudo usermod -aG sudo <username> ; sudo usermod -aG wheel <username> |
NOPASSWD not taking effect |
Is a later PASSWD: tag overriding? Is the rule too broad? |
Place NOPASSWD: next to the specific command or remove conflicting tags; re-validate. |
sudo visudo -f /etc/sudoers.d/99-team-rules ; sudo visudo -c |
Caution: The exact steps to enter single-user or emergency mode can vary significantly depending on your Linux distribution, bootloader (such as GRUB or systemd-boot), and whether you are running on a physical server, virtual machine, or cloud image. Always consult your platform’s official documentation if you encounter differences.
Esc
, Shift
, or F12
) to access the boot menu.Once in recovery or single-user mode, you should be presented with a root shell prompt.
On many systems, the root filesystem is mounted as read-only for safety. To make changes, you must remount it as read-write:
mount -o remount,rw /
If you receive an error, double-check the device name for your root filesystem (it may be /dev/sda1
, /dev/vda1
, etc.) and adjust the command accordingly.
visudo
Use the visudo
command to safely edit the main sudoers file or a specific fragment. visudo
checks for syntax errors before saving, which helps prevent configuration mistakes that could lock you out.
visudo
If you know the problematic rule is in a fragment (for example, a file in /etc/sudoers.d/
), target that file directly:
visudo -f /etc/sudoers.d/99-team-rules
After making your changes, always validate the configuration:
visudo -c
If you encounter syntax errors, visudo
will report them with file and line number information. Correct any issues before proceeding.
Once you have repaired and validated the sudoers configuration, reboot the system to return to normal multi-user mode:
reboot
After rebooting, test sudo
functionality to ensure the issue is resolved.
Tip: If you are working on a cloud server (such as DigitalOcean), you may need to use the provider’s web console or serial console access to perform these steps, since SSH may not be available until the system is fully booted and sudo is working.
Summary:
Entering single-user or emergency mode allows you to recover from sudo misconfigurations by directly editing the sudoers file with root privileges. Always use visudo
to prevent syntax errors, and validate your changes before rebooting. If you are unsure about any step, consult your distribution’s recovery documentation or seek assistance to avoid accidental lockout or data loss.
Run these checks to confirm the system is healthy and the policy matches intent:
# 1) Syntax
sudo visudo -c
# 2) Authentication cache reset and re-auth
sudo -k && sudo -v
# 3) Effective privileges
sudo -l
# 4) Functional check (example)
sudo -u www-data /usr/bin/systemctl reload nginx
The most common operation that users want to accomplish when managing sudo
permissions is to grant a new user general sudo
access. This is useful if you want to give an account full administrative access to the system.
The easiest way of doing this on a system set up with a general purpose administration group, like the Ubuntu system in this guide, is actually to add the user in question to that group.
Note: Ubuntu 20.04 reached end-of-life (EOL) in May 2025. However, the
sudo
group continues to provide full administrative privileges on all currently supported Ubuntu versions (22.04, 24.04, and later).
For example, on Ubuntu 22.04 and newer, the sudo
group has full admin privileges. We can grant a user these same privileges by adding them to the group like this:
sudo usermod -aG sudo <username>
The gpasswd
command can also be used:
sudo gpasswd -a <username> sudo
These will both accomplish the same thing.
On CentOS, this is usually the wheel
group instead of the sudo
group:
sudo usermod -aG wheel <username>
Or, using gpasswd
:
sudo gpasswd -a <username> wheel
On CentOS, if adding the user to the group does not work immediately, you may have to edit the /etc/sudoers
file to uncomment the group name:
sudo visudo
# /etc/sudoers
. . .
%wheel ALL=(ALL) ALL
. . .
Now that we have gotten familiar with the general syntax of the file, let’s create some new rules.
The sudoers
file can be organized more easily by grouping things with various kinds of “aliases”.
For instance, we can create three different groups of users, with overlapping membership:
# /etc/sudoers
. . .
User_Alias GROUPONE = abby, brent, carl
User_Alias GROUPTWO = brent, doris, eric
User_Alias GROUPTHREE = doris, felicia, grant
. . .
Group names must start with a capital letter. We can then allow members of GROUPTWO
to update the apt
database by creating a rule like this:
# /etc/sudoers
. . .
GROUPTWO ALL = /usr/bin/apt-get update
. . .
If we do not specify a user/group to run as, as above, sudo
defaults to the root user.
We can allow members of GROUPTHREE
to shutdown and reboot the machine by creating a “command alias” and using that in a rule for GROUPTHREE
:
# /etc/sudoers
. . .
Cmnd_Alias POWER = /sbin/shutdown, /sbin/halt, /sbin/reboot, /sbin/restart
GROUPTHREE ALL = POWER
. . .
Note: The
POWER
alias above includes/sbin/restart
, which is not standard on many Linux distributions. To avoid confusion, it is best to remove it and keep only/sbin/shutdown
,/sbin/halt
, and/sbin/reboot
.
We create a command alias called POWER
that contains commands to power off and reboot the machine. We then allow the members of GROUPTHREE
to execute these commands.
We can also create “Run as” aliases, which can replace the portion of the rule that specifies the user to execute the command as:
# /etc/sudoers
. . .
Runas_Alias WEB = www-data, apache
GROUPONE ALL = (WEB) ALL
. . .
This will allow anyone who is a member of GROUPONE
to execute commands as the www-data
user or the apache
user.
Just keep in mind that later rules will override earlier rules when there is a conflict between the two.
When configuring sudo
, it is essential to restrict privileges as much as possible to prevent accidental or malicious misuse. Overly broad or permissive rules can allow users to perform unintended actions, potentially leading to system compromise, data loss, or service disruption. By carefully locking down your sudoers rules, you enforce the principle of least privilege—ensuring that users and groups can only perform the specific administrative tasks they require, and nothing more.
In summary, locking down sudo rules:
The following sections will show you practical techniques and examples for writing secure, tightly-scoped sudoers rules, using tags like NOPASSWD
and NOEXEC
only where appropriate, and ensuring that every rule is as specific and safe as possible.
Locking down rules in the sudoers file ensures that privilege escalation remains controlled and intentional. Without constraints, users may unintentionally gain broader access than required, leading to potential misuse or security gaps. By applying tags like NOPASSWD
or NOEXEC
carefully and only to specific commands, you maintain least-privilege principles while enabling safe, auditable operations. This strengthens your security posture, makes audits clearer, and reduces the risk of errors in production environments.
There are a number of ways that you can achieve more control over how sudo
reacts to a call.
The updatedb
command associated with the mlocate
package is relatively harmless on a single-user system. If we want to allow users to execute it with root privileges without having to type a password, we can make a rule like this:
# /etc/sudoers
. . .
GROUPONE ALL = NOPASSWD: /usr/bin/updatedb
. . .
NOPASSWD
is a “tag” that means no password will be requested. It has a companion command called PASSWD
, which is the default behavior. A tag is relevant for the rest of the rule unless overruled by its “twin” tag later down the line.
For instance, we can have a line like this:
# /etc/sudoers
. . .
GROUPTWO ALL = NOPASSWD: /usr/bin/updatedb, PASSWD: /bin/kill
. . .
Another helpful tag is NOEXEC
, which can be used to prevent some dangerous behavior in certain programs.
For example, some programs, like less
, can spawn other commands by typing this from within their interface:
!command_to_run
This basically executes any command the user gives it with the same permissions that less
is running under, which can be quite dangerous.
To restrict this, we could use a line like this:
# /etc/sudoers
. . .
<username> ALL = NOEXEC: /usr/bin/less
. . .
There are a few more pieces of information that may be useful when dealing with sudo
.
If you specified a user or group to “run as” in the configuration file, you can execute commands as those users by using the -u
and -g
flags, respectively:
sudo -u <run_as_user> command
sudo -g <run_as_group> command
For convenience, by default, sudo
will save your authentication details for a certain amount of time in one terminal. This means you won’t have to type your password in again until that timer runs out.
For security purposes, if you wish to clear this timer when you are done running administrative commands, you can run:
sudo -k
If, on the other hand, you want to “prime” the sudo
command so that you won’t be prompted later, or to renew your sudo
lease, you can always type:
sudo -v
You will be prompted for your password, which will be cached for later sudo
uses until the sudo
time frame expires.
If you are simply wondering what kind of privileges are defined for your username, you can type:
sudo -l
This will list all of the rules in the /etc/sudoers
file that apply to your user. This gives you a good idea of what you will or will not be allowed to do with sudo
as any user.
There are many times when you will execute a command and it will fail because you forgot to preface it with sudo
. To avoid having to re-type the command, you can take advantage of a bash functionality that means “repeat last command”:
sudo !!
The double exclamation point will repeat the last command. We preceded it with sudo
to quickly change the unprivileged command to a privileged command.
For some fun, you can add the following line to your /etc/sudoers
file with visudo
:
sudo visudo
# /etc/sudoers
. . .
Defaults insults
. . .
This will cause sudo
to return a silly insult when a user types in an incorrect password for sudo
. We can use sudo -k
to clear the previous sudo
cached password to try it out:
sudo -k
sudo ls
Output[sudo] password for demo: # enter an incorrect password here to see the results
Your mind just hasn't been the same since the electro-shock, has it?
[sudo] password for demo:
My mind is going. I can feel it.
The rise of AI copilots and assistants has transformed how developers and operations teams interact with infrastructure. Instead of manually running diagnostic commands, scanning logs, and performing repetitive monitoring, AI-assisted system administration enables intelligent automation while still enforcing strict security controls.
The Shell MCP Server (Model Context Protocol Server for Shell) provides a standardized way for AI assistants to execute specific commands on a system. When combined with carefully scoped sudoers
rules, it allows you to delegate limited, auditable system tasks to AI agents without exposing root shells or unlimited privileges.
Key benefits include:
Security Note: The primary risk of AI-driven administration is privilege abuse. This guide enforces the principle of least privilege—AI can only run pre-approved commands with clear audit trails, never arbitrary root actions.
Before setting up the Shell MCP Server for AI-assisted administration, ensure the following requirements are met:
System Requirements
pip
or uv
should be available for Python package management.Create a Dedicated AI Service Account
For security and auditability, create a non-login user specifically for AI operations:
sudo adduser --disabled-password --gecos "" aiops
Set Up Isolated Directories for AI Data
Establish dedicated directories for logs and temporary files, and assign ownership to the aiops
user:
sudo mkdir -p /var/aiops/{logs,tmp}
sudo chown -R aiops:aiops /var/aiops
Install the Shell MCP Server
Use your preferred Python package manager to install the server in the user environment:
python3 -m pip install --user shell-mcp-server
Alternatively, if you use uv
:
uv tool install shell-mcp-server
Perform Initial MCP Server Configuration
Create the configuration directory and set up the main config file with appropriate server and logging settings:
mkdir -p /home/aiops/.config/shell-mcp
cat <<EOF | sudo tee /home/aiops/.config/shell-mcp/config.yaml
server:
port: 11434
timeout: 30
allowed_shell: /bin/bash
logging:
level: INFO
file: /var/log/aiops/mcp-server.log
EOF
Ensure the aiops
user owns the configuration directory and its contents:
sudo chown -R aiops:aiops /home/aiops/.config/shell-mcp
Create /etc/sudoers.d/50-ai-mcp-server
with carefully scoped rules:
# AI-Safe Sudoers Configuration for Shell MCP Server
Cmnd_Alias AI_MONITORING = /usr/bin/uptime, /usr/bin/free, /usr/bin/df -h, /usr/bin/top -b -n 1
Cmnd_Alias AI_LOGS = /bin/journalctl -n 200, /bin/journalctl -u nginx -n 100, /usr/bin/tail -n 200 /var/log/syslog, /usr/bin/tail -n 200 /var/log/messages
Cmnd_Alias AI_SERVICES = /usr/bin/systemctl status nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl status docker, /usr/bin/systemctl restart myapp
Cmnd_Alias AI_FILES = /usr/bin/ls /var/aiops/*, /usr/bin/cat /var/aiops/logs/*, /usr/bin/touch /var/aiops/tmp/*
Cmnd_Alias AI_NETWORK = /bin/ping -c 4 *, /usr/bin/curl -I http://*, /usr/bin/curl -I https://*
aiops ALL=(ALL) NOPASSWD: AI_MONITORING, AI_LOGS, AI_SERVICES, AI_FILES, AI_NETWORK
Run the server:
sudo -u aiops shell-mcp-server --config /home/aiops/.config/shell-mcp/config.yaml
Claude integration example:
{
"servers": {
"shell": {
"command": "shell-mcp-server",
"args": ["--config", "/home/aiops/.config/shell-mcp/config.yaml"],
"env": { "PATH": "/usr/local/bin:/usr/bin:/bin" }
}
}
}
Validation:
ps -u aiops -o pid,cmd
sudo -u aiops sudo uptime
sudo -u aiops sudo bash # should be denied
sudo -u aiops sudo free -m
to analyze memory trends.sudo -u aiops sudo systemctl reload nginx
during deployments.sudo -u aiops sudo systemctl status docker
to diagnose issues.Defaults logfile="/var/log/sudo.log"
Issue | Diagnosis | Fix |
---|---|---|
MCP server fails | Config error | Check /var/log/aiops/mcp-server.log |
Command denied | Wrong sudoers rule | Run sudo visudo -c |
Commands hang | Timeout | Lower timeout in config |
Logs missing | Wrong path | Fix AI_LOGS path |
Full lockout | Broken sudoers | Use pkexec visudo or single-user mode |
1) What is the sudoers file and why is it important?
The sudoers file (/etc/sudoers
and /etc/sudoers.d/
) defines which users can run privileged commands.
visudo
to validate syntax before saving.2) Why should I always use visudo instead of a text editor?
Using nano
or vim
directly on /etc/sudoers
risks breaking privilege escalation. visudo
solves this by:
sudo visudo
sudo visudo -f /etc/sudoers.d/99-custom-ops
This guarantees safer, modular edits with less risk of lockout.
3) How can I give a user sudo privileges securely?
The best method is group-based assignment:
# Ubuntu/Debian
sudo usermod -aG sudo <username>
# RHEL/CentOS/Fedora
sudo usermod -aG wheel <username>
ALL
rules; instead, create fragments under /etc/sudoers.d/
.4) How do I safely configure passwordless sudo?
Passwordless sudo should only apply to narrow, low-risk commands:
# /etc/sudoers.d/99-team-rules
GROUPONE ALL = NOPASSWD: /usr/bin/updatedb
NOPASSWD:
sparingly, avoid ALL
.sudo visudo -c
./var/log/auth.log
(Ubuntu) or /var/log/secure
(RHEL).5) What should I do if I break the sudoers file?
If sudo fails entirely:
Try repairing with:
pkexec visudo
If unavailable, boot into single-user/emergency mode:
mount -o remount,rw /
visudo
Always validate with sudo visudo -c
before rebooting.
As a precaution, keep console or root access for recovery in production systems.
6) How can I troubleshoot common sudo errors effectively?
Match errors to quick fixes:
which systemctl
; check with sudo -l
..
or ~
, e.g., 99-team-rules
.visudo
, re-validate with visudo -c
.sudo
/wheel
group and re-login.7) What are advanced hardening practices for sudoers?
To enforce enterprise-grade security:
Enable logging: Defaults logfile=/var/log/sudo.log
.
Configure secure PATH:
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Use I/O logging for sensitive commands.
Require tty
on RHEL: Defaults requiretty
.
Regularly audit /etc/sudoers.d/
and rotate sudo-enabled accounts.
Integrate with MFA for root-level actions where possible.
You now have a solid foundation for safely reading and modifying the sudoers
file, along with the tools to manage root privileges responsibly. By always using visudo
, validating changes, and applying the principle of least privilege, you can minimize risk while maintaining flexibility and control.
Super-user access should never be taken lightly—use it only when necessary, and restrict or audit functionality that is not required. Following these best practices will help ensure your Linux systems remain secure, resilient, and easy to manage.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Former Senior Technical Writer at DigitalOcean, specializing in DevOps topics across multiple Linux distributions, including Ubuntu 18.04, 20.04, 22.04, as well as Debian 10 and 11.
Senior Technical Writer at DigitalOcean
Building future-ready infrastructure with Linux, Cloud, and DevOps. Full Stack Developer & System Administrator @ DigitalOcean | GitHub Contributor | Passionate about Docker, PostgreSQL, and Open Source | Exploring NLP & AI-TensorFlow | Nailed over 50+ deployments across production environments.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
absolute not useful! a lot of divagations, but again telling what do do instead HOW to do. beginners need to find HOW the fuck to do it!
@castleless: Sorry you feel that way! This article is trying to provide background material to help people understand the commands. Maybe something like the initial server setup guide is more your speed:
https://www.digitalocean.com/community/articles/initial-server-setup-with-ubuntu-14-04
If you want to add sudo privileges for a user named “myuser”, run the command:
<pre> visudo </pre>
Then add the following line to the file:
<pre> myuser ALL=(ALL:ALL) ALL </pre>
Done!
Never mind how to do it differently; how to do it the original way before you change it would be more helpful.
So to recap… add
Then on nano as visudo,
``` to writeout and save the file /etc/sudoers.tmp
And it's this sudoers.tmp file which is read by sudo as the config file?
Using a tmp file as a config file is a bit counter-intuitive. Does visudo rename it when it's saved?
Answering my own question, that does seem to be the case. So never mind the name of the file, just do it... :/
@rshpeley: visudo
ensures that you don’t leave /etc/sudoers
in a broken state. It’s saved to the temp file, checked for errors, then renamed.
Maybe I’m on a later version of Ubuntu since this was written, but it looks like the current config advises using an extra file to add user settings to sudoers.
Is it now correct to uncomment the last line of sudoers #includedir /etc/sudoers.d
then add a file in the etc/sudeors.d/ containing your additions?
Also, do I need to restart anything for the changes to take affect?
Hi, Very helpful article. By the way, how can we add an ldap user (normal user) to the sudoer’s file?
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.