Skip to content

V1.1

Latest

Choose a tag to compare

@saintmicha3l saintmicha3l released this 24 Oct 14:42
· 2 commits to main since this release
b8f524e

Let's Linux — Changelog: v1.0.0 → v1.1.0

Version 1.1.0 — released 2026-10-23 (second release).

The curriculum grows to 171 missions and 224 skills: chapter T is now complete with five more capstones — a hardened migration, a performance incident, a disaster recovery, an automation-to-specification build and a network move — plus three mid-campaign cumulative scenarios. The simulator gains SELinux/AppArmor MAC enforcement, quick review drills, and many new commands. ulimit -u is now a real enforced per-process limit. Each mission briefing names its distribution, and the release ships source (built with pip at install) instead of prebuilt wheels.

Changed

  • Distribution is now shown in-game: each mission briefing names the distribution it's written for and clarifies that the player's distribution only sets their sandbox; the new-player form, player list ("sandbox: …") and Settings say the same.
  • README explains the distribution model and documents lets-linux sandbox --distro (default debian).

Fixed (simulator)

  • ulimit -u is now a real enforced per-process limit (RLIMIT_NPROC). Settable (-u N/unlimited), displayed, inherited across fork(). A fork bomb under a process limit is now stopped exactly as on real Linux (bash: fork: retry: Resource temporarily unavailable, shell stays usable). The cgroup pids.max equivalent is still not enforced.
  • Simulator accuracy: bash accepts :, f.x, a-b as function names; loop/block redirection errors name the right line; ( cmd & ) prints no job number; /proc/1/exe points at the systemd binary; make -n says "Nothing to be done"/"is up to date"; strace -f sh -c shows one execve/exit per process; sar interval header shows start time; iostat -x/sar -d agree; gdb names the first statement's line for a function breakpoint; apt resolves a conflict by offering to remove the installed package; df uses GNU column widths and accepts -BM-style sizes.
  • Full-screen display markup crash: the command reference crashed on dd and dropped [OPTION] brackets on 148 of 367 entries (help text read as markup). Fixed everywhere the TUI shows text it doesn't control — player names (e.g. [x would crash the chooser), read -p prompts like [y/N], dialog/window titles, error notifications.

Fixed (installer)

  • Stopped installing unneeded -pip packages (venv brings its own pip) — they pulled ~150 packages via apt Recommends (incl. a C compiler) and blocked the uninstaller from ever removing the Python it added. Now only Python (+ apt's venv package) is installed; dnf skips weak deps.
  • Uninstaller's apt dry-run no longer miscounts auto-installed packages as "other software"; it now removes deps left unneeded by removing Python — only those.
  • Alpine: both scripts now look in /usr/sbin and /sbin when the package manager isn't on PATH (apk).
  • Minimal systems without awk: both scripts now check for required tools first and name the missing one before changing anything.
  • Known limitation: a 1.0.0 install on Fedora/RHEL or Arch that added Python also added -pip packages, so uninstalling it keeps Python.

Added — Missions & curriculum

Five chapter-T capstones:

  • The Hardened Migration (Fedora, SELinux enforcing): create operator account, dnf install/enable nginx, relabel web root with restorecon (verified by a real confined read, without disabling SELinux), open HTTP via firewall-cmd — all checked after a reboot.
  • The Performance Incident: read a genuine OOM-killer record in journalctl -k, identify the leaking service by cgroup, contain it with a persistent per-service MemoryMax=, restore the panic-stopped service — verified after reboot.
  • The Disaster Recovery: two simultaneous failures on a RAID1→LVM→ext4 share — rebuild the degraded mirror (mdadm --remove/--add → [UU]), unlock a LUKS off-site backup by key file, restore and verify against a sha256sum -c manifest, bring the service back. Teaches RAID = availability vs backup = recoverability.
  • Automation to a Specification: deliver an unattended backup job to spec (dated dump, fail-safe on missing/empty source, mode 600, keep newest 7, log each run) + systemd oneshot & timer — graded by running it against seeded good/bad inputs on machine clones, not by reading the script.
  • The Network Move: move a live site off a dying host onto the learner's machine over SSH/rsync, serve with nginx (running+enabled), open HTTP with ufw, then cut the name over last (pinned in /etc/hosts as a DNS stand-in).

Three mid-campaign cumulative scenarios:

  • Close of Business (E, challenge): argument-checked log-tally script + exact octal chmod.
  • The Service That Quit (H, troubleshooting): a failed service whose ExecStart needs a missing package — diagnose, install, start, enable.
  • The Backup Window (J, troubleshooting): one failure, two causes — a full /var/backups to clear and a backup hostname to restore in /etc/hosts.

Three missions practising recent additions:

  • Picking Up the Pieces (F): recover an interrupted apt full-upgrade with dpkg --configure -a; decline a "fix" that would swap the system logger.
  • Tracing the Path (D): why a world-readable file is unreadable — find the parent dir missing the search bit with namei -l.
  • Same Change, Everywhere (R, challenge): roll out one change across Debian/Fedora/Arch, translating package managers and sudo/wheel.

Plus troubleshooting missions The Page That Won't Load (L, SELinux httpd_t denial), The Immovable File (D, immutable attr), and Where the Path Breaks (M, wrong default gateway via traceroute).

Added — Simulator features & commands

  • SELinux & AppArmor enforcement: MAC now actually blocks (not just reports). A bounded targeted-policy model decides read/write/execute by SELinux type; denials are refused and logged as real AVCs (ausearch -m avc). Dormant in ordinary gameplay — only fires for a labelled process. New tools: ls -Z, chcon, restorecon, semanage fcontext|boolean, getsebool/setsebool, audit2why, runcon, and AppArmor aa-enforce/aa-complain/apparmor_parser. New selinux_context objective check. Approximations: path-based labels (not per-inode xattrs); small rule subset; only file r/w/x enforced; semanage port|login and audit2allow not modelled.
  • Quick review drills: from the Review screen (d), short answer-checked questions for due skills instead of replaying a mission. Recorded as prediction-kind evidence — refreshes the review schedule but can never alone reach Proficient/Mastered.
  • jq: JSON processor covering a documented subset — paths, pipes, comma, construction, arithmetic/comparisons, ~40 functions; -r -c -s -n -e -S, --arg/--argjson; unknown filters reported, not silently ignored.
  • iptables/ip6tables + iptables-save/-restore: as iptables-nft — writes the same ruleset as nft and vice versa. Full classic model (filter/nat/mangle/raw, chains, matches, targets).
  • fail2ban-client/fail2ban-server: jails that watch the log and ban via the firewall. sshd jail (default) scans the journal and installs a real drop rule after maxretry/findtime, lifted after bantime. Approximations: lazy log scan; only sshd modelled in depth; stop flushes bans.
  • auditctl/ausearch/aureport: file watches (-w -p -k) and syscall rules; a persistent VFS observer feeds the audit log. Boundary: only the file-watch feed makes records; syscall rules stored/listed only; no auditd daemon or /var/log/audit; AVC records planned.
  • loginctl: logind's view of sessions/users/seats reconstructed from login records; enable-linger/disable-linger, terminate-session/-user.
  • timedatectl/localectl: set-timezone makes date honour the zone (and TZ, -u) while the clock stays UTC; set-ntp manages systemd-timesyncd; locale/keymap.
  • traceroute/mtr -r: hop-by-hop path over the simulated routes; gateway first hop, * * * for unmodelled/firewalled hops, !X/!H/!N rejects, per-hop Loss%.
  • chattr/lsattr: immutable (i) and append-only (a) now enforced above owner/mode — they stop even root.
  • syslog-ng: classic alternative logger; Conflicts with rsyslog, working daemon + unit.
  • namei: walks a path component by component (-l for modes/owners), follows symlinks, stops at the first unreachable component.
  • Misc: df --output[=FIELDS]; dpkg --configure -a/-C/--audit (apt now refuses until fixed); modinfo -n; systemd-cgtop -P; systemd --version; podman format templates ({{range}}, variables, {{- -}}).