What is it? #
Linux is multi-user by design. Every process runs as some user, and that user determines what it can read, write and execute.
root is the superuser, with no restrictions. It can delete anything, change anything and bypass every permission check.
sudo lets an ordinary user run specific commands as root, with an audit trail. That is the normal way to administer a server — log in as yourself, elevate when needed.
Applications should run as their own dedicated user, not as root. If the application is compromised, the attacker gets that account's limited access rather than the whole machine.
Think of it like this #
An office building with different keycards. Most staff have access to their own floor. The building manager has a master key, kept in a safe and signed out when needed.
Handing every employee the master key would be convenient right up until the first mistake.
Simple example #
You set up a server. You create a personal account with sudo access, disable direct root login, and create a separate unprivileged account for the application to run under.
Code #
# Who am I, and who else exists?
whoami
id # user id, group id, group memberships
who # who is currently logged in
cat /etc/passwd # all accounts (system and human)
# Creating a human user with sudo access
sudo adduser ravi # interactive: creates home dir, sets password
sudo usermod -aG sudo ravi # Debian/Ubuntu: add to the sudo group
# sudo usermod -aG wheel ravi # RHEL/Rocky: the wheel group
# Creating a service account for an application
sudo useradd --system \
--home-dir /srv/app \
--shell /usr/sbin/nologin \
appuser
# --system: no password ageing, low UID
# --shell nologin: this account cannot log in interactively
sudo chown -R appuser:appuser /srv/app
# Using sudo
sudo systemctl restart nginx # run one command as root
sudo -u appuser ./manage.py # run as a different user
sudo -i # an interactive root shell (use sparingly)
# What can I run with sudo?
sudo -l
/etc/passwd format
appuser:x:998:998::/srv/app:/usr/sbin/nologin
│ │ │ │ │ └── login shell (nologin = cannot log in)
│ │ │ │ └── home directory
│ │ │ └── primary group id
│ │ └── user id (UID). Below 1000 is conventionally a system account.
│ └── x means the password hash lives in /etc/shadow, not here
└── username
Why an application should not run as root
running as root running as appuser
any file can be read only files the app owns or is granted
any file can be deleted damage limited to its own data
can bind any port needs a reverse proxy for port 80/443
a bug becomes a takeover a bug stays contained
How it works #
id shows your numeric user ID and group memberships, which is what permission checks actually use. Names are for humans; the kernel works with numbers.
adduser is the friendly wrapper: it creates the home directory, sets up a group and prompts for a password. useradd is the lower-level command with explicit flags.
Adding a user to the sudo group is what grants elevation. The -a in usermod -aG means append — leaving it out replaces all the user's groups, which is a classic way to lock yourself out.
The service account uses --shell /usr/sbin/nologin, so even if someone obtains its credentials, they cannot open a shell with it. Combined with --system, it is clearly not a human account.
chown -R appuser:appuser /srv/app gives the application ownership of its own directory, which is all it needs.
sudo logs every command it runs, so there is a record of who did what. That audit trail is a real reason to prefer sudo command over sudo -i followed by a shell session.
Ports below 1024 require privilege, which is one reason applications sit behind a reverse proxy rather than binding port 80 directly.
Real-world use #
The standard server setup is: disable direct root SSH login, create a personal account with sudo and a key, and run each application under its own unprivileged user.
Container images follow the same principle. An image that runs as root gives a container escape far more to work with, which is why production images specify a USER.
In audits and incident reviews, "what was running as root" is one of the first questions. Reducing that list is one of the cheapest security improvements available.
Locking yourself out is a real risk when editing sudo configuration or group membership. Keeping a second session open while making changes means you can undo a mistake.
Shared accounts are worth avoiding. When several people log in as the same user, the audit log tells you nothing about who did what.
Common mistakes #
- Running the application as root because it was easier during setup.
- Using
usermod -Gwithout-a, removing the user from all other groups. - Leaving root SSH login enabled with a password.
- Sharing one account between several people, destroying accountability.
- Giving a service account a real login shell it does not need.
Practice #
On a test machine, create a personal user with sudo access and a service account with no login shell. Give the service account ownership of an application directory, then confirm with "id" and "ls -l" that the ownership and groups are what you expect. Finally, try to open a shell as the service account and confirm it is refused.