How to Configure sudo and the sudoers File on Linux: Safe Permission Management for Each User

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

I’ve been in this situation before: a colleague needed to restart the Nginx service on a production server but didn’t have root access. The quickest fix was to hand them the root password — but that’s the worst possible move from a security standpoint. That’s when I truly understood just how important sudo really is.

On the company’s old CentOS 7 server, I had to optimize quite a few things. One of the first was overhauling the entire sudo policy — because previously, almost everyone had been added to the wheel group with no restrictions whatsoever.

The Real Problem with Granting Permissions on a Server

When working with Linux servers in a team environment, you immediately face the question: who gets to do what? Developers need to deploy code, DevOps engineers need to manage services, junior sysadmins need to view logs — but none of them should have unrestricted root access.

Linux addresses this through sudo (superuser do) and the /etc/sudoers configuration file. Instead of sharing the root password, you control exactly which user can run which command, as which user, and on which machine.

Three Approaches to Granting sudo Access

Approach 1: Add the User to the sudo or wheel Group

The fastest and most familiar option — one command and you’re done. But keep in mind: this grants full sudo privileges with no command restrictions.

# Ubuntu/Debian — uses the "sudo" group
sudo usermod -aG sudo username

# CentOS/RHEL/Fedora — uses the "wheel" group
sudo usermod -aG wheel username

# Verify the user has been added to the group
id username
# groups: uid=1001(username) gid=1001(username) groups=1001(username),10(wheel)

After being added to the group, the user needs to log out and log back in for the new group membership to take effect.

Approach 2: Add a Rule Directly to /etc/sudoers

If you want finer-grained control — for example, only allowing a restart of Nginx rather than the entire system — this is the way to go.

# ALWAYS use visudo to edit sudoers — NEVER open the file directly
sudo visudo

# Basic syntax in sudoers:
# user  host=(runas_user) command
username ALL=(ALL) ALL

# Restrict to restarting nginx only
username ALL=(ALL) /usr/bin/systemctl restart nginx

# Multiple commands, separated by commas
username ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx

Approach 3: Create Separate Files in /etc/sudoers.d/

Instead of cramming everything into a single ever-growing /etc/sudoers file, create individual files for each team inside /etc/sudoers.d/. Need to revoke someone’s access? Just delete their file — no need to dig through a massive config.

# Create a separate config file for a user or team
sudo visudo -f /etc/sudoers.d/devteam

# File contents:
# Grant deploy permissions to the entire devteam group
%devteam ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl restart php-fpm

# Note: file permissions must be 0440
sudo chmod 0440 /etc/sudoers.d/devteam

Comparing the Pros and Cons of Each Approach

Criteria Group (sudo/wheel) Edit /etc/sudoers /etc/sudoers.d/
Ease of use Very easy Moderate Moderate
Fine-grained control No (full access) Yes Yes
Easy to manage many users Difficult Difficult (one large file) Easy (separate files)
Safe against mistakes Low Low without visudo Higher
Best suited for Personal dev machines Small servers, few users Production, teams

Approach 1 grants full sudo — the user can do anything root can. Approaches 2 and 3 let you restrict access to only the commands that are actually needed. The security principle here is least privilege — grant only what’s necessary, nothing more.

Which Approach Should You Choose?

  • Personal machine / dev machine: Approach 1 is perfectly fine — adding the user to the sudo group is enough.
  • Small server with just you or 1–2 admins: Approach 2, editing sudoers directly with visudo.
  • Production server with multiple teams: Approach 3 — each team or role gets its own file in /etc/sudoers.d/, making auditing and revoking access straightforward.

I typically use Approach 3 for production. When someone’s access needs to be revoked, I just delete or rename their file rather than hunting through a massive sudoers file.

Practical Implementation Guide

Step 1: Create the User and Group (if they don’t exist)

# Create a new user
sudo useradd -m -s /bin/bash deployer
sudo passwd deployer

# Create a group for the team
sudo groupadd devteam

# Add the user to the group
sudo usermod -aG devteam deployer

Step 2: Create a sudoers Rule with Restricted Permissions

