CoursesLinux essentialsWhere to go next

Where to go next

From fluency to hardening.

Beginner6 min · lesson 25 of 25

Learning to run a Linux machine is like getting comfortable in a large building where you work. You know which corridor leads where. You can read the small sign on every door, you know who is allowed into which room, and you can tell at a glance when a room is in use. Over the last stretch of this course, that is the fluency you built, and it is real.

You can move around the shell and the filesystem without stopping to think. You can read a permission string like -rw-r----- and know instantly who can open a file and who cannot. You know that every process runs as some user, that sudo is a controlled way to borrow the powers of root (the all-powerful administrator account that can change anything on the system), and that a service is a long-running program kept alive by systemd (the manager that starts, stops, and supervises everything on a modern Linux). You can pull one event out of days of logs with journalctl, list which programs are waiting for network connections with ss, and install or remove software with apt while knowing exactly where the files landed.

That is enough to run a real server. It is also enough to follow what Docker, Kubernetes, and a CI pipeline (continuous integration, the automated system that builds and tests your code every time it changes) are doing underneath, because all of them are orchestrating these same Linux parts. So the question now is not whether you can operate the machine. You can. The question is whether you can defend it.

A Fresh Install Trusts Almost Everyone

A brand-new Linux install is like an office on opening day. Every lock came with the same factory key, the front gate is propped open for the movers, and nobody has hung a single camera. It works. It also assumes everyone who walks up means well. Operating that machine and defending it are different skills, and you can see the gap with commands you already know how to read. Here is a normal, freshly installed Ubuntu server.

~/secopslog — bash
$ sudo ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=623,fd=14)) LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3)) LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=812,fd=4))

Look at the Local Address column. 0.0.0.0:22 means the SSH server (secure shell, the encrypted remote-login service) is listening on every network interface the machine has, so anyone who can route a packet to port 22 can knock on it. The resolver on 127.0.0.53 listens only on the loopback address, the machine's internal-only address, so it is reachable from the machine itself and nowhere else. You already know how to read this. The security question is this: for each open port, who out there can reach it, and should they?

~/secopslog — bash
$ sudo sshd -T | grep -Ei 'passwordauthentication|permitrootlogin'
permitrootlogin prohibit-password passwordauthentication yes

The most exposed of those is SSH, so look closer at it. sshd -T prints the server's effective settings after all config files are merged. passwordauthentication yes means anyone who reaches port 22 can sit there trying username and password combinations, forever, automated. Bots do exactly this to every server on the public internet within minutes of it appearing. permitrootlogin prohibit-password is a little better: the root account can log in with a key but not a password. Passwords are the weak link here, and they are switched on.

~/secopslog — bash
$ sudo nft list ruleset | wc -l
0

Zero lines. nftables (the packet filter built into the Linux kernel, the core of the operating system that talks directly to the hardware) has not one rule loaded. There is no host firewall deciding what to allow and what to drop. Every port you just saw is reachable from wherever the surrounding network lets packets travel. On a cloud server, the only thing standing between those ports and the whole internet might be a setting in a web console you have never opened.

~/secopslog — bash
$ sysctl net.ipv4.conf.all.accept_redirects net.ipv4.conf.all.send_redirects
net.ipv4.conf.all.accept_redirects = 1 net.ipv4.conf.all.send_redirects = 1

sysctl (the tool that reads and sets tunable settings inside the running kernel) shows two of the kernel's network defaults, and 1 means on. accept_redirects lets another machine on your network send an ICMP redirect (a low-level network control message) that tells your host to route traffic a different way. Left on, that is a small door an attacker on the same network can use to quietly bend your traffic through their own machine. There are dozens of these knobs, and a stock kernel sets many of them for convenience rather than safety.

~/secopslog — bash
$ sudo systemctl status auditd
Unit auditd.service could not be found.

And nobody is keeping a logbook. The audit daemon (auditd, a background service that records security-relevant events like a file being edited or a program being run as root) is not even installed. If someone did get in and add a user or change a config file, nothing on this host would have written it down. You would have no way to answer what happened, or when.

Test your key before you kill the password
Turning off SSH password login is usually the first hardening step, and it is the easiest way to lock yourself out of a cloud server that has no monitor to fall back on. Before you set PasswordAuthentication no and reload sshd, open a second terminal and confirm you can log in with your key. Keep that spare session open until you are certain the new setting works.

Hardening Turns The Same Knobs The Other Way

The Linux server hardening course takes the same four things you just looked at and turns each from open to closed. None of it is new Linux. It is the permissions, users, services, and networking you already understand, aimed at keeping people out instead of getting work done.

