Setting Up a Linux User with a Non-Interactive Shell
This is Day 1 of my #100DaysOfDevOps 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!) |
Connect via:
ssh steve@stapp02
Enter the password when prompted.
Step-by-Step: What I Did
1. Connect and Check Context
Before running anything, I verified who I was and what environment I landed in:
whoami
# steve
steve is not root. That matters — only root can create users, so I'll need sudo.
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.
💡 Lesson: 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 in a single step:
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 |
What I'd Do Differently
Run the full command correctly the first time:
sudo useradd -s /sbin/nologin john
And always verify immediately with:
grep john /etc/passwd
Don't trust exit codes. Trust the source of truth.
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.
Following along? Drop a comment below or connect with me on LinkedIn. See you on the next one
#100DaysOfDevOps #Linux #DevOps #KodeCloud #Beginner


