Primer · Linux · CLI & System Security

Linux Command &
File Reference

A guided tour of the commands and system files that run — and secure — a Linux machine: what each one does, what it prints, and why it matters when you are the one keeping the box safe. No virtual machine required. Read it end to end, or jump to what you need before a lab.

No VM required Linux Mint / Debian 13 sections Companion to the FIDO & Secure Boot labs
Contents
New to Linux entirely? This primer assumes you can already find your way around a shell. If commands, distros, or "which desktop environment" are unfamiliar territory, start with Linux 101 first — it's a friendlier on-ramp — then come back here.

How to read this primer

This is a read-through, not a hands-on lab — every command shows representative output so you can learn it without running anything. It is the conceptual foundation the FIDO and Secure Boot labs build on: identity, permissions, PAM, services, and exposure. A few conventions carry throughout.

The label above each block tells you the privilege

Every command block is tagged. Normal user shell runs as an ordinary user. Uses sudo needs administrator rights — you will be asked for your own password, and the command runs as root for that one invocation.

Command blocks vs. OUTPUT blocks

Blocks with a copy button are commands you could type. Dimmed blocks headed OUTPUT show representative results — nothing to run. A red DESTRUCTIVE header flags a command that is irreversible; read the path twice before you would ever run it.

Security lens

Amber Security lens callouts call out the stakes: how a setting gets abused, and what to check. Red callouts mark something that can destroy data or lock you out.

Sample identities. Examples use a host named mint, an admin labadmin, plain users user1user4, a stand-in intruder rogue1, and the lab network 192.168.56.x. All are illustrative placeholders. Commands are shown for Linux Mint and behave the same across Debian- and Ubuntu-based systems.

1. Linux & the shell

Linux is a family of open-source operating systems built on a shared kernel — the core that manages the CPU, memory, devices, and processes. Everything you type goes through a shell, the program that turns your commands into requests the kernel carries out. Mint is one Linux distribution among hundreds; it is based on Ubuntu, which is based on Debian, which is why its commands match most of the Linux world.

Why the command line matters for security. Much of what hardens a Linux box — password policy, PAM, services, kernel parameters — simply cannot be reached from the graphical settings. If you cannot drive the shell, you cannot secure the system.

Reading the shell prompt

The prompt tells you who and where you are. The final character is the tell that matters most: $ means an ordinary user, # means root — the all-powerful superuser.

Normal user shell
whoami
Example output
labadmin
Example prompts
labadmin@mint:~$    the trailing $  ->  an ordinary user
root@mint:~#        the trailing #  ->  you are root, no guardrails
Security lens. Glance at the prompt before every command. A stray # means a single typo can rewrite or destroy system files with no "are you sure?" — root has no guardrails. This primer uses sudo for one-off admin commands so you spend as little time as possible sitting at a # prompt.

2. Navigating the filesystem

Linux has no drive letters. Everything hangs off a single root, written / — think of the filesystem as a tree whose trunk is /, whose branches are directories, and whose leaves are files. Paths are either absolute (start at /) or relative (start where you are). Names are case-sensitive: Notes.txt and notes.txt are two different files.

The key directories

A handful of top-level directories carry most of the security weight:

PathWhat lives there
/homePer-user home directories (/home/labadmin). Each user can read only their own.
/etcSystem configuration — the passwd, group, shadow, PAM, and sysctl files you will harden.
/bootBootloader and kernel. Do not touch unless you mean to.
/varVariable data: logs (/var/log), databases, mail.
/procA virtual view into the kernel and every running process — not real files on disk.
/bin /sbin /usrPrograms. /sbin holds tools meant for root.

pwd · cd · ls

pwd prints your present working directory. cd changes it. ls lists what is there. With no argument, cd takes you home and ls lists the current directory.

Normal user shell
pwd
Example output
/home/labadmin
Normal user shell
cd /home/labadmin/Music
cd ../Documents   # .. is the parent directory
cd ~              # ~ is a shortcut to your home
  • . is always the current directory, .. the parent, ~ your home.
  • Absolute: cd /etc. Relative: cd Documents (from where you stand).

ls -l -a -la

The options make ls a security tool. -l is the long listing (owner, group, permissions, size, date). -a shows all files, including hidden ones whose names start with a dot. They combine as -la.

Normal user shell
ls -la
Example output
drwxr-xr-x 14 labadmin labadmin 4096 Jun 12 09:14 .
drwxr-xr-x  4 root     root     4096 May 30 11:02 ..
-rw-------  1 labadmin labadmin  220 May 30 11:02 .bash_history
-rw-r--r--  1 labadmin labadmin 3771 May 30 11:02 .bashrc
drwxr-xr-x  2 labadmin labadmin 4096 Jun 12 09:14 Documents
Security lens. Attackers hide their work in dot-files. A plain ls will not show them — ls -la will. Reviewing hidden files in home directories is a routine hunt for persistence.

