
September 11, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
When you deploy a Laravel app or WordPress site on Ubuntu, you must manage users and groups on Linux correctly or permissions break within days. A web app owned by root blocks PHP-FPM writes. A cron job running as the wrong user reads a stale release path. On production servers I maintain, user and group setup is not optional housekeeping—it is part of every Linux system administration workflow. This guide walks through real commands, config files, and fixes you can copy on Ubuntu 22/24 today.
useradd/usermod and groupadd/gpasswd, then verify with id and the files /etc/passwd, /etc/shadow, and /etc/group. Grant admin access through the sudo group, not shared root passwords.What files does Linux use to manage users and groups?
Linux stores account data in plain-text databases under /etc. You rarely edit them by hand, but you must know what each file controls when debugging login or permission errors.
/etc/passwd— username, UID, GID, home directory, default shell./etc/shadow— password hashes and expiry rules (root-readable only)./etc/group— group name, GID, and member list./etc/gshadow— group passwords and admin members (seldom used on modern servers)./etc/sudoers— who may run commands as root viasudo.
A typical /etc/passwd line looks like this:
deploy:x:1001:1001:Deploy User:/home/deploy:/bin/bash The fields are: login name, placeholder password (x means hash lives in shadow), UID, primary GID, GECOS comment, home path, login shell.
On Ubuntu, system accounts often use UIDs below 1000. Human and app accounts usually start at 1000. Keep UIDs stable across servers if you NFS-mount storage or rsync backups between hosts. Changing a UID after files exist is painful—every owned file must be updated.
For deeper permission work, pair this with our guide on Linux file permissions and ACLs. The UID and GID numbers you assign here directly drive every chmod decision on the filesystem.
How do you create, modify, and delete users on Linux?
On Debian and Ubuntu, prefer adduser for interactive human accounts and useradd for scripted service accounts. Both wrap the same underlying databases.
Create a human user interactively
sudo adduser alice Ubuntu prompts for password and optional profile fields. Verify the account:
id alice
getent passwd alice Create a service account without login shell
App deploy users should not accept SSH passwords. I use this pattern on Laravel servers:
sudo useradd -m -s /bin/bash -G www-data deploy
sudo mkdir -p /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo nano /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh Lock password login so only keys work:
sudo passwd -l deploy Generate a strong passphrase for any break-glass account with the password generator if you store emergency credentials offline.
Modify an existing user
sudo usermod -aG sudo alice
sudo usermod -d /var/www/alice -m alice
sudo usermod -s /usr/sbin/nologin oldbatch The -aG flag appends groups. Without -a, usermod -G replaces the entire supplementary group list—a common production mistake.
Delete a user safely
- Confirm no cron jobs or systemd units reference the account (cron jobs on Linux often hard-code usernames).
- Archive or reassign owned files:
sudo find / -user alice 2>/dev/null. - Remove the account:
sudo deluser --remove-home aliceon Ubuntu, orsudo userdel -r aliceelsewhere.
Our Ubuntu user management guide covers similar flows with desktop-focused notes. Server admins should still read both—desktop and headless setups diverge on defaults.
How do you create groups and manage membership on Linux?
Groups bundle permissions. A user has one primary group (stored in /etc/passwd) and zero or more supplementary groups (stored in /etc/group).
Create and inspect groups
sudo groupadd developers
getent group developers
groups alice Rename or change GID only before files depend on the number:
sudo groupmod -n devteam developers
sudo groupmod -g 1500 developers Add and remove members
sudo usermod -aG developers alice
sudo gpasswd -d alice developers
sudo delgroup developers Common Ubuntu groups worth knowing:
| Group | Typical purpose | Caution |
|---|---|---|
sudo | Full admin via sudo | Limit to trusted operators only |
www-data | Apache/Nginx and PHP-FPM on Debian/Ubuntu | App code must be readable, not writable, by this group |
docker | Run containers without root | Equivalent to root on many setups |
adm | Read log files in /var/log | Useful for support staff |
deploy (custom) | CI/CD release ownership | Pair with www-data for shared write dirs |
On sister sites I deploy with Deployer 7 and GitLab CI—projects like Notary Kathmandu—the deploy user owns releases while PHP-FPM runs as www-data. Shared directories such as storage/ and bootstrap/cache/ get group www-data and mode 2775 so new files inherit the group. That pattern prevents upload failures without opening the whole tree to the web server user.
Official reference: the Debian Administrator's Handbook section on user accounts documents these tools consistently across releases. For RHEL-family systems, see the Red Hat documentation on useradd and groupadd—flags differ slightly, but the concepts match.
How should you configure sudo and service accounts in production?
Shared root passwords are unacceptable on any server you care about. Grant privilege through sudo with scoped rules instead.
Safe sudo patterns
Add a user to the sudo group on Ubuntu:
sudo usermod -aG sudo alice For finer control, create a file in /etc/sudoers.d/—never edit /etc/sudoers directly without visudo:
sudo visudo -f /etc/sudoers.d/deploy Example: allow deploy to reload PHP-FPM without full root:
deploy ALL=(root) NOPASSWD: /bin/systemctl reload php8.3-fpm Validate syntax before saving—bad sudoers files can lock you out. Related reading: manage services on Linux with systemd.
Service account checklist
- Dedicated Unix user per app or per site on shared hosts.
- No password login; SSH keys or local socket auth only.
- Shell
/usr/sbin/nologinfor database-only accounts if they never need SSH. - Document UID/GID in your runbook or Ansible inventory.
- Rotate keys when staff leave—group membership persists until removed.
MySQL and PostgreSQL create their own system users (mysql, postgres) during package install. Do not run mysqld as root. When you automate database backups on Linux, run dump scripts as a user that can read credentials but cannot sudo.
For hosting clients who lack in-house ops staff, this is exactly the work covered under support and maintenance and domain registration and hosting—getting ownership right once saves hours of ticket noise later.
How do you troubleshoot UID, GID, and permission problems?
Most "it worked yesterday" Linux permission bugs trace back to a UID mismatch after restore, tarball extract, or manual chown.
Diagnose quickly
ls -la /var/www/example/current/storage
id deploy
id www-data
stat -c '%U:%G %a' /var/www/example/current/storage/logs Find orphaned files after deleting a user:
sudo find /var/www -nouser -o -nogroup 2>/dev/null Fix ownership recursively when you are sure of the target:
sudo chown -R deploy:www-data /var/www/example/shared/storage
sudo chmod -R ug+rwx /var/www/example/shared/storage
sudo find /var/www/example/shared/storage -type d -exec chmod g+s {} \; The setgid bit (g+s, shown as s in group execute) keeps new uploads group-writable by www-data.
UID collisions after migration
Restoring a backup onto a fresh VPS often maps files to the wrong names. User deploy might be UID 1001 on the old box but 1002 on the new one. The numeric UID on disk still says 1001—which now belongs to someone else entirely.
Fix options, in order of preference:
- Recreate users with explicit UIDs:
sudo useradd -u 1001 -o deploy(use-oonly when necessary). - Mass
chownafter confirming the correct mapping. - Re-deploy from Git instead of rsyncing
storage/with preserved numeric owners.
I've hit this during website migration work when clients move off cheap shared hosting. Always export /etc/passwd and /etc/group from the source server before cutover.
Audit and compliance basics
List human accounts with login shells:
getent passwd | awk -F: '$7 !~ /nologin|false/ {print $1, $3, $7}' Find members of privileged groups:
getent group sudo
getent group docker Pair this with Linux server monitoring and log rotation so audit trails do not fill the disk. Lock inactive accounts:
sudo passwd -l formeremployee
sudo usermod -L formeremployee External authority: the passwd(5) man page defines field layout, and Ubuntu documents adduser in the official server guide at ubuntu.com/server/docs.
More command reference lives in essential Linux commands for Ubuntu users and Linux process management. Firewalls matter too—a misconfigured sudo rule is an internal risk; pair user hygiene with iptables vs nftables hardening.
Key Takeaways
- Manage users and groups on Linux through
useradd,usermod,groupadd, andgpasswd—not by hand-editing/etc/passwd. - Always use
usermod -aGwhen adding supplementary groups; omitting-awipes existing memberships. - Separate deploy users from
www-data; use group ownership and setgid on shared write directories. - Grant admin rights via scoped
/etc/sudoers.d/files instead of sharing the root password. - Document UID/GID before migrations; fix numeric ownership before debugging application code.
- Audit
sudoanddockergroup membership regularly on every production VPS.
People Also Ask
What is the difference between a primary group and supplementary groups?
The primary group is the GID on the /etc/passwd line. It applies to new files the user creates unless overridden. Supplementary groups come from /etc/group and grant shared access—such as letting deploy also act as www-data on upload folders. Run id username to see both.
Should I use adduser or useradd on Ubuntu?
Use adduser for interactive human accounts—it handles home directories, skeleton files, and password prompts. Use useradd in shell scripts and Ansible when you need explicit flags for service accounts. Both update the same backend files.
How do I list all users on a Linux server?
Run getent passwd to list every passwd entry from local files and NSS sources like LDAP. Filter login-capable users with awk on the shell field. For group membership, run getent group groupname.
Why do files show numeric UID instead of a username after restore?
The username lookup failed because that UID has no matching entry in /etc/passwd. Recreate the user with the same UID or run chown to assign files to the correct account. This is one of the most common post-migration surprises on VPS hosts.
Build a clean account model before your next deploy
Manage users and groups on Linux with the same discipline you apply to firewall rules and database backups. Get UID, GID, and sudo scope right on day one, and PHP-FPM, cron, and CI pipelines stop fighting each other. Onboarding a new server takes less than an hour when you follow a checklist; fixing ownership across years of uploads takes days.
If you run production apps on Ubuntu and want ownership, sudo, and deploy users configured properly from the start, see the Adventure Third Pole Trek stack and other portfolio deployments for real examples—or read more from about me and Linux performance tuning basics. When you need hands-on help, contact us for server setup aligned with how you actually ship code.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

