su system
become someone else. literally.
The su man page is 200 lines long. You need one command and a password.
You need to be root. Or you need to be the postgres user to run a database command. Or you need to be www-data to test file permissions. You could log out, log back in as that user, do the thing, log out again, and log back in as yourself. That’s four steps and three password prompts for one command.
Or you could just become them. Right now. In this terminal. And switch back when you’re done.
That’s su. “Substitute user.” You type it, provide a password, and your shell identity changes. You are now someone else. Your permissions change. Your home directory changes. Everything the system uses to decide what you’re allowed to do — changed. One command.
On Windows, this concept doesn’t exist. “Run as different user” is buried in a right-click context menu that only works on some applications, requires a graphical login dialog, and still doesn’t change your current session. You’re still you. You just launched one program as someone else. su changes you.
Unless you’re running Windows then wtf none of this applies to you. But hey, come to the dark side, go install WSL2 and you can follow along. We’ll wait. Impatiently.
If you’re lazy like me (all sysadmins are!) then click here for the su cheat sheet.
Switch to root
su -
The - (or -l, or --login) makes it a login shell — you get root’s environment, root’s PATH, root’s home directory. Without the dash, you keep your own environment variables, which causes weird problems when commands can’t find things or configs load from the wrong place.
You’ll be prompted for root’s password. Not yours — root’s. This is the key difference between su and sudo. su needs the target user’s password. sudo needs yours.
Without the login shell (don’t do this)
su
Switches to root but keeps your environment. Your HOME is still your home directory. Your PATH might be missing root-only directories like /sbin. Commands might behave differently because they’re reading your config files, not root’s. Always use su - or su -l.
Switch to another user
su - postgres
Become the postgres user. Login shell loaded, home directory changed, environment set. You’ll need to know the postgres user’s password — or be root already, in which case su doesn’t ask for any password. Root can become anyone without credentials.
su - www-data -s /bin/bash
Some service accounts have /usr/sbin/nologin or /bin/false as their shell, which means su alone would fail. The -s flag forces a specific shell. Now you’re www-data with a bash prompt.
Run a single command as another user
su - postgres -c "pg_dump mydb > /tmp/backup.sql"
Becomes postgres, runs the command, and returns to your original user. No interactive session. One command, done.
su - root -c "systemctl restart nginx"
If you know root’s password and don’t have sudo configured, this is the way to run a single root command without staying in a root shell.
su vs sudo
This is the important part. Modern Linux systems prefer sudo for good reasons:
su |
sudo |
|
|---|---|---|
| Password needed | Target user’s password | Your own password |
| Logging | Logs the switch, not individual commands | Logs every command |
| Granularity | All or nothing — you’re root or you’re not | Per-command, per-user restrictions via sudoers |
| Shared credentials | Root password shared among admins | Each admin uses their own password |
| Revocation | Change root password and tell everyone | Remove one user from the sudo group |
su still has its place. When you’re already root and need to become a service account, su - postgres is the natural choice. When your system doesn’t have sudo configured (rare these days), su is your only option. But for day-to-day “I need root for this one command,” sudo is what you should be using.
Many modern distros (Ubuntu, Fedora) disable root login entirely and don’t set a root password — sudo is the only path to root. If su - asks for a password and you’ve never set one for root, that’s why it’s not working.
The flags that actually matter
| Flag | What it does |
|---|---|
- / -l |
Login shell — loads the target user’s full environment. Always use this. |
-c COMMAND |
Run a single command and return. |
-s SHELL |
Use a specific shell (overrides the target user’s default). |
-p |
Preserve environment (opposite of -l). Rarely what you want. |
“But I—”
Sure.
“I use su for everything.” Then you’re sharing the root password with everyone who needs admin access. When someone leaves the team, you change the root password and tell everyone the new one. When something breaks, you check the logs and see “root did it” with no indication of which human was behind the keyboard. sudo solves both problems.
“Root login is fine on my home machine.” Until you run a script that assumes it’s not root and does something unexpected with root privileges. Until you tab-complete the wrong path and rm something you can’t get back. The root account has no guardrails. sudo forces you to be explicit about what you’re escalating, one command at a time.
“I can’t remember the root password.” If you’re on Ubuntu or Fedora, there might not be one. These distros disable root login by default and rely on sudo. If you need su for a service account, use sudo su - postgres instead — it uses your sudo password to become root, then root switches to postgres without needing postgres’s password.
su cheat sheet
You made it. Or you skipped straight here. Either way, no judgment. Copy and paste these. Pin them. Tattoo them on your forearm. Whatever works.
| What you’re doing | Command |
|---|---|
| Switch to root (login shell) | su - |
| Switch to another user | su - username |
| Run one command as another user | su - username -c "command" |
| Force a shell for nologin users | su - username -s /bin/bash |
| Root → service account (no password) | su - postgres |
| Combo: sudo to root, then su | sudo su - postgres |
The one rule: Always use
su -(with the dash), never baresu. The dash loads the target user’s full environment. Without it, you’re root with your own user’s broken PATH and wrong home directory.