newerkey notes
// devops · 18 June 2026 · 4 min read
DevOps · part 1

Setting Up a Linux User with a Non-Interactive Shell

Why service accounts should not be able to log in — and how /sbin/nologin enforces the principle of least privilege at the OS level.

linux users security least-privilege fundamentals

This is Day 1 of my #DevOpsFromZero series on KodeCloud.

The Task

Create a user named john with 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:

DetailValue
Hostnamestapp02
SSH Usersteve
ShellBash (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

ConceptWhat It Means
Non-interactive shellBlocks login access; account exists but can’t be used for SSH
/sbin/nologinThe standard shell path for non-interactive accounts
/etc/passwdThe file that stores all user accounts and their attributes
useradd -sCreates a user with a specified shell
usermod -sModifies the shell of an existing user
Least privilegeGive 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.

linux users security least-privilege fundamentals

// newerkey notes

Engineering notes on Linux, infrastructure, automation, and platform systems — written as I learn and build.

about these notes