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.
मित्रांनो, प्रत्येक DevOps job Linux server वरून सुरू होते. आज आपण एक नवीन Ubuntu machine घेऊन team साठी तयार करू: users तयार करणे, गरज तिथेच sudo, root password login बंद, आणि SSH keys ने प्रवेश. प्रत्येक step हाताने करू, आणि प्रत्येक step नंतर result तपासू.
दोस्तों, हर DevOps job Linux server से शुरू होती है. आज हम एक नई Ubuntu machine लेकर team के लिए तैयार करेंगे: users बनाना, जरूरत पर ही sudo, root password login बंद, और SSH keys से प्रवेश. हर step हाथ से करेंगे, और हर step के बाद result जाँचेंगे.
What you will build in this project
- A fresh Ubuntu server with a safe hostname and updated packages.
- Named users for developers and operators, each with their own home folder.
- Sudo for only the people who need it, with a clear audit trail.
- 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.
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.
खूप students थेट /etc/sudoers edit करतात आणि एका typo ने स्वतःला बाहेर करतात. नेहमी /etc/sudoers.d/ मध्ये file ठेवा आणि बाहेर पडण्यापूर्वी sudo visudo -cf ने check करा. हा नियम लक्षात ठेवा.
बहुत students सीधे /etc/sudoers edit करते हैं और एक typo से खुद को बाहर कर लेते हैं. हमेशा /etc/sudoers.d/ में file रखें और बाहर निकलने से पहले sudo visudo -cf से check करें. यह नियम याद रखिए.
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.
मित्रांनो, आज तुम्ही company अपेक्षेप्रमाणे server तयार केला: named users, group ला sudo, SSH keys चालू, SSH साठी password बंद, आणि शेवटी छोटी checklist. Practice VM वर स्वतःसाठी आणखी एक user तयार करून key steps न बघता पुन्हा करा.
दोस्तों, आज आपने company की उम्मीद के मुताबिक server बनाया: named users, group को sudo, SSH keys चालू, SSH के लिए password बंद, और अंत में छोटी checklist. Practice VM पर अपने लिए एक और user बनाकर key steps बिना देखे दोहराएँ.
Lab: try at home
- Create a practice VM (local Multipass, VirtualBox, or a free-tier cloud instance).
- Set hostname lab-linux-01 and update packages.
- Create users dev1 and ops1. Put only ops1 in an ops group with sudo.
- Generate an ed25519 key on your laptop and install the public key for dev1.
- Turn off PasswordAuthentication and PermitRootLogin, then reload sshd.
- From your laptop, prove key login works and password login fails.
- 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.