Linux Admin

Linux User & Service Management: useradd, sudo, systemctl, journalctl

Part of pathway: Linux Mastery: 300 Commands

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 -G without -a. Wipes existing group memberships. Always -aG.
  • Editing /etc/sudoers with vim directly. Bad syntax locks out sudo. Use visudo.
  • Forgetting daemon-reload after editing unit files. Systemd caches unit definitions. Reload after edits.
  • systemctl restart when reload works. Restart drops connections; reload re-reads config without dropping. Many services support reload (nginx, apache, ssh).
  • Checking status of an old / failed service. systemctl status doesn’t scroll its log buffer; use journalctl -xeu SERVICE for the full story.
  • userdel without -r. Leaves orphaned files in /home/alice/ owned by a freed UID. Next user with that UID inherits them.

Conclusion

Five habits:

  1. visudo, never raw editor on sudoers.
  2. usermod -aG, never bare -G.
  3. systemctl daemon-reload after every unit-file edit.
  4. journalctl -xeu SERVICE for the full story when something fails.
  5. 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:

Leave a Reply