SSH stops taking passwords and takes only keys. A key is like a key cut for one specific lock: there is nothing to type, so there is nothing for a bot to guess. On modern Ubuntu and Debian you make this change in a small drop-in file inside /etc/ssh/sshd_config.d/, not in the main config, so a package update cannot quietly revert you. One detail trips people up: sshd uses the first value it finds for each setting, and it reads those drop-in files in alphabetical order. Cloud images often ship a 50-cloud-init.conf that turns password login back on, so you give yours a name that sorts ahead of it.

/etc/ssh/sshd_config.d/00-hardening.conf
# Read before 50-cloud-init.conf, so these values win.
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes

Reload SSH and check the same setting you looked at before. It now reads the other way.

~/secopslog — bash
$ sudo systemctl reload ssh && sudo sshd -T | grep -i passwordauthentication
passwordauthentication no

The firewall goes from empty to default-deny, written with nftables: drop everything coming in, then allow back only the few ports you actually serve. The kernel knobs get set for safety with sysctl, so accept_redirects and its neighbours read 0. A mandatory access control system (MAC, a layer that pens each program into only the files and actions it is meant to touch, so a hacked web server cannot roam the whole disk) is switched to enforcing mode, whether that is AppArmor, which Ubuntu ships, or SELinux, which Red Hat systems use. auditd gets installed with a real ruleset, so the logbook finally exists. Then you score the whole result against the CIS Benchmark (Center for Internet Security, a published checklist of hundreds of specific settings that experienced people agree a hardened host should have), instead of guessing whether you covered everything.

Seeing What Actually Happens

Locked doors are not the end of it. A serious building also has cameras and a guard who can answer 'who went into that room at 2am?' That is detection and response, and it is where the Advanced Linux security course goes.

auditd is the written logbook, the record you read after the fact. eBPF (extended Berkeley Packet Filter, a technology that lets you run tiny inspection programs safely inside the kernel while the system keeps running) is the live camera feed, showing processes, file changes, and network calls the moment they happen, without slowing the machine down. osquery (a tool that shows the state of a machine as if it were a database you can query with SQL, the standard language for asking a database questions) turns each host into something you can interrogate. Point a fleet manager at it and you can ask the same question of a thousand hosts at once, like which of them have a process listening on a port it should not. When something does go wrong, you use all three to rebuild what happened, in order, and to decide what to do next.

The path every DevSecOps engineer walks
Operate (this course)
Shell & filesystem
move around, read paths
Permissions & sudo
who can touch what
Services & logs
systemd, journalctl
Network view
ss, open ports
Defend (hardening course)
Key-only SSH
no passwords, no root
Default-deny firewall
nftables
Kernel + MAC
sysctl, AppArmor/SELinux
Measure it
CIS Benchmark
See & respond (advanced course)
The logbook
auditd rules
Live view
eBPF
Fleet questions
osquery
Investigate
reconstruct incidents
Same Linux concepts, aimed three different ways.
Quick check
01On a fresh server, sudo sshd -T prints passwordauthentication yes. Why does a DevSecOps engineer treat that as a problem to fix?
Incorrect — yes means password login is enabled and working, not broken.
Correct — a password can be brute-forced from anywhere, while a key cannot be guessed.
Incorrect — the firewall is a separate layer (nftables); this line only controls SSH login method.
Incorrect — no passwords live in sshd_config; the setting only permits the password login method.
02When hardening SSH on modern Ubuntu, the lesson puts the settings in a drop-in file named 00-hardening.conf inside /etc/ssh/sshd_config.d/. Why does the numeric prefix '00' matter?
Incorrect — the prefix controls order, not whether the file is read.
Correct — cloud images often ship a 50-cloud-init.conf that re-enables passwords, so your file must sort before it.
Incorrect — the filename has nothing to do with login retry or lockout limits.
Incorrect — it reads them in alphabetical order and takes the first value, so a low number wins.
03On a fresh cloud server, 'sudo nft list ruleset | wc -l' prints '0'. What does that tell you about the host?
Correct — zero lines means nftables has no rules, so the host itself is blocking nothing.
Incorrect — that is the opposite; a default-deny firewall would contain rules, not zero lines.
Incorrect — an empty ruleset means no rules are loaded, not that the feature is missing.
Incorrect — with no firewall, listening ports are reachable by default; rules would be needed to close them.

Here is a concrete next move. On a machine you own, run those five commands today and write down what each one says. That is your baseline. As you work through the hardening course and change each setting, run the same command again and watch the answer flip from open to closed. Being able to prove a host is more defensible than it was yesterday, with a command anyone can rerun, is the difference between operating Linux and securing it.

Try this

Work through “Seeing What Actually Happens” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.

Takeaway

The trap worth remembering here: test your key before you kill the password. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.

Related