sudo visudo -f /etc/sudoers.d/deployer

# Contents — only allow restarting/reloading services related to deployment:
deployer ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, \
                              /usr/bin/systemctl reload nginx, \
                              /usr/bin/systemctl restart php8.1-fpm, \
                              /usr/bin/systemctl status nginx

NOPASSWD means the user won’t be prompted for a password when running those commands — useful for automation and CI/CD scripts.

Step 3: Advanced Configuration with Aliases

As the number of commands grows (5–10 commands is common in production environments), use Command Aliases to keep things tidy:

sudo visudo -f /etc/sudoers.d/webteam

# Define aliases
Cmnd_Alias WEB_SERVICES = /usr/bin/systemctl restart nginx, \
                          /usr/bin/systemctl reload nginx, \
                          /usr/bin/systemctl restart php8.1-fpm

Cmnd_Alias VIEW_LOGS = /usr/bin/tail -f /var/log/nginx/error.log, \
                       /usr/bin/tail -f /var/log/nginx/access.log

# Grant permissions to the group
%webteam ALL=(ALL) NOPASSWD: WEB_SERVICES
%webteam ALL=(ALL) NOPASSWD: VIEW_LOGS

Step 4: Verify the Configuration

# Check syntax of all sudoers files (no execution)
sudo visudo -c
# Expected output: /etc/sudoers: parsed OK
# /etc/sudoers.d/deployer: parsed OK

# View the current permissions for the logged-in user
sudo -l

# View permissions for a specific user (requires root)
sudo -lU deployer

# Test a command with the -l flag (list only, no execution)
sudo -l -U deployer

Additional Useful Configuration Options

# Increase the sudo timeout (default is 15 minutes, this changes it to 5)
# Add to /etc/sudoers:
Defaults timestamp_timeout=5

# Require password on every invocation (timeout = 0)
Defaults timestamp_timeout=0

# Log all sudo commands to a dedicated file
Defaults logfile=/var/log/sudo.log

# Enable the lecture (warning shown on first sudo use)
Defaults lecture=always

Common Mistakes and How to Avoid Them

Mistake 1: Editing sudoers with a regular editor (not visudo)

If you open /etc/sudoers directly with nano or vim and accidentally save with a syntax error, sudo will break entirely — nobody will be able to use it. visudo validates the syntax before saving. That’s exactly why it exists.

Mistake 2: Forgetting to use absolute paths in sudoers

# Wrong — sudoers ALWAYS requires absolute paths
deployer ALL=(ALL) systemctl restart nginx

# Correct
deployer ALL=(ALL) /usr/bin/systemctl restart nginx

# Find the correct path for a command
which systemctl
# /usr/bin/systemctl

Mistake 3: Wildcards in sudoers being bypassed

# DANGEROUS — user could run: sudo vim /etc/sudoers
deployer ALL=(ALL) /usr/bin/vim *

# Safer — only allow editing a specific file
deployer ALL=(ALL) /usr/bin/vim /var/www/html/config.php

I’ve personally seen wildcards in sudoers exploited for privilege escalation — a user with vim * permission opened /etc/passwd and edited it directly. Be very careful with wildcards in sudoers.

Auditing and Monitoring

Once everything is configured, don’t just leave it alone — enable logging so you know who is using sudo and what they’re doing:

# View sudo logs on Ubuntu/Debian
grep sudo /var/log/auth.log

# View sudo logs on CentOS/RHEL
grep sudo /var/log/secure

# Example output:
# Mar 15 10:23:45 server sudo: deployer : TTY=pts/1 ; PWD=/home/deployer ;
# USER=root ; COMMAND=/usr/bin/systemctl restart nginx

If your server uses journald (systemd-based), you can also use:

journalctl -u sudo --since "today"
# Or filter by a specific user:
journalctl SYSLOG_IDENTIFIER=sudo _UID=$(id -u deployer)

Configuring sudo correctly isn’t just a security concern — it also helps your entire team work smoothly without pinging an admin every time they need to restart a service. Remember three things: grant only the permissions that are actually needed, log every action, and always use visudo — no exceptions.

Share: