Ravindra BagaleCourses & study guides मराठी

Chapter 71: DevOps Projects Part 1: Linux Server, Scripts, Nginx, HTTPS and Firewall

71.1 Project 1: Set up a Linux server with users, sudo and SSH keys

Friends, every DevOps job starts on a Linux server. Today we take a fresh Ubuntu machine and make it ready for a team: create users, give sudo only where needed, lock the root password login, and let people enter with SSH keys. We do every step with our own hands, and after each step we check the result.

What you will build in this project

  1. A fresh Ubuntu server with a safe hostname and updated packages.
  2. Named users for developers and operators, each with their own home folder.
  3. Sudo for only the people who need it, with a clear audit trail.
  4. SSH key login, root password login turned off, and a quick connection test from a laptop.

1. Start from a real company story

At Infosys in Pune, a new Ubuntu server was ordered for the badge API team. The cloud team created the machine and gave the root password to three developers on a Slack message.

Within a week, one developer left the company. Nobody rotated the root password. Two days later someone logged in as root from an unknown IP and installed a crypto miner. The bill jumped by ₹42,000 in one weekend.

The team lead, Priya, said: never share root passwords again. Every person gets their own user. Login is only with SSH keys. Sudo is given only to operators, and every sudo command is logged.

Today we rebuild that server the safe way, one small step at a time.

Shared root passwordthree people know itCreate named usersone account per personAdd SSH public keyspassword login offSudo only for opsevery command is logged
Picture 1: from a shared root password to named users

2. Meet the server and update it

Step 1: Check the operating system

Why: Before we change anything, we confirm what we are standing on.

What: The operating system (OS) is the base software of the server. Ubuntu and Amazon Linux are common in companies. We read the OS name and the kernel version so we know which commands will work.

Example 1: Read the OS pretty name

Type this:

cat /etc/os-release | grep PRETTY_NAME

You will see:

PRETTY_NAME="Ubuntu 24.04.1 LTS"

What it means: This server runs Ubuntu 24.04 LTS. LTS means long-term support, which companies prefer.

Example 2: Read the kernel version

Type this:

uname -r

You will see:

6.8.0-1015-aws

What it means: The kernel is the heart of Linux. AWS images often have -aws in the name.

Example 3: See who you are and whether you are root

Type this:

whoami; id

You will see:

ubuntu
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),27(sudo)

What it means: The default cloud user is often ubuntu or ec2-user. It already has sudo. We will add named users next.

Step 2: Set a clear hostname

Why: A random name like ip-172-31-12-4 is hard to remember in logs.

What: A hostname is the friendly name of the server. Companies use a pattern like env-role-number, for example prod-badge-01.

Example 4: See the current hostname

Type this:

hostnamectl --static

You will see:

ip-172-31-12-4

What it means: This is the default AWS name. We will replace it.

Example 5: Set a new hostname

Type this:

sudo hostnamectl set-hostname prod-badge-01 && hostnamectl --static

You will see:

prod-badge-01

What it means: The static hostname is now prod-badge-01. New shells will show it in the prompt.

Example 6: Put it in /etc/hosts for local name lookup

Type this:

grep -q 'prod-badge-01' /etc/hosts || echo '127.0.1.1 prod-badge-01' | sudo tee -a /etc/hosts; grep prod-badge-01 /etc/hosts

You will see:

127.0.1.1 prod-badge-01

What it means: Some tools resolve the hostname locally. This line keeps them happy.

Step 3: Update packages safely

Why: An unpatched server is an open door.

What: Packages are the programs installed from the OS repository. Updating them installs security fixes. We refresh the list first, then upgrade.

Example 7: Refresh the package list

Type this:

sudo apt-get update -y | tail -3

You will see:

Get:24 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Fetched 8,412 kB in 2s
Reading package lists... Done

What it means: apt now knows about the newest versions.

Example 8: Upgrade installed packages

Type this:

sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y | tail -5

You will see:

Setting up openssl ...
Processing triggers for man-db ...
0 upgraded, 0 newly installed, 0 to remove

What it means: noninteractive skips questions. On a fresh image you may see many packages upgrade.

Example 9: Install tools we need for this project

Type this:

sudo apt-get install -y openssh-server sudo curl ca-certificates | tail -3

You will see:

openssh-server is already the newest version.
sudo is already the newest version.
0 upgraded, 0 newly installed

What it means: These packages are usually present. The command is safe to repeat.

3. Create users the company way

Step 4: Add a developer user

Why: Each person gets one account. Never share accounts.

What: useradd creates a user. -m makes a home folder. -s sets the login shell. We use /bin/bash so the person gets a normal shell.

Example 10: Create user ananya for a developer

Type this:

sudo useradd -m -s /bin/bash ananya && getent passwd ananya

You will see:

ananya:x:1001:1001::/home/ananya:/bin/bash

What it means: User id 1001, home /home/ananya, shell bash. The x means the password hash is in /etc/shadow.

Example 11: Create user rohit for another developer

Type this:

sudo useradd -m -s /bin/bash rohit && ls -ld /home/rohit

You will see:

drwxr-x--- 2 rohit rohit 4096 Oct 28 10:01 /home/rohit

What it means: Only rohit (and root) can enter this home folder. That is the default safe mode.

Example 12: List human users with a home under /home

Type this:

getent passwd | awk -F: '$6 ~ /^\/home\// {print $1,$3,$6,$7}'

You will see:

ubuntu 1000 /home/ubuntu /bin/bash
ananya 1001 /home/ananya /bin/bash
rohit 1002 /home/rohit /bin/bash

What it means: Three human users. Service accounts like www-data are not listed because their home is not under /home.

Step 5: Set a temporary password and force a change

Why: Passwords are a backup, not the main door.

What: We set a temporary password so the person can unlock the account if keys fail. force_change makes them pick a new password on first login. Still, SSH keys will be the normal way in.

Example 13: Set a temporary password for ananya

Type this:

echo 'ananya:ChangeMe-Now-1' | sudo chpasswd && echo set

You will see:

set

What it means: Password is set. This is a practice value. In real life use a password manager and share it through a secure channel, never Slack.

Example 14: Force password change on next login

Type this:

sudo chage -d 0 ananya && sudo chage -l ananya | head -3

You will see:

Last password change                : password must be changed
Password expires                : never
Password inactive               : never

What it means: -d 0 marks the password as expired, so the next login asks for a new one.

Example 15: Lock a user who left the company

Type this:

sudo usermod -L rohit && sudo passwd -S rohit

You will see:

rohit L 2026-10-28 0 99999 7 -1

What it means: L means locked. The account still exists for file ownership, but password login is blocked. Remove SSH keys too when someone leaves.

Step 6: Create an operators group

Why: Group people by role, then give rights to the group.

What: A group is a named set of users. We create ops for people who may use sudo, and put only operators in it.

Example 16: Create the ops group

Type this:

sudo groupadd ops && getent group ops

You will see:

ops:x:1003:

What it means: Group id 1003. Empty for now.

Example 17: Add an operator named meera to ops

Type this:

sudo useradd -m -s /bin/bash -G ops meera && id meera

You will see:

uid=1003(meera) gid=1003(meera) groups=1003(meera),1004(ops)

What it means: -G adds a supplementary group. meera is in ops.

Example 18: See who is in ops

Type this:

getent group ops

You will see:

ops:x:1004:meera

What it means: Only meera. Developers stay out of this group.

4. Give sudo only where needed

Step 7: Sudo with a group file

Why: Sudo lets a normal user run one command as root, after a password or key check.

What: We drop a file in /etc/sudoers.d/ instead of editing the main sudoers file. That is safer. The file says: anyone in ops may run any command, and their commands are logged.

Example 19: Create a sudoers drop-in for ops

Type this:

printf '%s\n' '%ops ALL=(ALL:ALL) ALL' | sudo tee /etc/sudoers.d/ops >/dev/null && sudo chmod 440 /etc/sudoers.d/ops && ls -l /etc/sudoers.d/ops

You will see:

-r--r----- 1 root root 24 Oct 28 10:05 /etc/sudoers.d/ops

What it means: Mode 440 means only root can read it. Never use a world-writable mode on sudoers files.

Example 20: Check the file with visudo

Type this:

sudo visudo -cf /etc/sudoers.d/ops

You will see:

/etc/sudoers.d/ops: parsed OK

What it means: visudo -cf checks syntax without opening an editor. Always run this after a change.

Example 21: Prove meera can sudo and ananya cannot

Type this:

sudo -u meera sudo -n true && echo meera_ok; sudo -u ananya sudo -n true 2>&1 | head -1

You will see:

meera_ok
sudo: a password is required

What it means: meera is in ops so sudo works. ananya is not in ops. -n means non-interactive, so it fails fast without asking.

Ravindra Bagale's Tip

Many students edit /etc/sudoers directly and lock themselves out with one typo. Always use a file under /etc/sudoers.d/ and check it with sudo visudo -cf before you log out. Keep that rule.

5. SSH keys instead of passwords

Step 8: Make an SSH key on the laptop

Why: The private key stays on the laptop. The public key goes on the server.

What: ssh-keygen creates a key pair. We use ed25519, which is short and strong. The private key never leaves the laptop.

Example 22: Generate an ed25519 key with a comment

Type this:

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_badge -C 'ananya@infosys-badge' -N '' && ls -l ~/.ssh/id_ed25519_badge*

You will see:

-rw------- 1 ananya ananya 399 Oct 28 10:10 /home/ananya/.ssh/id_ed25519_badge
-rw-r--r-- 1 ananya ananya 104 Oct 28 10:10 /home/ananya/.ssh/id_ed25519_badge.pub

What it means: Private key mode 600. Public key is safe to copy. -N '' means empty passphrase for the lab; at work use a passphrase or an agent.

Example 23: Show the public key

Type this:

cat ~/.ssh/id_ed25519_badge.pub

You will see:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyMaterialOnly ananya@infosys-badge

What it means: This one line is what we paste into the server. It is not a secret.

Example 24: See the fingerprint

Type this:

ssh-keygen -lf ~/.ssh/id_ed25519_badge.pub

You will see:

256 SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789abcd ananya@infosys-badge (ED25519)

What it means: Fingerprints help you confirm you copied the right key.

Step 9: Install the public key on the server

Why: authorized_keys lists which public keys may enter this account.

What: We create ~/.ssh on the server user, set safe modes, and append the public key. Mode 700 on .ssh and 600 on authorized_keys are required, or sshd ignores the file.

Example 25: Prepare .ssh for ananya on the server

Type this:

sudo mkdir -p /home/ananya/.ssh && sudo chmod 700 /home/ananya/.ssh && sudo chown -R ananya:ananya /home/ananya/.ssh && ls -ld /home/ananya/.ssh

You will see:

drwx------ 2 ananya ananya 4096 Oct 28 10:12 /home/ananya/.ssh

What it means: Only ananya can enter this folder.

Example 26: Append the public key

Type this:

printf '%s\n' 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyMaterialOnly ananya@infosys-badge' | sudo tee -a /home/ananya/.ssh/authorized_keys >/dev/null && sudo chmod 600 /home/ananya/.ssh/authorized_keys && sudo chown ananya:ananya /home/ananya/.ssh/authorized_keys && wc -l /home/ananya/.ssh/authorized_keys

You will see:

1 /home/ananya/.ssh/authorized_keys

What it means: One key installed. Replace the example key with your real public key from the laptop.

Example 27: Test from the laptop (dry run of auth)

Type this:

ssh -i ~/.ssh/id_ed25519_badge -o BatchMode=yes -o ConnectTimeout=5 ananya@prod-badge-01 'echo login_ok && whoami'

You will see:

login_ok
ananya

What it means: BatchMode refuses password prompts. If you see login_ok, the key works.

