Two Areas, One Article
Two of a Linux admin’s most-used tasks: managing users (creating accounts, granting permissions, controlling sudo) and managing services (starting, stopping, monitoring, scheduling daemons). Both happen multiple times a week. This article is a working reference for both, with the gotchas that bite in production.
The Files Behind User Management
Three files store almost everything:
/etc/passwd— user accounts. World-readable.username:x:UID:GID:GECOS:home:shell/etc/shadow— password hashes. Readable only by root./etc/group— group memberships.
The tools (useradd, passwd, usermod, etc.) are wrappers that update these files atomically with locks — do NOT edit them by hand unless you really know what you’re doing. Use vipw and vigr if you must.
Adding Users
useradd alice # bare minimum
useradd -m alice # with home directory
useradd -m -s /bin/bash alice # explicit shell
useradd -m -G sudo,docker alice # add to extra groups
useradd -m -d /opt/alice alice # custom home location
useradd -r postgres # system account (UID < 1000)
passwd alice # set initial password
Most distros also have adduser — an interactive Perl wrapper that asks you questions and creates a more complete user (home, shell, password, GECOS). Use adduser for interactive setup; useradd for scripts.
Modifying Users — usermod
usermod -aG docker alice # ADD alice to docker group (note -a)
usermod -G docker,wheel alice # REPLACE alice's groups (without -a, dangerous)
usermod -s /usr/bin/zsh alice # change shell
usermod -L alice # lock account
usermod -U alice # unlock
usermod -e 2026-12-31 alice # set expiration date
Always use -a with -G when adding to a group. Without -a, -G replaces the user’s entire group list, dropping them from groups they were in. This is the most common usermod accident.
Inspecting Users
id alice # UID, GID, group memberships
groups alice # just the groups
finger alice # GECOS info (often not installed)
getent passwd alice # consults nsswitch (LDAP, etc.)
last alice # login history
who # who's logged in now
w # who, plus what they're running
Removing Users
userdel alice # remove account, KEEP home directory
userdel -r alice # remove account AND home directory
deluser alice # interactive variant
Switching Identity — su and sudo
su # become root (need root password)
su - # root with root's environment
su - alice # become alice
su -c "cmd" alice # one command as alice
sudo command # run command as root (need YOUR password)
sudo -i # interactive root shell
sudo -u alice command # run as alice
sudo -l # list what YOU can sudo
sudo -k # invalidate cached credentials
sudo is preferred over su for almost every task: better logging, granular per-command permissions, no need to share root’s password, individual accountability via auth.log.
visudo — The Right Way to Edit sudoers
sudo visudo # always use visudo, never raw vim
sudo visudo -f /etc/sudoers.d/alice # safer: per-user file
visudo validates syntax before saving. A bad /etc/sudoers can lock out all sudo — including yours. Use visudo. Always.
Drop a per-user file in /etc/sudoers.d/ rather than editing the main file:
# /etc/sudoers.d/alice
alice ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
alice ALL=(ALL) /usr/bin/apt update
Groups
groupadd developers # create group
groupadd -g 1500 -r postgres # specific GID, system group
groupdel developers
groupmod -n new old # rename
gpasswd -a alice developers # add user
gpasswd -d alice developers # remove
gpasswd -A alice developers # make alice an admin of the group
Service Management — systemd
systemctl status nginx
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx # if service supports SIGHUP-style reload
systemctl enable nginx # start at boot
systemctl disable nginx # don't start at boot
systemctl mask nginx # prevent ANY start (even by dep)
systemctl unmask nginx
systemctl is-active nginx # script-friendly check
systemctl is-enabled nginx
systemctl daemon-reload # after editing unit files
Listing
systemctl list-units # all loaded units
systemctl list-units --type=service # just services
systemctl list-units --state=failed # what's broken
systemctl list-unit-files # ALL unit files (loaded or not)
systemctl list-timers # systemd timers (cron alternative)
Logs — journalctl
journalctl -u nginx # all of nginx's logs
journalctl -u nginx --since today
journalctl -u nginx -f # live tail
journalctl -u nginx -p err # only errors
journalctl --since "5 minutes ago"
journalctl -k # kernel only
journalctl -b -1 # previous boot
journalctl --disk-usage # how much space the journal uses
journalctl --vacuum-time=2weeks # keep only last 2 weeks
Custom Service — Minimal Unit File
Drop into /etc/systemd/system/myapp.service:
[Unit]
Description=My App
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/run.sh
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Then:
systemctl daemon-reload
systemctl enable --now myapp
journalctl -u myapp -f
Common Pitfalls
usermod -Gwithout-a. Wipes existing group memberships. Always-aG.- Editing
/etc/sudoerswith vim directly. Bad syntax locks out sudo. Usevisudo. - Forgetting
daemon-reloadafter editing unit files. Systemd caches unit definitions. Reload after edits. systemctl restartwhenreloadworks. Restart drops connections; reload re-reads config without dropping. Many services support reload (nginx, apache, ssh).- Checking status of an old / failed service.
systemctl statusdoesn’t scroll its log buffer; usejournalctl -xeu SERVICEfor the full story. userdelwithout-r. Leaves orphaned files in/home/alice/owned by a freed UID. Next user with that UID inherits them.
Conclusion
Five habits:
visudo, never raw editor on sudoers.usermod -aG, never bare-G.systemctl daemon-reloadafter every unit-file edit.journalctl -xeu SERVICEfor the full story when something fails.- Per-service files in
/etc/sudoers.d/over editing the main file.
Related Linux Admin troubleshooting
For common errors and fixes related to this topic, see: