Linux Essentials – Guide

A Guide to Core Concepts

This guide is organized around the mental models that make Linux click — not just commands to memorize, but why the system is shaped the way it is. Each section builds toward the next.


1. Everything Is a File

The single idea that unlocks the most about Linux: nearly everything — regular files, directories, devices, sockets, pipes — is represented through the filesystem and accessed with the same syscalls (open, read, write, close).

  • /dev/sda is your disk, but it’s a file.
  • /proc/1234/status is live kernel data about process 1234, exposed as a file.
  • /sys/class/thermal/thermal_zone0/temp is a hardware sensor reading, as a file.

This is why tools like cat, grep, and redirection (>, >>, |) work almost universally — they don’t need to know what’s on the other end, only that it behaves like a file.

Filesystem Hierarchy Standard (FHS) — the layout you should recognize:

PathPurpose
/etcSystem-wide configuration files (mostly plain text)
/varVariable data: logs (/var/log), spool queues, databases
/usrUser-space programs and libraries (the bulk of installed software)
/bin, /sbinEssential binaries (now often symlinked into /usr)
/homePer-user data
/rootThe root user’s home directory
/optOptional/third-party software bundles
/tmpTemporary files, often cleared on reboot
/proc, /sysVirtual filesystems exposing kernel/process state (not real disk data)

Run man hier for the authoritative version.


2. Users, Groups, and Permissions

Linux permissions exist to answer one question for every file access: is this identity allowed to do this?

Every process runs as a user and group. Every file has an owner (user) and a group, plus a permission triad for owner/group/others:

-rw-r--r--  1 datapioneer  users  1024  Sep 5 10:00  notes.txt

Read as: owner can read+write, group can read, others can read. chmod 644 notes.txt sets this numerically (4=read, 2=write, 1=execute, summed per triad).

Special bits worth actually understanding:

  • setuid (chmod u+s) — a binary runs with its owner’s privileges, not the caller’s. This is how passwd lets unprivileged users edit /etc/shadow.
  • setgid on a directory — new files inherit the directory’s group, useful for shared team directories.
  • sticky bit (/tmp has this) — users can only delete their own files in a shared directory, even with write access to it.

Beyond the classic triad: ACLs (setfacl/getfacl) let you grant permissions to specific additional users or groups without changing ownership — useful when the owner/group/other model is too coarse.

sudo doesn’t change who you are permanently — it re-executes a single command as another user (root by default), governed by /etc/sudoers. This is a meaningfully different model from su, which starts a new login shell as that user.


3. Processes and the Process Tree

Every process has a PID, a parent PID (PPID), and exists in a tree rooted at PID 1 (the init system — usually systemd). When a process’s parent dies, it’s “reparented” to PID 1 or a subreaper.

Process states you’ll see in ps or top:

  • R running/runnable
  • S sleeping (interruptible — waiting on I/O or a signal)
  • D uninterruptible sleep (usually waiting on disk I/O — can’t even be killed with SIGKILL while stuck here)
  • Z zombie — the process has exited but its parent hasn’t yet reaped its exit status
  • T stopped (e.g., via Ctrl+Z)

Signals are the basic IPC mechanism for controlling processes: SIGTERM (15) asks a process to exit cleanly; SIGKILL (9) terminates it unconditionally at the kernel level, bypassing any cleanup; SIGHUP (1) traditionally meant “your controlling terminal closed,” and is now widely repurposed by daemons to mean “reload your config.” Knowing this distinction matters operationally: reach for SIGTERM first, always, and treat SIGKILL as a last resort since it can leave resources (locks, temp files, partial writes) in an inconsistent state.

Foreground vs. background vs. daemon: a daemon detaches from any controlling terminal and is typically supervised by an init system rather than a shell — which is exactly the gap systemd unit files are designed to fill (see below).


4. systemd: Init and Service Management

Modern Linux systems boot into and are managed by systemd, which replaced the older sequential SysV init scripts. Its core unit is the unit file — a declarative description of something the system manages.

Common unit types:

  • .service — a long-running or one-shot program
  • .socket — activates a service on first connection (lazy startup)
  • .timer — schedules a unit to run (systemd’s answer to cron, with better logging and dependency handling)
  • .mount / .target — filesystem mounts and grouping points (a “target” is roughly systemd’s equivalent of an old runlevel)

The dependency model matters more than the syntax. Unit files declare relationships like Wants=, Requires=, After=, Before= — systemd builds a dependency graph and parallelizes startup wherever the graph allows, rather than running everything in one fixed sequence. This is why systemd boots faster than SysV init, and also why boot-order bugs manifest as “unit A started before the resource it needed was ready” — After= orders things, but doesn’t imply the dependency actually succeeded; that’s what Requires=/BindsTo= are for.

Practical commands you’ll use constantly:

systemctl status <unit>        # current state + recent log lines
systemctl enable --now <unit>  # start now, and on every future boot
journalctl -u <unit> -f        # follow logs for one unit
journalctl -b                  # logs since last boot

journald (systemd’s logging component) stores structured, indexed binary logs — this is why journalctl supports fast filtering by unit, boot, priority, and time range in ways that grepping flat text files can’t match.


5. Package Management

Distributions solve “how do I install and track software” very differently, but the underlying problem is always the same: resolve dependencies, avoid conflicts, and allow clean removal.

FamilyLow-level toolFrontendPackage format
Debian/Ubuntudpkgapt.deb
RHEL/Fedorarpmdnf.rpm
Archpacmantarball + metadata

The low-level tool (dpkg, rpm) installs an individual package file but knows nothing about fetching it or resolving its dependencies from the internet — that’s the frontend’s (apt, dnf) job. This split is why you’ll occasionally see a dpkg error mention a missing dependency that only apt --fix-broken install can resolve — you dropped down a layer.

Newer, distro-agnostic formats (Flatpak, Snap, AppImage) trade tight system integration for bundling all dependencies inside the package itself — worth knowing about since they behave differently under systemctl, permissions, and updates than native packages.


6. Networking Fundamentals

A minimal mental model that covers most troubleshooting:

  • Interfaces (ip addr) — your NICs, virtual bridges, and loopback. Configuration on modern Ubuntu/Debian systems lives in netplan YAML, which generates the actual config consumed by systemd-networkd or NetworkManager underneath.
  • Routing (ip route) — the kernel’s table of “to reach this network, send packets out this interface, via this gateway.” A missing or wrong default route is the single most common cause of “I have an IP but no internet.”
  • DNS — resolution order is typically controlled by /etc/nsswitch.conf, with the actual resolver config in /etc/resolv.conf (often managed automatically now, rather than hand-edited).
  • Sockets and portsss -tulpn shows what’s listening where and which process owns it; this is usually the first command to run when a service “isn’t reachable.”
  • iptables/nftables — the kernel’s packet filter. nftables is the modern replacement for iptables, but many tools (including Docker) still generate iptables-style rules under the hood, which is a common source of confusing overlapping rule sets on a server running both.

Given your reverse-proxy setup, the concept worth internalizing is the request path: client → DNS resolves your domain → hits your public IP on port 443 → Nginx Proxy Manager terminates TLS and inspects the Host header → proxies to the correct backend container’s internal IP:port. Most “it worked yesterday” reverse-proxy bugs live in exactly one of those hops.


7. The Shell and Scripting Model

The shell (bash, zsh, etc.) is a program like any other — it’s not special-cased by the kernel. What makes it powerful is composability:

  • Pipes (|) connect one process’s stdout to another’s stdin, letting the kernel stream data between them without an intermediate file.
  • Redirection (>, >>, 2>, &>) rewires file descriptors 0 (stdin), 1 (stdout), 2 (stderr) — this is why command > /dev/null 2>&1 silences everything: redirect stdout to the null device, then point stderr at wherever stdout now points.
  • Exit codes — every command returns 0 (success) or nonzero (failure) to $?. This is the backbone of && (run next only on success) and || (run next only on failure), and of scripting error handling in general.
  • Subshells and variable scope — a command in $(...) or (...) runs in a child shell; variables it sets don’t leak back to the parent. This trips people up constantly when piping into a while read loop that seems to “forget” variables afterward.

set -euo pipefail at the top of a script is the standard defensive trio: exit on any error, treat unset variables as errors, and make a pipeline fail if any stage fails (not just the last one).


8. Storage: Block Devices, Partitions, Filesystems, LVM

The stack, bottom to top:

  1. Block device (/dev/sda) — the raw disk.
  2. Partition table (GPT or the older MBR) — divides the block device into partitions (/dev/sda1).
  3. Filesystem (ext4, XFS, Btrfs, ZFS) — the structure that turns raw blocks into files and directories.
  4. Mount — attaches a filesystem to a point in the directory tree; /etc/fstab makes this happen automatically at boot.

LVM (Logical Volume Manager) inserts a flexible layer between partitions and filesystems: physical volumes (PVs) are grouped into a volume group (VG), which is then carved into logical volumes (LVs) that filesystems actually sit on. The payoff is resizing — you can grow an LV (and its filesystem) live, across multiple physical disks, without the rigid boundaries a raw partition imposes.

df -h shows filesystem-level usage; du -sh <dir> shows what’s actually consuming space within a directory — they can disagree (e.g., a deleted-but-still-open file keeps its space held by the filesystem until the holding process closes it), which is a classic “why is my disk full but du doesn’t add up” puzzle.


9. The Kernel, Modules, and /proc & /sys

The kernel is one program, but its functionality — especially device drivers — is largely modular. lsmod lists currently loaded modules; modprobe loads one (and its dependencies); dmesg shows the kernel’s own ring buffer log, invaluable for hardware and driver issues that never make it into journalctl‘s regular unit logs.

/proc and /sys are virtual — they don’t exist on disk, but are generated on-demand by the kernel:

  • /proc/cpuinfo, /proc/meminfo — live hardware/resource state
  • /proc/<pid>/ — a directory per running process, containing its open file descriptors, memory maps, environment, and more
  • /sys — a more structured, newer interface exposing kernel objects (devices, drivers) for configuration, largely superseding ad hoc /proc entries for that purpose

This is also the layer container tooling (Docker, LXC) leans on: containers are ordinary Linux processes isolated via kernel namespaces (PID, network, mount, etc. — separate views of “the system”) and resource-limited via cgroups — there’s no separate “container kernel,” which is the key difference from a VM.


10. Security Fundamentals
  • Principle of least privilege — run services as dedicated non-root users wherever possible; a compromised process should own as little as possible.
  • SSH key-based auth over passwords — and disabling password auth entirely on internet-facing boxes once keys are set up.
  • Firewalls (ufw as a friendly wrapper over nftables/iptables) — default-deny inbound, explicitly allow what you need.
  • Mandatory Access Control (AppArmor on Debian/Ubuntu, SELinux on RHEL/Fedora) — goes beyond standard permissions by confining what a program can do even if it’s compromised or misconfigured, based on a policy rather than just file ownership.
  • Unattended upgrades / patch cadence — most real-world compromises exploit known, already-patched vulnerabilities; timely updates do more for security than most hardening checklists.

How These Concepts Connect

The throughline across all ten sections: Linux exposes almost everything as either a file or a process, uses a small number of composable primitives (permissions, signals, file descriptors, namespaces) rather than special-casing each subsystem, and layers user-friendly tools (apt, systemctl, ufw) over lower-level mechanisms you can always drop down to when the abstraction leaks. Once that pattern is visible, unfamiliar tools tend to make sense faster, because you’re recognizing a variation on a primitive you already understand rather than learning something wholly new.