Step 10: Harden sshd

Why: Close the doors you do not need.

What: sshd is the SSH server program. We turn off root password login and password login for everyone, then reload. Keep one active key session open while you test, so you do not lock yourself out.

Example 28: Write a drop-in config

Type this:

printf '%s\n' 'PasswordAuthentication no' 'PermitRootLogin no' 'PubkeyAuthentication yes' 'ChallengeResponseAuthentication no' | sudo tee /etc/ssh/sshd_config.d/99-harden.conf && cat /etc/ssh/sshd_config.d/99-harden.conf

You will see:

PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
ChallengeResponseAuthentication no

What it means: Drop-in files are easier to review than editing the main config.

Example 29: Test the config and reload

Type this:

sudo sshd -t && sudo systemctl reload ssh && echo reloaded

You will see:

reloaded

What it means: sshd -t checks syntax. reload applies changes without dropping current sessions.

Example 30: Confirm password login is refused

Type this:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -o BatchMode=yes ananya@prod-badge-01 true 2>&1 | head -1

You will see:

ananya@prod-badge-01: Permission denied (publickey).

What it means: Password path is closed. Only publickey remains. That is what we want.

6. Daily checks and cleanup habits

Step 11: Audit who can log in and who has sudo

Why: Once a month, print this list in a team meeting.

What: We combine passwd, group and sudoers data into a short report. Real companies like TCS and Wipro keep the same habit.

Example 31: List users with a login shell

Type this:

getent passwd | awk -F: '$7 ~ /bash|sh/ {printf "%s uid=%s home=%s\n",$1,$3,$6}'

You will see:

ubuntu uid=1000 home=/home/ubuntu
ananya uid=1001 home=/home/ananya
rohit uid=1002 home=/home/rohit
meera uid=1003 home=/home/meera

What it means: Quick view of human accounts.

Example 32: Show sudoers drop-ins

Type this:

sudo ls -l /etc/sudoers.d/ && echo '---' && sudo cat /etc/sudoers.d/ops

You will see:

total 4
-r--r----- 1 root root 24 Oct 28 10:05 ops
---
%ops ALL=(ALL:ALL) ALL

What it means: Only the ops group has a drop-in. Good.

Example 33: Show recent sudo use

Type this:

sudo grep -E 'sudo|COMMAND' /var/log/auth.log 2>/dev/null | tail -5 || sudo journalctl -u ssh -n 5 --no-pager

You will see:

Oct 28 10:15:01 prod-badge-01 sudo: meera : TTY=pts/0 ; USER=root ; COMMAND=/usr/bin/apt-get update

What it means: Every sudo command leaves a trail. This is how Priya proved who installed what after the miner incident.

Step 12: Remove a user the safe way

Why: When someone leaves, close every door.

What: We lock the account, remove keys, remove sudo group membership, and only then decide whether to delete the home folder after a backup.

Example 34: Remove meera from ops

Type this:

sudo gpasswd -d meera ops && getent group ops

You will see:

Removing user meera from group ops
ops:x:1004:

What it means: meera no longer has sudo.

Example 35: Remove all SSH keys for a locked user

Type this:

sudo rm -f /home/rohit/.ssh/authorized_keys && sudo ls /home/rohit/.ssh 2>/dev/null || echo 'no keys'

You will see:

no keys

What it means: Even a locked account can log in with a leftover key. Always delete keys.

Example 36: Archive and delete a home folder after backup

Type this:

sudo tar -czf /var/backups/rohit-home.tgz -C /home rohit && sudo userdel -r rohit && echo removed && ls /var/backups/rohit-home.tgz

You will see:

removed
/var/backups/rohit-home.tgz

What it means: -r removes the home folder. The tgz keeps files for 30 days in case something was needed.

Step 13: Firewall reminder before you leave

Why: SSH is useless if the port is blocked, and dangerous if the world can guess passwords.

What: On Ubuntu, ufw is a simple firewall front-end. Allow SSH before you enable it. We only open what we need.