3. Working with files

The everyday verbs: read, create, copy, move, delete, and edit. Two ideas make them powerful — every program has a standard output you can redirect into a file, and the manual is one command away.

man · --help

Never guess. man ls opens the manual for ls; press q to quit, arrows or PgUp/PgDn to scroll. Most commands also accept --help for a quick summary. Files have manuals too — man 5 passwd documents the format of /etc/passwd.

Normal user shell
man 5 shadow   # section 5 = file formats
ls --help

cat · echo · file

cat prints a file's contents. echo prints whatever you give it. file tells you what a file actually is, regardless of its name.

Normal user shell
cat /etc/hostname
Example output
mint
Normal user shell
file report.pdf
Example output
report.pdf: PDF document, version 1.7

touch · mkdir · cp · mv · rm

touch makes an empty file (or updates a timestamp). mkdir makes a directory. cp copies, mv moves or renames, rm removes.

Normal user shell
touch notes.txt
cp notes.txt notes.bak   # copy
mv notes.bak archive/    # move into a directory
rm notes.txt             # delete — no recycle bin
Security lens. rm is immediate and permanent — there is no undo and no trash on the command line. Run as an administrator, sudo rm -rf on the wrong path can erase the system. Read the path twice.

rm -rf, demonstrated safely

Worth seeing once — on a throwaway tree under /tmp, so nothing real is at risk. Build a small directory tree, make every file and folder in it read-only, then watch sudo rm -rf erase the whole thing anyway, without a single prompt. Everything here is safe to run yourself.

Normal user shell
mkdir -p /tmp/rm-demo/keep/nested
touch /tmp/rm-demo/keep/nested/report.txt /tmp/rm-demo/keep/notes.log
chmod -R a-w /tmp/rm-demo          # strip write permission from the whole tree
ls -lR /tmp/rm-demo
Example output
/tmp/rm-demo:
total 0
dr-xr-xr-x 3 labadmin labadmin 80 Jul 16 21:00 keep

/tmp/rm-demo/keep:
total 0
dr-xr-xr-x 2 labadmin labadmin 60 Jul 16 21:00 nested
-r--r--r-- 1 labadmin labadmin  0 Jul 16 21:00 notes.log

/tmp/rm-demo/keep/nested:
total 0
-r--r--r-- 1 labadmin labadmin  0 Jul 16 21:00 report.txt
Uses sudo
sudo rm -rf /tmp/rm-demo   # gone — read-only did not save it
Security lens. Every file and folder above was read-only, yet sudo rm -rf deleted the entire tree silently — no confirmation, no recovery. Read-only permissions guard against accidental edits, not against root: the superuser bypasses the permission check entirely. That is exactly why the red DESTRUCTIVE banner rides on the block above — -f ("force") suppresses every safety prompt and -r makes it recursive. Aim that at the wrong path as root and there is nothing to bring it back.

redirection > >> < |

Every program reads standard input and writes standard output. Redirect them: > sends output to a file (overwriting it), >> appends, < feeds a file in as input, and the pipe | hands one command's output to the next as input.

Normal user shell
echo "hello" > hello.txt    # overwrites hello.txt
echo "again" >> hello.txt   # appends
cat hello.txt                 # show what's in the file now
Example output
hello
again
Normal user shell
cat /etc/passwd | wc -l      # count user records
Example output
42
Security lens. > silently destroys whatever the file held. Reach for >> when appending to logs or config, and double-check before redirecting over a system file.

head · tail · wc

head shows the first 10 lines, tail the last 10; -n N changes the count. tail -f follows a file live as it grows — the classic way to watch a log. wc -l counts lines.

Uses sudo
sudo head -n 1 /etc/shadow
Example output
root:!:19700:0:99999:7:::
Uses sudo
sudo tail -f /var/log/auth.log   # live view; Ctrl+C to stop
Security lens. tail -f /var/log/auth.log shows authentication attempts as they happen — failed logins appear in real time, which makes it a quick tripwire during an incident.

diff · gedit

diff a b reports the lines that differ between two files (< is in the first, > in the second). gedit opens a file in a graphical editor — the gentlest way to edit config.

Normal user shell
diff sshd_config sshd_config.bak
Example output
32c32
< PermitRootLogin no
---
> PermitRootLogin yes
Security lens. diff against a known-good backup is how you spot exactly what an attacker (or a bad change) altered in a config file.

4. Searching & text streams

Finding things fast is half of defense. find walks the filesystem by any property; locate answers from a prebuilt index; grep searches inside files. Pipe them together and you have a forensic toolkit.

find

find searches a directory tree and tests each file against expressions — by name, type, owner, and more — then optionally acts on matches. Searching all of / reads directories other users own, so it is run with sudo.

Uses sudo
sudo find /home -name "*.pdf"        # by name
sudo find / -type f -user rogue1     # every file owned by an intruder
Example output
/var/tmp/.cache
/home/rogue1/notes
Security lens. After you find an unauthorized account, find / -user rogue1 locates everything it left behind. The same command can find world-writable files or misplaced SUID binaries — common footholds.

locate · updatedb

locate is far faster than find because it reads a database instead of walking the disk — but the database can be stale, so refresh it with updatedb first.

Uses sudo
sudo updatedb
locate "*.pdf"

grep -R

grep pattern file prints lines matching a pattern; -R searches recursively through a directory.

Uses sudo
sudo grep FAILED /var/log/auth.log     # find failed authentications
grep -R "PermitRootLogin" /etc/ssh
Security lens. Grepping the auth log for FAILED surfaces brute-force attempts; grepping /etc for a setting tells you where it is configured before you change it.

5. Users, groups & identity

Three files define who exists on the system. /etc/passwd lists accounts, /etc/group lists groups, and /etc/shadow holds the encrypted passwords. The operating system identifies everyone by number — a UID and GID — not by name.

/etc/passwd

One line per account, seven colon-separated fields. Despite the name, it no longer holds passwords — the x means "look in the shadow file."

Normal user shell
cat /etc/passwd
Example output
root:x:0:0:root:/root:/bin/bash
labadmin:x:1000:1000:Lab Admin:/home/labadmin:/bin/bash
user1:x:1001:1001:User One:/home/user1:/bin/bash
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
FieldMeaning
nameLogin name humans use.
xPassword placeholder — the real hash is in /etc/shadow.
UIDNumeric user ID. 0 is root. The kernel identifies users by this, not the name.
GIDPrimary group ID.
commentUsually the person's real name.
homeHome directory.
shellProgram run at login. /usr/sbin/nologin means the account cannot log in interactively.

The UID is worth reading closely, because its range tells you what kind of account it is:

  • 0root, the superuser. Only root should ever have it.
  • 1999system accounts for services (www-data, sshd, …); these are hidden from the graphical login screen.
  • 65534nobody, the deliberately unprivileged account.
  • 1000 and up — human users; the first real person is usually 1000.
Security lens. Two things to hunt here. First, any account other than root with UID 0 — that is an instant backdoor. Second, any login-capable account hiding in the system range below 1000: a service account should never have a real shell. Then compare the human accounts (1000+) against who is actually supposed to be on the box — an extra name in that range is the classic planted account.

/etc/group

Defines groups and their members: name:password:GID:members. Group membership is how privileges like sudo are granted.

Normal user shell
cat /etc/group
Example output
sudo:x:27:labadmin
team1:x:1002:user1,user2
projectx:x:1003:user3
Security lens. The sudo group is the crown jewel — anyone in it can become root. Review its membership first; an unexpected name here is a privilege-escalation finding.

/etc/shadow

Readable only by root. Holds the hashed password and its aging rules: name:hash:lastchange:min:max:warn:::. A hash starting $y$ is yescrypt; a lone ! or * means the account has no usable password (locked).

Uses sudo
sudo getent shadow labadmin
sudo head -n 1 /etc/shadow
Example output
labadmin:$y$j9T$…hash omitted…:19700:0:90:7:::
root:!:19700:0:99999:7:::      # root is locked (! = no password)
Security lens. The hashes are secret for a reason — anyone who reads them can run an offline password cracker. That is precisely why passwords were moved out of the world-readable passwd file. On Mint, root having no password is intentional: it cannot be logged into directly.

whoami · id · who · w · getent

whoami is your effective name; id shows your UID, GID, and groups; who and w list who is logged in (and what they are running); getent pulls specific records from passwd/group/shadow.

Normal user shell
id
Example output
uid=1000(labadmin) gid=1000(labadmin) groups=1000(labadmin),27(sudo)
Normal user shell
getent group sudo
Example output
sudo:x:27:labadmin

su · sudo · sudo -i — changing privilege

There are two ways to act as another user, and here the difference is the whole point, so we sit in a real root shell to see it. su user becomes that user — you need their password. sudo command runs a single command as root and asks for your own password (if you are allowed). sudo -i opens an interactive root shell; sudo su and su - reach a root shell too, but sudo -i is the clean, logged way.

Uses sudo
sudo -i
Example session
[sudo] password for labadmin:
root@mint:~#          you are now root — the prompt ends in #
whoami
root
exit                  leave the root shell as soon as you are done
Security lens. Mint gives root no password by default, so su to root fails — that is a feature. sudo is the sanctioned path: it is logged, time-limited, and needs only your own credentials. Prefer sudo command for one-off tasks, reach for sudo -i only when you have several to do, and stay root no longer than necessary.

/etc/sudoers · visudo — who may run what

Membership in the sudo group is the usual grant, but the actual rules live in /etc/sudoers and the drop-in directory /etc/sudoers.d/. Never open sudoers in a plain editor — visudo checks the syntax before it saves, so a typo cannot lock everyone out of sudo. sudo -l shows what the current user is permitted to run.

Uses sudo
sudo visudo        # edit safely — syntax-checked on save
sudo visudo -c     # just validate the current file
sudo -l            # list what you are allowed to run
Example — /etc/sudoers
root      ALL=(ALL:ALL) ALL
%sudo     ALL=(ALL:ALL) ALL           # everyone in the sudo group
labadmin  ALL=(ALL) NOPASSWD: ALL     # DANGER: full root with no password prompt
Security lens. NOPASSWD: ALL means whoever reaches that account is instantly root with no prompt — a favorite backdoor. Treat any of these as a privilege-escalation finding: a user or %group line you did not add, a stray file in /etc/sudoers.d/, or NOPASSWD on a broad command. Audit both /etc/sudoers and /etc/sudoers.d/ by hand, and confirm a specific user's rights with sudo -l -U user1.

6. Managing accounts & permissions

Creating and removing users and groups, setting passwords, and controlling exactly who can read, write, or run each file. Permissions are the everyday access control of Unix.

adduser · deluser (useradd · userdel)

On Mint, prefer the friendly adduser/deluser — they create the home directory and prompt for a password. useradd/userdel are the lower-level tools that exist on every distribution.

Uses sudo
sudo adduser user4                   # create, with home + prompts
sudo deluser --remove-home rogue1    # remove an intruder and their files
Security lens. Removing an unauthorized account is step one; --remove-home (or a later find -user sweep) makes sure nothing they planted is left behind.

addgroup · delgroup · gpasswd

addgroup/delgroup create and delete groups. gpasswd -a user group adds a member; -d removes one.

Uses sudo
sudo addgroup projectx
sudo gpasswd -a user3 projectx   # add user3 to projectx
sudo gpasswd -d user2 sudo       # revoke someone's admin rights

passwd

passwd changes a password — your own by default, or another user's if you are root. passwd -l locks an account, -e forces a change at next login.

Uses sudo
sudo passwd user1        # set a strong password for user1
sudo passwd -l user2     # lock a suspicious account

Reading permissions

Every file has an owner, a group, and three permission sets — for the user (owner), the group, and others. Each set grants read (r), write (w), or execute (x). The ten-character string at the front of ls -l encodes it all.

Normal user shell
ls -l script.sh
Example output
-rwxr-x--- 1 labadmin team1 2048 Jun 12 09:14 script.sh
PieceReads as
-Type: - file, d directory, l symlink.
rwxOwner labadmin: read, write, execute.
r-xGroup team1: read and execute, no write.
---Others: nothing.

chown · chgrp · chmod

chown changes the owner, chgrp the group, chmod the permissions. Changing ownership needs root; changing the mode on a file you own does not. The symbolic form of chmod reads left to right: who (u/g/o/a), how (+ add, - remove, = set), what (r/w/x).

Uses sudo
sudo chown labadmin script.sh    # give ownership to labadmin
chmod o-rwx script.sh            # others: remove all access
chmod g+x script.sh             # group: allow execute
Security lens. A world-writable file (-rw-rw-rw-) lets any user tamper with it — a classic vulnerability. Strip o (other) permissions from anything sensitive, and never leave scripts or config writable by "others."
Where this goes next. The FIDO Lab leans directly on this: it stores each user's hardware-key credential in a file locked to mode 0640 — root may write it, one login group may read it, everyone else gets nothing. That exact mode exists for the tampering rule above.

SUID, SGID & the sticky bit

Three special bits sit on top of rwx. SUID (set-user-ID) makes a program run as its owner rather than as you — it is how passwd, owned by root, can edit /etc/shadow. SGID does the same for the group. The sticky bit on a shared directory like /tmp lets anyone create files but lets each person delete only their own. In ls -l they appear as an s or t where an x would be.

Normal user shell
ls -l /usr/bin/passwd
ls -ld /tmp
Example output
-rwsr-xr-x 1 root root 59976 Mar 23 /usr/bin/passwd   # the s = SUID: runs as root
drwxrwxrwt 2 root root  4096 Jul 16 /tmp               # the t = sticky bit
Uses sudo
sudo find / -perm -4000 -type f 2>/dev/null    # every SUID binary on the system
sudo find / -perm -2000 -type f 2>/dev/null    # every SGID binary
Example output
/usr/bin/sudo
/usr/bin/passwd
/usr/bin/mount
/usr/bin/su
Security lens. A SUID-root program is a direct route to root if it can be tricked into doing something it should not — so an unexpected SUID binary (a copied shell, anything in a home directory, a tool with no business being setuid) is a classic backdoor and one of the first privilege-escalation checks to run. Baseline the list on a known-good machine, investigate anything not on it, and strip the bit from tools that do not need it with sudo chmod u-s /path/to/file.

Capabilities — SUID's finer-grained successor

SUID is all-or-nothing: a SUID-root program gets every root power, even if it needs only one. Modern Linux splits root's authority into about forty capabilities — discrete powers like cap_net_bind_service (bind a port below 1024), cap_net_raw (craft raw packets), or cap_dac_override (ignore file permissions). A binary can be granted just the one it needs instead of full root. It is why ping on Debian is no longer SUID-root — it carries cap_net_raw and nothing else.

Normal user shell
getcap -r / 2>/dev/null    # every file that carries a capability
Example output
/usr/bin/ping cap_net_raw=ep
Security lens. Capabilities are a privilege-escalation hunting ground exactly like SUID — and one people forget to check. cap_setuid or cap_dac_override on an unexpected binary hands out root just as surely as a SUID shell. Run getcap -r / alongside your SUID sweep, and treat anything you did not expect — especially a capability on a shell or on a file in a home directory — as a finding.

7. Software & updates

Mint installs software as packages managed by apt (the Advanced Package Tool). Keeping packages patched is the single highest-value habit in defense — most breaches exploit a known, already-fixed flaw.

apt update · upgrade · full-upgrade

apt update refreshes the list of available packages (it installs nothing). Then apt upgrade installs newer versions; apt full-upgrade does the same but will remove old packages when needed.

Uses sudo
sudo apt update
sudo apt full-upgrade
Example output
Reading package lists... Done
15 packages can be upgraded.
Security lens. Run update then upgrade as a pair, regularly. An unpatched service is the easiest way in; patching closes it before it is ever reached.

apt install · remove · purge · autoremove

install adds a package and its dependencies. remove uninstalls it but keeps config; purge removes config too. autoremove cleans up dependencies nothing needs anymore.

Uses sudo
sudo apt purge nmap       # remove a scanner + its config
sudo apt autoremove       # then clean orphaned dependencies
Security lens. Every installed program is attack surface, and some are outright red flags on an ordinary workstation. A short list of suspicious tools to look for: nmap / zenmap (network scanning), netcat / ncat (raw connections and reverse shells), steghide (hiding data inside images), and password crackers or sniffers like john, hydra, and aircrack-ng. Unless a tool has a clear reason to be there, apt purge it and then autoremove. Review the removal list carefully; it is easy to uninstall something important.

Tracing a program to its package — which · dpkg -S · apt-cache search

Before you can remove a stray program — a game, a scanner, anything with no business on a workstation — you need its package name, which is not always the command you type. Three commands take you from "this thing is here" to "here is the package to purge."

which locates the program: it prints the full path of the executable that runs when you type a command, found by searching your PATH.

Normal user shell
which gnome-mahjongg
Example output
/usr/games/gnome-mahjongg

dpkg -S (search) names the installed package that owns that path — the answer to "where did this come from?" Hand it the path, or nest which inside it.

Normal user shell
dpkg -S /usr/games/gnome-mahjongg
dpkg -S $(which gnome-mahjongg)   # same thing, in one step
Example output
gnome-mahjongg: /usr/games/gnome-mahjongg

The name left of the colon — gnome-mahjongg — is the package, so sudo apt purge gnome-mahjongg removes it cleanly. To search the other direction — for a package that is not installed yet — apt-cache search matches a keyword against every available package's name and description.

Normal user shell
apt-cache search mahjongg
apt-cache search nmap
Example output
gnome-mahjongg - classic Eastern tile game
nmap - The Network Mapper
Security lens. This is the everyday move for clearing prohibited software: spot the program, which it to a path, dpkg -S the path to a package, then sudo apt purge the package. For something with no obvious command — a game you only see in the applications menu — dpkg -l | grep -i game lists installed packages by keyword, so you can find it by name instead.

Package integrity — signatures & debsums

Patching assumes the packages you install are the ones the distribution actually published. apt enforces that for you: every repository is signed, and apt verifies each package's cryptographic signature against a set of trusted keys before it installs anything — a tampered or spoofed package is refused. That signature check is the front line against supply-chain attacks like the XZ backdoor.

Signatures protect a package in transit; debsums checks it after install. It compares the files on disk against the checksums recorded when the package was built, so a system binary an attacker has quietly replaced shows up as changed.

Uses sudo
sudo apt install debsums    # once
sudo debsums -c             # list only files that fail their checksum
Example output — a flagged binary
/usr/bin/ssh
Security lens. A clean debsums -c prints nothing. A flagged system binary — ssh, ls, sshd — is a serious finding: either a local change you can explain, or a trojaned binary. Config files under /etc are expected to differ and can be excluded with debsums -ce.
The graphical equivalents. Mint's Software Manager and Synaptic install packages, and Update Manager applies updates — all fronts for the same apt system. The command line is faster once you know the package name, and it is the only option over a plain SSH session.

8. Hardening: policy & PAM

This is where Linux security lives — and most of it is invisible to the graphical settings. Password aging rules, the authentication stack (PAM), account lockout, and kernel parameters are all edited as text. It is also where a single typo can lock everyone out, so the golden rule is: change it, test it in a second terminal, then close your editor.

/etc/login.defs

Sets the default password-aging policy for new accounts: how long a password lasts, how soon it can be changed, and when the warning starts.

Normal user shell
grep ^PASS /etc/login.defs
Example output
PASS_MAX_DAYS   90    # expire after 90 days
PASS_MIN_DAYS   1     # must wait 1 day before changing again
PASS_WARN_AGE   7     # warn 7 days before expiry
Security lens. A PASS_MAX_DAYS of 99999 means passwords never expire — a common weak default. Tighten it to a sane maximum, set a minimum so users cannot cycle back to an old password instantly, and keep a warning window.

chage — aging on existing accounts

login.defs only sets the policy for accounts created after you change it — it does not touch anyone who already exists. To read or set aging on a current account, use chage (change age): -l lists it, -M sets the maximum days, -m the minimum, and -W the warning window.

Uses sudo
sudo chage -l user1
Example output
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7
Uses sudo
sudo chage -M 90 -m 1 -W 7 user1   # 90-day max, 1-day min, 7-day warning
Security lens. Fixing login.defs alone is a classic half-done job: every account that predates the change still reads 99999. Audit each real user with chage -l and apply the policy to any that slipped through — exactly what the checklist's "existing users have aging applied" step confirms.

PAM — the authentication stack

Pluggable Authentication Modules decide how login, sudo, su, and passwd authenticate. Config lives in /etc/pam.d/, one rule per line, and each rule is powerful and unforgiving: one wrong line can lock out every account, or silently accept any password. Never edit it without a second root session open to undo the change — this is the exact machinery the FIDO labs modify, which is why they insist on a break-glass account first.

Where this goes deeper. The PAM Primer is a dedicated, no-VM walkthrough of PAM's rule structure, the shared common-* stack files, and how to edit any of it safely — building all the way up to a preview of pam_u2f, the module the FIDO Lab adds to this same auth stack so that logging in requires touching a hardware key, not just a typed password.

/etc/pam.d/common-password

The pam_unix.so line here governs new passwords. Add minlen to require length and remember to forbid reuse of recent passwords.

Normal user shell
grep pam_unix /etc/pam.d/common-password
Example output
password  [success=1 default=ignore]  pam_unix.so obscure yescrypt minlen=10 remember=5
Security lens. minlen=10 forces at least ten characters; remember=5 blocks the last five passwords so users cannot cycle back to a favorite. Both raise the cost of a guessed or cracked credential.

/etc/pam.d/common-auth — pam_faillock

pam_unix.so checks the password but does not count failures. pam_faillock.so adds lockout: after too many wrong tries, the account is blocked for a while. The stack wraps the existing auth line.

Example — /etc/pam.d/common-auth
auth  requisite                    pam_faillock.so preauth silent deny=5 unlock_time=900
auth  [success=1 default=ignore]   pam_unix.so
auth  [default=die]                pam_faillock.so authfail deny=5 unlock_time=900
auth  required                     pam_faillock.so authsucc
  • deny=5 — lock after 5 consecutive failures.
  • unlock_time=900 — unlock automatically after 15 minutes.
  • Check or clear counts with faillock --user user1 and --reset.
Security lens. Lockout is the direct counter to password-guessing. Set it, then test it from a second terminal before closing your editor — a mistake in common-auth can lock out everyone, including labadmin.

sysctl · /proc/sys

Kernel behavior is tunable through the /proc/sys tree, and made permanent in /etc/sysctl.conf or /etc/sysctl.d/. sysctl --system reloads them.

Normal user shell
cat /proc/sys/net/ipv4/tcp_syncookies
Example output
0   # SYN-flood protection is off
Uses sudo
echo 1 | sudo tee /proc/sys/net/ipv4/tcp_syncookies        # on, until reboot
sudo sh -c 'echo 1 > /proc/sys/net/ipv4/tcp_syncookies'    # same effect, redirect inside a root shell
Security lens. A change written to /proc is lost on reboot. To make it stick, set it in /etc/sysctl.d/ and reload with sudo sysctl --system. tcp_syncookies=1 hardens against SYN-flood denial-of-service. Note that a bare sudo echo 1 > … would fail — your shell opens the file as you, not root. Two idioms get around this: pipe into sudo tee, or run the whole redirect inside a root shell with sudo sh -c '…'.

9. Services & startup

A service is a program that runs in the background. The init system starts them at boot and supervises them. Mint uses systemd, driven by systemctl; you will still meet the older SysV names on other systems. Fewer running services means less to attack.

init & systemd

The kernel starts one first process — init, PID 1 — and every other process descends from it. On Mint that is systemd. It starts services at boot, stops them at shutdown, and adopts orphaned processes. (Older SysV init used numbered runlevels and scripts in /etc/init.d/; systemd still understands them for compatibility.)

systemctl

One command controls services. enable/disable set whether a service starts at boot; start/stop act now; status reports the current state.

Normal user shell
systemctl status ssh
Example output
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
     Active: active (running)
Uses sudo
sudo systemctl disable --now cups     # stop printing service + keep it off at boot
systemctl list-unit-files --type=service --state=enabled
Security lens. The riskiest services are those that accept network connections and are not essential. List what starts at boot, and disable anything you cannot justify — every enabled service is a door someone might try.

chkservice

An optional terminal UI that lists every service with its enabled/running state, so you can toggle them interactively — a friendlier view than reading systemctl lists.

Uses sudo
sudo apt install chkservice
sudo chkservice   # [x] enabled  > running  =  stopped

10. Processes & scheduled tasks

A process is a running program with a numeric PID. Knowing what is running, being able to stop it, and knowing what is scheduled to run later are core to spotting and evicting an intruder.

ps -ef · top

ps -ef (or ps aux) lists every process with its PID, parent PID (PPID), and the user it runs as. top is the live, sorted-by-CPU view.

Normal user shell
ps -ef | head -3
Example output
UID   PID  PPID  CMD
root     1     0  /sbin/init splash
root   412     1  /usr/sbin/sshd -D
Security lens. The UID column shows what a process can do. A process running as root that you do not recognize — or one owned by an account that should not exist — is worth investigating. Note that the command name can be faked, so corroborate.

kill · killall — signals

You stop a process by sending it a signal. kill PID sends SIGTERM (a polite "please quit"); if it ignores that, kill -SIGKILL PID forces it. killall name targets by name; Ctrl+C interrupts the foreground program.

Uses sudo
sudo kill 3709              # ask process 3709 to stop
sudo kill -SIGKILL 3709     # force it if it won't

/proc

On a compromised box, tools like ps can be replaced with liars (a rootkit trick). The /proc filesystem reads straight from the kernel, so it is much harder to fake. Each PID has a directory; /proc/1/exe points at the real executable behind PID 1.

Uses sudo
sudo ls -l /proc/1/exe
Example output
lrwxrwxrwx 1 root root 0 Jun 12 /proc/1/exe -> /usr/lib/systemd/systemd
Security lens. Never fully trust a system you suspect is compromised — its own tools may be lying. Cross-check against /proc, run known-good binaries from read-only media, and when it matters, analyze the disk offline from a trusted machine.

cron · crontab · /etc/crontab

Scheduled jobs run on a timer via cron. The system schedule is /etc/crontab and the drop-in directory /etc/cron.d/; each user also has a personal one edited with crontab -e. A line's five time fields are: minute, hour, day-of-month, month, day-of-week.

Normal user shell
cat /etc/crontab
Example output
# m h dom mon dow user  command
  17 *  *   *   *  root  cd / && run-parts /etc/cron.hourly
Security lens. Scheduled tasks are a favorite persistence mechanism — a job that re-creates a backdoor every few minutes. Audit /etc/crontab, /etc/cron.d/, and each user's crontab -l for anything you did not put there — and check systemctl list-timers too, since systemd timers are the modern equivalent of a cron job and an equally common place to hide persistence.

11. Logs & auditing

Logs are the record of what happened. Mint keeps them in a systemd journal; the graphical Logs app browses it. For fine-grained tracking of who touched what, the audit daemon adds a second, tamper-resistant trail.

system logs — the journal & Logs app

The journal daemon collects log messages; the Logs application is its graphical viewer — think of it as Linux's Event Viewer. It filters by priority (Important shows the top severities), by category (Applications, System/kernel, Security, Hardware), and by date, and it searches by process, PID, or message text.

Uses sudo
sudo journalctl -p err -b   # errors and worse, this boot
Security lens. Logs are where intrusions leave fingerprints — failed logins, unexpected service restarts, permission errors. Knowing how to filter and search them is what turns a pile of messages into an answer.

auditd · auditctl

Auditing is not on by default. Install the daemon, enable it, and it records security-relevant events you define — file access, config changes, authentication.

Uses sudo
sudo apt install auditd
sudo auditctl -e 1     # turn auditing on
Security lens. The audit trail answers "who changed this, and when" — the questions that matter after an incident. Turning it on before you need it is the whole point; you cannot audit the past.

12. Networking & exposure

Your network exposure is the sum of what is listening and what you allow in. Modern Linux uses the ip and ss tools (the older ifconfig/netstat may not be installed), and ufw is the friendly firewall.

ip addr · ip route

ip addr show lists interfaces with their addresses; ip route show lists how packets leave the box. These replace the legacy ifconfig and route.

Normal user shell
ip addr show eth0
ip route show
Example output
2: eth0: <BROADCAST,MULTICAST,UP> ...
    inet 192.168.56.10/24 brd 192.168.56.255 scope global eth0
default via 192.168.56.1 dev eth0
192.168.56.0/24 dev eth0 proto kernel scope link

ss -A inet -anp

ss lists sockets — network connections and listening ports. The options: -A inet IP sockets, -a all states, -n numeric (do not resolve names), -p show the owning process. It replaces netstat.

Uses sudo
sudo ss -A inet -anp
Example output
State   Local Address:Port     Peer Address:Port   Process
LISTEN  127.0.0.1:3306          0.0.0.0:*           mysqld     # local only — safe
LISTEN  0.0.0.0:139             0.0.0.0:*           smbd       # any address — reachable from the network
ESTAB   192.168.56.10:55914     8.8.8.8:443         chromium   # outbound to a remote host
Security lens. A service on 127.0.0.1 is reachable only from the machine itself; one on 0.0.0.0 is open to the whole network. Keep the list of network-facing listeners to exactly what you need — any process or port you cannot identify should be treated as suspicious.

ufw

The Uncomplicated Firewall. ufw enable turns it on, default deny incoming blocks unsolicited inbound traffic, and allow opens exactly the services you intend.

Uses sudo
sudo ufw enable
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw status verbose
Example output
Status: active
Default: deny (incoming), allow (outgoing)
22/tcp   ALLOW IN   Anywhere
Security lens. Default-deny inbound plus a short allow-list is the workstation standard: nothing reaches the machine unless you explicitly permitted it. Allow only the services you actually run.

13. Remote access & SSH

SSH is the encrypted way into a machine from across the network — and because it is exposed, it is the front door attackers knock on first. The server's behavior is set in /etc/ssh/sshd_config; change a setting, test it, then reload the daemon. This is the same login path the FIDO labs harden, and the one the XZ backdoor was built to subvert.

sshd_config — the daemon's policy

Read a setting, edit the file, then reload. The server config is /etc/ssh/sshd_config (do not confuse it with ssh_config, the client's). sshd -T prints the daemon's effective settings — the real answer after every default and include is applied.

Uses sudo
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|pubkey'
Example output
permitrootlogin no
passwordauthentication no
pubkeyauthentication yes
Uses sudo
sudo sshd -t                # test the config for syntax errors
sudo systemctl reload ssh   # apply it without dropping live sessions
Security lens. Always run sshd -t before you reload — a broken sshd_config can lock you out of a remote machine with no way back in. Keep a second session open while you change it, exactly as with PAM.

The settings that matter

SettingHarden toWhy
PermitRootLoginnoForce admins to log in as themselves and escalate with sudo — attributable and logged.
PasswordAuthenticationnoRequires a key; kills online password brute-force outright.
PubkeyAuthenticationyesPublic-key login, the secure default.
PermitEmptyPasswordsnoObvious, but verify it is actually set.
X11ForwardingnoShrink the surface unless you truly need forwarded GUIs.
AllowUsers / AllowGroupsallow-listOnly the named users or groups may connect at all.
Security lens. PermitRootLogin no plus PasswordAuthentication no is the two-line change that closes off the most common SSH attacks. Everything reachable from the network should be an explicit allow-list, not a default-open.

Keys, not passwords

Key authentication replaces a guessable password with a keypair: the private key stays on your client, and its public half goes into the server's ~/.ssh/authorized_keys. Only the holder of the private key can log in.

Normal user shell
ssh-keygen -t ed25519 -C "labadmin@mint"    # create a modern keypair
ssh-copy-id labadmin@192.168.56.10          # install the public key on the server
Security lens. Guard the private key like a house key — it should be chmod 600 and never leave your machine. This is the same idea the FIDO labs push one step further: proof of possession instead of a shared secret. A hardware token takes it all the way, because the private key physically cannot be copied off the device.
Where this goes next. The FIDO Lab replaces the on-disk private key with a hardware security key you touch to log in — the strongest form of the "possession, not a password" principle above.