Managing Users and Permissions on Linux: Practical Tips for Beginners

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

I recently onboarded a junior developer to the team, and the first question they asked was: “Should I use useradd or adduser to create a new user on the server?” — It sounds like a simple question, but it opened up a whole topic that even seasoned Linux users often get wrong.

After 3 years of managing over 10 VPS instances, I’ve personally been locked out of a server due to a misconfigured sudo setup, and watched a site go down for nearly 2 hours just because of wrong permissions on an upload directory. With users and permissions, one small mistake has immediate consequences — unlike regular code where you can still git revert.

1. Creating Users: useradd vs adduser — Which Should You Use?

These two commands look similar but behave quite differently.

useradd — Low-level, bare minimum

useradd is a low-level command that creates a user with minimal parameters. Without additional flags, it will not create a home directory, not set a reasonable default shell, and not create a password.

# Simple useradd — missing a lot
sudo useradd newuser
# Result: user exists but has no home dir, default shell is /bin/sh

# Need to add the right flags to make it usable
sudo useradd -m -s /bin/bash -c "Nguyen Van A" newuser
# -m: create home directory
# -s: specify shell
# -c: comment (usually the full name)

adduser — High-level, interactive, more user-friendly

adduser on Debian/Ubuntu is a wrapper script that automatically creates a home directory, prompts for a password, and fills in the comment field. On CentOS/RHEL, adduser is just a symlink to useradd — meaning they behave identically. If you’re working on Fedora, the setup process is similar — see Installing Fedora Server and Initial Configuration for the initial steps you shouldn’t skip.

# adduser on Ubuntu/Debian — interactive, easier to use
sudo adduser newuser
# Script will prompt: password, full name, phone...
# Automatically creates /home/newuser and copies skeleton from /etc/skel

Which one should you use?

  • useradd: Available on every distro, ideal for automation scripts, but you must manage every flag yourself — easy to miss something
  • adduser: User-friendly for interactive use, only available on Debian-based systems, not suitable for cross-platform scripts

Bottom line: Manual setup on Ubuntu/Debian → use adduser. Writing automation scripts or running on CentOS/RHEL → use useradd -m -s /bin/bash with all the necessary flags.

2. Permissions: Numeric chmod vs Symbolic chmod

Many people learn by memorizing “magic numbers” without understanding why — then when stuck, they just chmod 777 and move on, later wondering why their site got exploited.

Numeric chmod (Octal) — Fast once you know it

# Formula: read=4, write=2, execute=1
# 755 = rwxr-xr-x
# Owner: 4+2+1=7 | Group: 4+1=5 | Others: 4+1=5
chmod 755 /var/www/html

# 644 = rw-r--r-- (regular file)
chmod 644 index.html

# 600 = rw------- (sensitive file: SSH key, password file)
chmod 600 ~/.ssh/id_rsa

# 700 = rwx------ (directory for owner use only)
chmod 700 ~/private

Symbolic chmod — Easier to understand when starting out

# u=user/owner, g=group, o=others, a=all
# +add, -remove, =set exactly

# Add execute permission for owner
chmod u+x deploy.sh

# Remove write permission for group and others
chmod go-w config.yaml

# Set exactly: owner rwx, group r-x, others nothing
chmod u=rwx,g=rx,o= script.sh

When to use which?

  • Octal: Faster to type, but requires mental math — easy to get wrong when you’re tired
  • Symbolic: More explicit, only changes the bits you intend without touching the rest — safer when modifying existing permissions

Practical tip: Use stat -c "%a %n" filename to view permissions in octal format — more convenient than ls -l when you need to copy the value elsewhere.

# View permissions in octal format
stat -c "%a %n" /etc/passwd
# Output: 644 /etc/passwd

# Check multiple files at once
stat -c "%a %n" /var/www/html/*

3. Ownership: chown and chgrp

Correct permissions with the wrong owner still results in access denied. This is a common issue when deploying web apps — files created by root can’t be read by nginx/apache running as www-data. The same principle applies when deploying Node.js applications with Docker, where container user mismatches cause identical headaches.

# Change owner
sudo chown www-data /var/www/html/uploads

# Change both owner and group at once
sudo chown www-data:www-data /var/www/html/uploads

# Recursively change entire directory — be careful with -R!
sudo chown -R www-data:www-data /var/www/html/

# Change group only
sudo chgrp developers /var/log/app.log

Warning: When using chown -R, make sure the path is correct. I’ve seen someone mistype the path and chown the entire /var directory — afterward, many services couldn’t start because ownership was wrong across the board.

4. Sudo: Granting Permissions the Right Way

The two most common extremes are: adding everyone to the sudo group for convenience, or locking things down completely so that anything requiring root needs a separate SSH account. Both approaches have their own problems.

Option 1: Add to the sudo group — Simple but risky

# Ubuntu/Debian
sudo usermod -aG sudo username

# CentOS/RHEL/Fedora
sudo usermod -aG wheel username

# Check which groups a user belongs to
id username
groups username

Option 2: Grant specific permissions via sudoers — Safer

# ALWAYS use visudo to edit — it checks syntax before saving
sudo visudo

# Or create a separate file in /etc/sudoers.d/ (recommended)
sudo visudo -f /etc/sudoers.d/deployer

# Allow user 'deployer' to reload nginx without a password
deployer ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nginx

# Allow group 'developers' to view logs
%developers ALL=(ALL) NOPASSWD: /usr/bin/tail -f /var/log/nginx/access.log

Why is full sudo access dangerous?

  • Full sudo group access: Convenient for dev environments, but users can do anything on production — including accidentally deleting things
  • Specific sudoers rules: Follows the principle of least privilege — only grants what’s needed, nothing more

On production, I always use specific sudoers rules for service accounts. The deploy user can only reload nginx and restart the app service — nothing else, even if they wanted to. For a broader look at hardening your server after initial setup, Things to Do After Installing Ubuntu Server 22.04 covers the steps that prevent 2 AM disasters.

5. Auditing Permissions — Don’t Skip This Step

Knowing how to set permissions is one thing; verifying that your current system has them right is another. These are commands I use regularly when reviewing a new server — especially one handed over from someone else. If you ever suspect something more serious has happened, the guide on detecting and responding to a hacked server is worth keeping in your back pocket.

# Find files with SUID bit set (potential security risk)
find / -perm /4000 -type f 2>/dev/null

# Find world-writable files — anyone can write to them, extremely dangerous
find /var/www -perm -002 -type f 2>/dev/null

# Find files with no owner (orphan files)
find /home -nouser -o -nogroup 2>/dev/null

# Check what sudo commands a user can run
sudo -l -U username

Conclusion: Get It Right from the Start

  • Production servers: Create dedicated service users (don’t use root), grant minimal permissions, use specific sudoers rules for each required command
  • Dev/staging: More relaxed, but developers still shouldn’t use root directly — it builds bad habits that carry over to production
  • Web server files: Owner should be the web user (www-data/nginx), 644 for files, 755 for directories, 600 for sensitive files
  • Automation scripts: Use useradd with all the necessary flags — don’t rely on each distro’s default behavior

One rule I’ve applied from the start: chmod 777 is a sign of laziness, not a solution. When you hit a permission denied error, stop and understand the root cause before throwing the doors wide open.

Practice on a VM or container first, master each command, then move to production — that’s how I learned, and the advice I always pass on to newcomers in the field. If you want a consistent, isolated environment to practice safely, Vagrant is an excellent choice for spinning up reproducible dev environments without risking your main system.

Share: