Linux & operating systems
The OS every server, container and pipeline runs on
You will live in a Linux shell. Get fluent with the filesystem, permissions, processes, packages, services, SSH and scheduling — it pays off in every later stage.
On this page · 6 lessons
The command line & filesystem
Navigation, pipes and redirection, and the text triad (grep/sed/awk). Small tools, composed.
Servers have no mouse. Your entire job runs through a shell — almost always Bash on Linux. Fluency here is the single biggest early productivity multiplier.
Start with navigation and inspection: pwd (where am I), ls -la (list, including hidden), cd, cat, less, find, and tree. Everything in Linux is a file — even devices and processes — so these commands go a very long way.
The real power is composition with pipes (|) and redirection (>, >>, <). Each tool does one thing; you chain them:
# find the 5 largest files under /var/log
du -ah /var/log | sort -rh | head -5
# count errors in a log
grep -i error app.log | wc -l
Learn the "text triad": grep (search), sed (stream edit), awk (field processing). And use man <command> or tldr <command> the moment you're unsure — reading the manual is the skill.
Filesystem hierarchy, disks & mounts
Where everything lives (/etc, /var/log), how disks are mounted, and how to find what filled the disk.
Linux organises everything under a single root, / — there are no drive letters. Learn the Filesystem Hierarchy Standard, because it tells you where to look:
/etc— configuration files (this is where you'll spend a lot of time)./var— variable data: logs (/var/log), caches, spools./home— user home directories./root— root's home./usr/bin,/bin— installed programs./tmp— scratch space, wiped on reboot./proc,/sys— virtual filesystems exposing kernel and process state.
Storage is mounted into that tree: a disk or partition is attached at a mount point (e.g. /data). Inspect with:
df -h # free space per filesystem — check this when "disk full"
du -sh /var/* # what is actually eating the space
lsblk # block devices and partitions
mount | column -t
Permanent mounts are declared in /etc/fstab. LVM (Logical Volume Manager) adds a layer that lets you resize and span volumes across disks without repartitioning — common on servers.
"Disk full" is one of the most frequent production incidents, and it's usually runaway logs in /var/log. df -h then du -sh narrows it in seconds.
Users, permissions & processes
chmod/chown, sudo and least privilege, ps/top, signals and exit codes.
Linux is multi-user by design, and its security model is refreshingly simple once it clicks.
Permissions apply to three classes — user (owner), group, and others — each with read (4), write (2), and execute (1) bits. That's why chmod 750 script.sh means owner=7 (rwx), group=5 (r-x), others=0 (none). Use ls -l to read them and chown user:group file to change ownership.
Users and privilege: you avoid logging in as root. Instead, an ordinary user runs specific commands as root via sudo. This gives you an audit trail and limits blast radius — the foundation of least privilege.
Processes: every running program is a process with a PID. Inspect with ps aux, watch live with top/htop, and control with signals: kill -TERM asks a process to stop gracefully, kill -9 (SIGKILL) forces it. Background a job with &, and understand exit codes — 0 means success, anything else is failure (this is what pipelines check).
Package managers, services & systemd
apt/dnf, managing daemons with systemctl, unit files, and reading logs with journalctl.
Real servers install software from package managers, not by downloading binaries by hand. On Debian/Ubuntu that's apt (apt install nginx); on RHEL/Fedora it's dnf/yum. Packages handle dependencies, upgrades, and removal cleanly, and you can pin versions for reproducibility.
Long-running programs (web servers, databases, your app) run as services managed by systemd, the init system on modern Linux. The key command is systemctl:
systemctl status nginx # is it running? why did it crash?
systemctl start|stop|restart nginx
systemctl enable nginx # start automatically on boot
A service is defined by a small unit file (/etc/systemd/system/myapp.service) that says what to run, which user to run as, and how to restart on failure (Restart=always). Writing one for your own app is a rite of passage.
Logs go to the journal: journalctl -u nginx -f follows a service's logs live — this is where you look first when something won't start.
SSH & surviving in vim
Key-based login, ~/.ssh/config, port forwarding, hardening sshd — plus enough vim to edit any config file.
Two skills you'll use every single day on a server.
SSH is how you reach remote machines securely. Stop using passwords — use key pairs: you keep a private key, the server holds your public key.
ssh-keygen -t ed25519 # generate a modern key pair
ssh-copy-id user@server # install your public key on the server
ssh user@server # log in, no password
Configure shortcuts in ~/.ssh/config so ssh prod just works. Learn two power moves: scp/rsync to copy files, and port forwarding (ssh -L 8080:localhost:80 server) to reach a service that isn't exposed publicly. On the server side, harden sshd: disable root login and password authentication entirely.
A terminal editor is unavoidable — there's no VS Code on a remote box. Vim is everywhere, so learn survival mode: i to insert, Esc to leave insert, :w write, :q quit, :wq both, :q! quit discarding changes, /text to search, dd delete a line. That's genuinely enough to edit a config file. (nano is friendlier if it's installed, but vim is always installed.)
Scheduling with cron & systemd timers
Crontab syntax, the environment traps, logging output, and the modern systemd timer alternative.
Plenty of ops work is just "run this thing on a schedule": backups, cleanups, report generation, certificate renewal.
Cron is the classic scheduler. Each line in a crontab (crontab -e) is a schedule plus a command, with five time fields — minute, hour, day-of-month, month, day-of-week:
# ┌ min ┌ hour ┌ dom ┌ mon ┌ dow
0 3 * * * /usr/local/bin/backup.sh
# → run backup.sh every day at 03:00
*/15 * * * * /usr/local/bin/healthcheck.sh
# → every 15 minutes
The classic traps: cron runs with a minimal environment (your PATH isn't what you think — use absolute paths), and it emails output nobody reads, so always redirect output to a log file (>> /var/log/backup.log 2>&1) or you'll be blind when it silently fails.
systemd timers are the modern alternative: more verbose, but they give you real logging via journalctl, dependency handling, and the ability to catch up on missed runs after a reboot.
In Kubernetes, the same idea is a CronJob — the concept follows you up the stack.
- $Spin up a Linux VM and harden it: non-root user, key-only SSH, firewall, automatic security updates.
- $Write a backup script, schedule it with cron, log its output, and verify it actually ran.