This is Day 1 of my #DevOpsFromZero series on KodeCloud.
The Task
Create a user named
johnwith a non-interactive shell on App Server 2.
Simple on the surface. But before touching the server, it’s worth understanding why this task exists at all.
Why Would You Ever Need a Non-Interactive User?
Imagine a company runs automated backups every night at 2AM. That backup tool needs a Linux user account to operate under — it owns the processes, the temp files, the log entries. But here’s the thing: the backup tool doesn’t need to log in. It doesn’t need a terminal prompt. It doesn’t need to run arbitrary commands.
Think of it like giving a robot a limited keycard that only opens the filing cabinet, rather than handing it a master key to the entire building.
This is the principle of least privilege in action: the account gets exactly enough access to do its job — copy the data — but zero power to delete files, change system settings, or poke around where it shouldn’t.
A non-interactive shell like /sbin/nologin enforces this at the OS level. If anyone (or anything) tries to SSH in as john, the connection is immediately terminated. No prompt. No shell. No risk.
The Infrastructure
This task runs on the Nautilus project environment from KodeCloud. App Server 2 details:
| Detail | Value |
|---|---|
| Hostname | stapp02 |
| SSH User | steve |
| Shell | Bash (steve’s shell — not john’s!) |
ssh steve@stapp02
Step-by-Step: What I Did
1. Connect and Check Context
Before running anything, verify who you are and what environment you landed in:
whoami
# steve
steve is not root. That matters — only root can create users, so sudo is needed.
2. Create the User — First Attempt (The Omission)
My first instinct was:
sudo useradd john
The command ran. No errors. Looked fine.
Then I verified in /etc/passwd:
grep john /etc/passwd
# john:x:1001:1001::/home/john:/bin/bash
See the issue? The last field — the shell — defaulted to /bin/bash. That’s a fully interactive shell. The exact opposite of what was required.
A command exiting without error doesn’t mean it did what you intended. Always verify.
3. Fix It — Without Deleting the User
I could have deleted john and started over, but that’s the heavy-handed approach. Linux gives you usermod to modify existing users:
sudo usermod -s /sbin/nologin john
Then verified again:
grep john /etc/passwd
# john:x:1001:1001::/home/john:/sbin/nologin
The shell field now shows /sbin/nologin. Task complete. ✅
The Right Command from the Start
For the record, the correct one-liner to create john with a non-interactive shell:
sudo useradd -s /sbin/nologin john
The -s flag sets the shell at creation time. Simple, explicit, intentional.
Key Concepts Recap
| Concept | What It Means |
|---|---|
| Non-interactive shell | Blocks login access; account exists but can’t be used for SSH |
/sbin/nologin | The standard shell path for non-interactive accounts |
/etc/passwd | The file that stores all user accounts and their attributes |
useradd -s | Creates a user with a specified shell |
usermod -s | Modifies the shell of an existing user |
| Least privilege | Give accounts only the access they need — nothing more |
Closing Thought
The bigger lesson from this exercise isn’t the useradd syntax. It’s the mindset:
Not every mistake requires deletion. Understand what you have, then modify deliberately.
Part of my #DevOpsFromZero series — documenting real KodeCloud tasks with the commands, the reasoning, the mistakes, and the principles behind every decision.