Example 37: Allow OpenSSH then enable ufw

Type this:

sudo ufw allow OpenSSH && sudo ufw --force enable && sudo ufw status

You will see:

Rules updated
Firewall is active and enabled on system startup
Status: active
To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere

What it means: SSH stays open. Other ports stay closed until you allow them.

Example 38: See listening ports

Type this:

ss -tulpn | grep -E 'sshd|:22'

You will see:

LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3))

What it means: sshd is listening on port 22. That matches the firewall rule.

Example 39: Fail a bad login and find it in the log

Type this:

sudo grep 'Failed password\|Invalid user\|Connection closed' /var/log/auth.log 2>/dev/null | tail -3 || sudo journalctl -u ssh --since '10 min ago' --no-pager | tail -3

You will see:

Oct 28 10:20:11 prod-badge-01 sshd[2201]: Invalid user admin from 203.0.113.50 port 55122

What it means: Attackers scan the internet. With passwords off and keys on, these attempts fail.

7. What good looks like

Step 14: Acceptance checklist

Why: Do not call the server ready until every line passes.

What: Print a short checklist and tick each item. Flipkart and PhonePe platform teams use the same habit before handing a box to an app team.

Example 40: Users exist and have homes

Type this:

for u in ananya meera; do getent passwd $u | awk -F: '{print $1,$6,$7}'; done

You will see:

ananya /home/ananya /bin/bash
meera /home/meera /bin/bash

What it means: Both users are present with bash homes.

Example 41: Sudo only for ops

Type this:

sudo cat /etc/sudoers.d/ops; id ananya; id meera

You will see:

%ops ALL=(ALL:ALL) ALL
uid=1001(ananya) ...
uid=1003(meera) ... groups=...,ops

What it means: ananya has no ops. meera has ops.

Example 42: Key login works, password login fails

Type this:

ssh -i ~/.ssh/id_ed25519_badge -o BatchMode=yes ananya@prod-badge-01 'echo key_ok'; echo pass_test; ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -o BatchMode=yes ananya@prod-badge-01 true 2>&1 | head -1

You will see:

key_ok
pass_test
ananya@prod-badge-01: Permission denied (publickey).

What it means: This is the finish line for Project 1.

Check yourself

Q1. Why did the Infosys badge server get mined?

A shared root password was not rotated when a person left.

Q2. Which file lists SSH public keys for a user?

~/.ssh/authorized_keys

Q3. What mode should ~/.ssh have?

700 (drwx------)

Q4. How do you check a sudoers drop-in safely?

sudo visudo -cf /etc/sudoers.d/FILENAME

Q5. What does PermitRootLogin no do?

Root cannot log in over SSH.

Q6. Why use a group for sudo instead of naming each user?

You add or remove people from the group without editing sudoers again.

Friends, today you built a server the way companies expect: named users, sudo for a group, SSH keys on, passwords off for SSH, and a short checklist at the end. Did you understand? Let us try it once more. Create one more user for yourself on a practice VM and repeat the key steps without looking.

Lab: try at home

  1. Create a practice VM (local Multipass, VirtualBox, or a free-tier cloud instance).
  2. Set hostname lab-linux-01 and update packages.
  3. Create users dev1 and ops1. Put only ops1 in an ops group with sudo.
  4. Generate an ed25519 key on your laptop and install the public key for dev1.
  5. Turn off PasswordAuthentication and PermitRootLogin, then reload sshd.
  6. From your laptop, prove key login works and password login fails.
  7. Write a five-line checklist file proving each acceptance item.

Recap

  • Never share root passwords. One person, one user.
  • Sudo belongs on a group file under /etc/sudoers.d/, checked with visudo -cf.
  • SSH keys: private on the laptop, public in authorized_keys.
  • Modes matter: .ssh is 700, authorized_keys is 600, sudoers drop-ins are 440.
  • Turn off password and root SSH login only after key login is proven.
  • When someone leaves: lock the user, remove keys, remove group membership, then archive the home.