Module 2 · Labs
These five labs take you from a bare micro PC to a hardened, headless server you’ve tested — including deliberately locking yourself out and recovering, which is the single most valuable exercise in the module. The capstone (Lab 5) is your build log: a runbook complete enough for a stranger to reproduce your server. As always, commit as you go.
Lab 1 · The install
Section titled “Lab 1 · The install”Goal: install Debian headless on your micro PC and reach it over SSH. Exercises Lesson 2.1.
- Create Debian install media on a USB stick (balenaEtcher, or
ddwith extreme care). - Boot the micro PC from USB via the firmware boot menu.
- Install Debian: set a hostname, create your admin user, lock root (blank root password → sudo setup), and — critically — deselect the desktop environment, keeping the SSH server.
- Choose guided whole-disk partitioning (take LVM if offered).
- First boot: log in at the console, find the IP with
ip addr. - From your laptop:
ssh <user>@<ip>, then add ahomelabentry to~/.ssh/configand copy your key up withssh-copy-id. - Confirm
ssh homelabworks with your key, then unplug the monitor and keyboard. sudo apt update && sudo apt upgradeto bring it current.
Verify
Section titled “Verify”- The server has no desktop environment (it’s a text-only, minimal install).
- It’s headless — monitor unplugged, and you administer it entirely via
ssh homelab. -
ssh homelablogs you in using your key. - The system is fully updated.
Commit
Section titled “Commit”Start your build log now (build-log.md) and record every choice you made and why, as you go.
This file becomes Lab 5.
Lab 2 · Break glass
Section titled “Lab 2 · Break glass”Goal: deliberately lock yourself out, then recover — so that the day it happens by accident (and it will), you’re calm and know the path. Exercises Lessons 2.1 and 2.3.
This lab feels scary and is completely safe as long as you have physical access to the machine. That’s the lesson: a headless server is never truly unreachable if you can walk to it.
- Cause a lockout on purpose. Pick one:
- Enable ufw with
default deny incomingbut withoutufw allow sshfirst (the classic mistake from Lesson 2.3), then disconnect. Your SSH is now blocked. - Or: misconfigure
sshd_config(e.g. set a wrongAllowUsers) and restart ssh.
- Enable ufw with
- Confirm you’re locked out —
ssh homelabnow fails. - Recover via the physical console. Reattach the monitor and keyboard, log in locally, and
fix it:
sudo ufw allow ssh(or revert the sshd change andsudo systemctl restart ssh). - Confirm recovery —
ssh homelabworks again from your laptop. - Unplug the monitor again.
Verify
Section titled “Verify”- You locked yourself out over the network (confirmed
sshfailed). - You recovered from the physical console and restored SSH access.
- You can articulate your recovery path for a headless box.
Commit
Section titled “Commit”Add labs/02-break-glass.md: what you broke, how you recovered, and — importantly — the
general recovery procedure for a locked-out headless server. This is a runbook you may
genuinely need. Note the lesson: always keep a second session open, and physical access is the
ultimate backstop.
Lab 3 · Hardening checklist
Section titled “Lab 3 · Hardening checklist”Goal: apply the full day-one hardening and prove it with a scan. Exercises Lesson 2.3.
Work the checklist, keeping a second SSH session open throughout:
- Confirm key login works (safety session), then set in
/etc/ssh/sshd_config:PasswordAuthentication no,PermitRootLogin no. Restart ssh and test in a new terminal. - Firewall:
ufw default deny incoming,ufw default allow outgoing,ufw allow ssh,ufw enable. Verify withufw status verbose. - Install and enable
fail2ban. Checksudo fail2ban-client status sshd. - Enable
unattended-upgrades. - Confirm root is locked and review
getent group sudo. - Prove it. From your laptop:
nmap -Pn homelab. Confirm only SSH (22) is open. - Bonus: open
/var/log/auth.logand see the real failed-login attempts from the internet.
Verify
Section titled “Verify”- Password SSH is refused; key SSH works; root SSH is denied.
-
ufw statusshows default-deny inbound with only SSH allowed. - fail2ban and unattended-upgrades are both active.
-
nmapfrom another machine shows only port 22.
Commit
Section titled “Commit”Add the completed hardening checklist to your build log, including the nmap output as
proof. This before/after evidence is exactly what makes the deliverable impressive.
Lab 4 · Service autopsy
Section titled “Lab 4 · Service autopsy”Goal: understand a systemd service inside-out and practice the troubleshooting method by breaking and fixing one. Exercises Lessons 2.2 and 2.4.
- Install a service.
sudo apt install nginx. It starts automatically. - Interrogate it using only
systemctlandjournalctl. Answer, in writing:- Is it active? Is it enabled (will it start at boot)? (
systemctl status nginx) - What’s its main PID?
- What does
sudo systemctl stop nginxthenstartthenrestartdo — and how does the status change at each step? - Where are its logs? (
journalctl -u nginx)
- Is it active? Is it enabled (will it start at boot)? (
- Break it on purpose. Introduce a syntax error into an nginx config file under
/etc/nginx/, thensudo systemctl restart nginx. It fails to start. - Diagnose it with the method (Lesson 2.4): note the
symptom, run
systemctl status nginxandjournalctl -xe, read the error, form one hypothesis, fix the one thing, restart, verify. (nginx even hassudo nginx -tto test config — discover this via the logs.) - Confirm the service is healthy again and reachable: from your laptop, after
sudo ufw allow 80, browse tohttp://homelaband watch the request land injournalctl -u nginx -f.
Verify
Section titled “Verify”- You can explain what starts nginx, whether it’s enabled, and where it logs.
- You broke it, diagnosed it from the logs (not by guessing), and fixed it.
- You saw a real request arrive in the live logs.
Commit
Section titled “Commit”Add labs/04-service-autopsy.md documenting the service’s anatomy and your break/diagnose/fix
walkthrough — narrated as the six-step method, so it doubles as troubleshooting practice.
Lab 5 · The build log
Section titled “Lab 5 · The build log”This is the module’s deliverable. Turn everything you did into a build log good enough that a stranger could reproduce your server. Exercises Lesson 0.5 as much as anything technical.
The assignment
Section titled “The assignment”Produce build-log.md — a combined README + runbook (Lesson 0.5)
for your server that covers, in order someone could follow:
- Hardware — what machine, specs, why.
- Install — the choices you made in the Debian installer and why (headless, no desktop, partitioning).
- Network — how it gets its address, its hostname, your
~/.ssh/configentry (redact real IPs if you’ll make this public — or use thehome.lanname). - The hardening checklist — completed, with your
nmapoutput as proof. - Services — what’s running (nginx from Lab 4) and how it’s configured.
- Recovery — your break-glass procedure from Lab 2.
- Gotchas — every mistake you made and what you learned. (These are the most valuable part; don’t sanitize them out.)
Verify
Section titled “Verify”- A competent stranger could rebuild your server from this document alone.
- It includes the hardening checklist and the
nmapproof. - It’s structured with headings and skimmable (Lesson 0.5).
- No real secrets or private keys are in it (recall Lesson 0.4); redact IPs if publishing.
Commit
Section titled “Commit”git add build-log.md labs/git commit -m "Add server build log and hardening checklist"git pushPublish it (or a redacted version) as a post on your site later — “How I built and hardened my first Linux server” is a genuinely strong portfolio piece, because it shows you don’t just run commands, you understand and document a system.
Module 2 checkpoint
Section titled “Module 2 checkpoint”- My server runs headless; I administer it exclusively over SSH with keys (Lab 1)
- I can create, enable, and debug a systemd service and read its logs (Lab 4)
- My firewall default-denies inbound; I can list exactly which ports are open and why (Lab 3)
- I’ve been locked out and recovered — and I know my recovery path (Lab 2)
- An
nmapscan of my server shows only the ports I intend (Lab 3) - My build log is committed and complete enough for a stranger to reproduce (Lab 5)
Deliverable
Section titled “Deliverable”Your server build log + hardening checklist (Lab 5), committed to your repo, with the
nmap proof included — your first real runbook, and evidence that you can stand up and secure a
Linux server from bare metal.
Next module: Module 3 · Build the Network → — where you take control of the network your server lives on.