[ norboten ]
Journals

The reading that goes with the machines

A journal is a study document, not a manual page: the mechanism, one failure walked through end to end, the wrong turns people actually take, a cheat sheet, and questions you should be able to answer a week later without looking. Lab journals accompany a lab, where the same machine is waiting to be broken, and end with where its hints lead; topic journals cover a subject end to end, with a table of symptoms and their causes, exercises and sources. Notes are different: how something in Norboten itself was built and why, written for someone building their own.

By topic

40 min Ansible

A green run is not a correct machine

What you should be able to do after this — 112 wordsThe mechanism — 1418 wordsA failure, walked through — 695 wordsCommon wrong turns — 312 wordsSymptoms and causes — 199 wordsCheat sheet — 239 wordsExercises — 117 wordsSources — 34 wordsReview — 549 words

Ansible's whole promise is a sentence: describe the state you want, and running the playbook again changes nothing. Every useful property follows from it — you can re-run after a failure, run against a fleet where half t

Covers idempotence per module; command/shell with creates and changed_when; lineinfile regexp; handlers and --force-handlers; check mode and diff; variable precedence; vault passwords without a terminal

3091 words · 8 review questions

45 min Claude CodeAI ServicesAI Agents

Claude Code in a job — what it loads, what it may do, and what it costs

What you should be able to do after this — 113 wordsThe mechanism — 809 wordsA failure, walked through — 634 wordsCommon wrong turns — 202 wordsSymptoms and causes — 182 wordsCheat sheet — 179 wordsExercises — 107 wordsSources — 23 wordsReview — 439 words

Claude Code is usually met as an interactive assistant in a terminal. This journal is about the other way it runs: as a program started by a script, a cron job or a CI workflow, with nobody watching. In that role it is a

Covers headless claude -p runs; the five settings levels and workspace trust; permission modes, allow and deny rules; hooks' matchers and exit statuses; subagents; turns, budgets and model choice

2476 words · 8 review questions

40 min Containers

The container that ran fine until the machine rebooted

What you should be able to do after this — 110 wordsThe mechanism — 1289 wordsA failure, walked through — 578 wordsCommon wrong turns — 323 wordsSymptoms and causes — 180 wordsCheat sheet — 220 wordsExercises — 95 wordsSources — 40 wordsReview — 552 words

The task sounds like one command: run a small web server in a container, as an unprivileged account, serving files from the host, and have it come back after a reboot. It is one command to get it running. Getting it righ

Covers rootless Podman: /etc/subuid and subgid, lingering sessions, SELinux labels on bind mounts (:Z), unprivileged ports, Quadlet units, volumes versus the writable layer

2678 words · 8 review questions

40 min Kernel and performance

The limits nobody set, and the numbers everybody misreads

What you should be able to do after this — 108 wordsThe mechanism — 1503 wordsA failure, walked through — 335 wordsCommon wrong turns — 269 wordsSymptoms and causes — 193 wordsCheat sheet — 203 wordsExercises — 93 wordsSources — 43 wordsReview — 505 words

A service falls over under load with Too many open files. Somebody raises the limit in /etc/security/limits.conf, logs in, runs ulimit -n, sees the new number, and closes the ticket. The next busy afternoon it falls over

Covers RLIMIT_* inherited from units, shells and pam_limits; /proc/PID/limits; free's available column; the machine's and a cgroup's OOM killer (memory.max, memory.events); load average and D state; sysctl -w, sysctl.d and tuned

2729 words · 8 review questions

35 min Logging and journald

The log lines that were never written down

What you should be able to do after this — 80 wordsThe mechanism — 1126 wordsA failure, walked through — 377 wordsCommon wrong turns — 258 wordsSymptoms and causes — 176 wordsCheat sheet — 209 wordsExercises — 113 wordsSources — 42 wordsReview — 439 words

After an incident, the logs are the only witness, and everyone assumes the witness saw everything. It did not. A logging pipeline makes decisions of its own: it drops messages from a service that logs too fast, it files

Covers stdout and stderr into the journal; per-unit rate limits (RateLimitIntervalSec/Burst); rsyslog's second copy; Storage=, SystemMaxUse=, vacuuming; journalctl by unit, boot, field and priority

2479 words · 7 review questions

45 min Model Context Protocol

The Model Context Protocol — servers, clients, and the boundaries between them

What you should be able to do after this — 96 wordsThe mechanism — 725 wordsA failure, walked through — 377 wordsCommon wrong turns — 145 wordsSymptoms and causes — 230 wordsCheat sheet — 80 wordsExercises — 104 wordsSources — 48 wordsReview — 283 words

The Model Context Protocol (MCP) is how an AI client — Claude Code, Claude Desktop, a claude.ai connector — reaches tools and data it was not built with. A server offers tools (functions a model can call), resources (thi

Covers stdio and Streamable HTTP; the 2026-07-28 stateless revision (_meta envelope, Mcp-Method/Mcp-Name, input_required, ttlMs); server-side boundaries; tool results as untrusted input; OAuth 2.1 with RFC 9728, PKCE, CIMD, RFC 9207 and audiences; Claude Code's MCP scopes

2053 words · 6 review questions

35 min Monitoring

Active, green, and not working

What you should be able to do after this — 102 wordsThe mechanism — 1246 wordsA failure, walked through — 421 wordsCommon wrong turns — 236 wordsSymptoms and causes — 194 wordsCheat sheet — 203 wordsExercises — 126 wordsSources — 47 wordsReview — 458 words

Every monitoring failure that matters has the same shape: the check said the service was fine, and a user said it was not. Nobody writes a check intending it to lie. It lies because it measures something adjacent to what

Covers checks as exit statuses with deadlines (timeout, 124); is-active versus a real request; OnFailure= alerts; WatchdogSec= and sd_notify; NRestarts and crash loops a sampler misses; where the probe runs

2617 words · 8 review questions

35 min Networking

Resolves here, listens there, routes until Tuesday

What you should be able to do after this — 91 wordsThe mechanism — 1044 wordsA failure, walked through — 374 wordsCommon wrong turns — 240 wordsSymptoms and causes — 230 wordsCheat sheet — 215 wordsExercises — 153 wordsSources — 69 wordsReview — 435 words

Most "network problems" on a server are not packets lost on a wire. They are questions answered by the wrong tool: a name that one program resolves and another says does not exist, a service that answers every

Covers NSS and getaddrinfo against dig; who writes /etc/resolv.conf (NetworkManager, systemd-resolved); ss -ltnp and bind addresses; ip route get, metrics and persistent routes in nmcli profiles; refused versus timed out

2436 words · 7 review questions

45 min OllamaAI Services

Ollama on a server — a model is a service, a file, a cache and a timer

What you should be able to do after this — 90 wordsThe mechanism — 651 wordsA failure, walked through — 584 wordsCommon wrong turns — 174 wordsSymptoms and causes — 167 wordsCheat sheet — 179 wordsExercises — 98 wordsSources — 26 wordsReview — 340 words

Ollama makes running a language model on your own hardware look like running any other daemon: install one binary, start ollama serve, and an HTTP API on port 11434 lists models, generates text, chats and computes embedd

Covers the ollama service account and OLLAMA_* environment; model storage; load, prompt and generation timings; num_ctx truncation; KV-cache memory times parallelism under MemoryMax=; embeddings; binding and origins

2067 words · 8 review questions

40 min Terraform

The plan says three to destroy, and you only removed one

What you should be able to do after this — 110 wordsThe mechanism — 1349 wordsA failure, walked through — 513 wordsCommon wrong turns — 294 wordsSymptoms and causes — 171 wordsCheat sheet — 224 wordsExercises — 87 wordsSources — 25 wordsReview — 515 words

Terraform's contract is simple to state: you describe what should exist, it compares that with what its state file says exists, and a plan tells you the difference before anything happens. The whole safety of the tool re

Covers state as address-to-object map; count versus for_each addressing; moved blocks; prevent_destroy's gap; sensitive values in state; saved plans and staleness; refresh-only drift

2507 words · 8 review questions

By lab

40 min AnsibleBoot and systemd

A playbook describes a state, not a sequence of commands

What you should be able to do after this — 113 wordsThe mechanism — 1026 wordsA failure, walked through — 1018 wordsCommon wrong turns — 254 wordsCheat sheet — 153 wordsGoing deeper — 167 wordsReview — 334 words

The playbook in /srv/ansible runs without errors. That is the problem with it: it runs without errors every single time, reports six changes every single time, restarts the application every single time, and grows a conf

2280 words · 8 review questions

40 min AnsibleUsers and permissions

Automation that needs a person is not automation

What you should be able to do after this — 122 wordsThe mechanism — 1082 wordsA failure, walked through — 960 wordsCommon wrong turns — 284 wordsCheat sheet — 154 wordsGoing deeper — 105 wordsReview — 342 words

deploy.service runs a playbook at every boot to render the application's database settings. The password comes from an Ansible Vault file, and the project's ansible.cfg says ask_vault_pass = true. That works perfectly wh

2518 words · 8 review questions

40 min OllamaAI ServicesNetworking

A proxy in front of a model is not a proxy in front of a web page

What you should be able to do after this — 124 wordsThe mechanism — 1661 wordsA failure, walked through — 971 wordsCommon wrong turns — 603 wordsCheat sheet — 323 wordsGoing deeper — 138 wordsReview — 658 words

Four faults, and only one of them is exotic. The models were moved and left owned by root, so the service account cannot read them. The service was never enabled. The proxy points at a port nothing listens on. And then t

3479 words · 8 review questions

45 min AI ServicesUsers and permissionsLogging and journald

Every place a secret can leak from

What you should be able to do after this — 124 wordsThe mechanism — 2336 wordsA failure, walked through — 843 wordsCommon wrong turns — 511 wordsCheat sheet — 339 wordsGoing deeper — 108 wordsReview — 600 words

The security review found four things wrong with the chat gateway, and none of them is a bug in the usual sense. The code does what it was told. The upstream API key is simply everywhere: in a world-readable file and in

4050 words · 8 review questions

40 min AI AgentsBoot and systemdUsers and permissions

An agent is a loop with tools, and systemd decides how often it runs

What you should be able to do after this — 83 wordsThe mechanism — 560 wordsA failure, walked through — 537 wordsCommon wrong turns — 244 wordsCheat sheet — 139 wordsGoing deeper — 74 wordsReview — 408 words

Strip the vocabulary away and an AI agent is a small program: ask a model what to do, do it, tell the model what happened, repeat until it stops asking. Everything dangerous about agents lives in three parts of that sent

1735 words · 8 review questions

30 min OllamaNetworkingUsers and permissions

A model server has no passwords, so the network and the proxy are its only locks

What you should be able to do after this — 65 wordsThe mechanism — 548 wordsA failure, walked through — 391 wordsCommon wrong turns — 185 wordsCheat sheet — 135 wordsGoing deeper — 101 wordsReview — 324 words

Ollama is a program that loads language models and serves them over HTTP on port 11434. Its API is small and powerful: list models, generate text, chat, embed, and also pull new models from the internet and delete existi

1493 words · 8 review questions

35 min OllamaAI Services

A model follows only the instructions that fit in its context window

What you should be able to do after this — 64 wordsThe mechanism — 503 wordsA failure, walked through — 455 wordsCommon wrong turns — 168 wordsCheat sheet — 101 wordsGoing deeper — 75 wordsReview — 368 words

A language model does not remember its instructions. Each request sends them again — the system prompt, then the conversation, then the new question — and the model reads that whole text as one sequence of tokens, up to

1523 words · 8 review questions

35 min OllamaKernel and performanceBoot and systemd

A loaded model costs its weights plus a cache for every token it may hold

What you should be able to do after this — 60 wordsThe mechanism — 448 wordsA failure, walked through — 409 wordsCommon wrong turns — 192 wordsCheat sheet — 154 wordsGoing deeper — 115 wordsReview — 365 words

"The model is 400 MB" is true of the file and says little about the server. To answer, the runtime loads the weights, adds its own working memory, and reserves a key-value cache: for every token of context, in

1492 words · 8 review questions

35 min PythonBoot and systemd

Your shell is not the environment

What you should be able to do after this — 99 wordsThe mechanism — 1609 wordsA failure, walked through — 800 wordsCommon wrong turns — 467 wordsCheat sheet — 245 wordsGoing deeper — 61 wordsReview — 490 words

The author is telling the truth: the job works on their machine. They cd /opt/etl, they source .venv/bin/activate, they run python report.py, and a report appears. What they are actually describing is a job that depends

3012 words · 8 review questions

35 min BashLinux basics

A deploy script is a transaction, or it is a hazard

What you should be able to do after this — 133 wordsThe mechanism — 1329 wordsA failure, walked through — 1039 wordsCommon wrong turns — 328 wordsCheat sheet — 238 wordsGoing deeper — 80 wordsReview — 408 words

deploy-site is eight lines long and does what every deploy script does: make a directory, unpack a release into it, point the live link at it, say so. On a good day it works, and it worked on every good day for months. T

2714 words · 8 review questions

35 min BashBoot and systemd

Deleting files is the one thing a script must get exactly right

What you should be able to do after this — 104 wordsThe mechanism — 990 wordsA failure, walked through — 1057 wordsCommon wrong turns — 278 wordsCheat sheet — 231 wordsGoing deeper — 93 wordsReview — 339 words

Most scripts that go wrong produce the wrong output. A cleanup script that goes wrong produces the wrong absence, and absence is hard to notice and impossible to undo. prune-releases is one line of real work — ls -t | ta

2264 words · 8 review questions

30 min BashLinux basics

A file name is any byte but slash and NUL — a backup has to believe it

What you should be able to do after this — 128 wordsThe mechanism — 611 wordsA failure, walked through — 392 wordsCommon wrong turns — 189 wordsCheat sheet — 126 wordsGoing deeper — 82 wordsReview — 252 words

backup-docs looks like the most boring script on the machine: find every file, make its directory in the backup, copy it, count it, say how many. It ran every night for months and systemd marked every run as a success. I

1595 words · 6 review questions

30 min BashBoot and systemd

A script run by a timer inherits nothing you set up for yourself

What you should be able to do after this — 105 wordsThe mechanism — 555 wordsA failure, walked through — 460 wordsCommon wrong turns — 205 wordsCheat sheet — 104 wordsGoing deeper — 50 wordsReview — 193 words

"It works when I run it" is the most expensive sentence in operations, because it is true. The person saying it is logged in, in an interactive shell that has read a start-up file, sitting in a directory they c

1476 words · 6 review questions

35 min BashLinux basics

Publish when complete, clean up however it ends

What you should be able to do after this — 97 wordsThe mechanism — 660 wordsA failure, walked through — 617 wordsCommon wrong turns — 209 wordsCheat sheet — 80 wordsGoing deeper — 46 wordsReview — 268 words

An export is read by someone else. That one fact changes what "done" means for the script that writes it: the warehouse importer does not wait for the script to finish, it takes whatever file has the right name

1694 words · 6 review questions

30 min BashLogging and journald

Nothing matched is an answer, not a failure

What you should be able to do after this — 90 wordsThe mechanism — 455 wordsA failure, walked through — 382 wordsCommon wrong turns — 152 wordsCheat sheet — 140 wordsGoing deeper — 65 wordsReview — 224 words

set -euo pipefail is good advice, and the review that asked for it was right. What the review did not say is that set -e acts on a single signal — a non-zero exit status — and that several perfectly ordinary commands use

1306 words · 6 review questions

35 min BashUsers and permissions

A value is data; sed's replacement is code

What you should be able to do after this — 98 wordsThe mechanism — 621 wordsA failure, walked through — 435 wordsCommon wrong turns — 165 wordsCheat sheet — 97 wordsGoing deeper — 39 wordsReview — 244 words

Filling placeholders in a template is the second thing every ops script learns to do, and sed s/@PLACEHOLDER@/$value/ is how almost everyone writes it. It works for a year, because the values are host names and port numb

1507 words · 6 review questions

35 min Claude CodeAI Agents

A headless agent gets the permissions you write down, and nothing asks twice

What you should be able to do after this — 129 wordsThe mechanism — 851 wordsA failure, walked through — 613 wordsCommon wrong turns — 253 wordsCheat sheet — 216 wordsGoing deeper — 111 wordsReview — 506 words

A nightly job asks Claude Code to fix typos. It "kept stopping to ask for permission", so someone added --dangerously-skip-permissions, and for weeks nothing bad happened. Then the model decided that a director

2378 words · 8 review questions

35 min Claude CodeBash

A hook is a policy only if it fires, reads its input and exits 2

What you should be able to do after this — 100 wordsThe mechanism — 640 wordsA failure, walked through — 765 wordsCommon wrong turns — 243 wordsCheat sheet — 178 wordsGoing deeper — 80 wordsReview — 488 words

Hooks are the part of Claude Code that turns a team's rules into code that runs every time: format what the agent writes, refuse a push, keep it out of files that must not change. They are also the part that fails most q

2049 words · 8 review questions

30 min Claude CodeAI Agents

A subagent exists only where Claude Code looks, with the keys it requires

What you should be able to do after this — 84 wordsThe mechanism — 648 wordsA failure, walked through — 386 wordsCommon wrong turns — 189 wordsCheat sheet — 134 wordsGoing deeper — 92 wordsReview — 375 words

A subagent is a Markdown file: a few lines of YAML frontmatter and a system prompt. Teams put real effort into the prompt — the payments team's security reviewer lists exactly what to look for and how to report it — and

1594 words · 8 review questions

35 min Claude CodeAI Agents

An MCP server has to be enabled, startable, allowed and given its secret

What you should be able to do after this — 85 wordsThe mechanism — 573 wordsA failure, walked through — 552 wordsCommon wrong turns — 182 wordsCheat sheet — 168 wordsGoing deeper — 67 wordsReview — 353 words

The Model Context Protocol lets Claude Code use tools that live outside it: a ticket queue, a database, an internal API. A project declares its servers in .mcp.json, Claude Code starts each one when a session starts, ask

1652 words · 8 review questions

40 min Claude CodeAI Agents

A CI agent costs what its trigger, turn cap, model and tools allow

What you should be able to do after this — 93 wordsThe mechanism — 736 wordsA failure, walked through — 394 wordsCommon wrong turns — 216 wordsCheat sheet — 153 wordsGoing deeper — 83 wordsReview — 376 words

A job that asks Claude Code to label an issue should cost a fraction of a cent and take seconds. The same job, written the way this lab's was, can cost as much as the model is willing to think about: it starts on every i

1866 words · 8 review questions

40 min Claude CodeLinux basics

Five settings levels, one winner per key, and a policy only if it can be read

What you should be able to do after this — 76 wordsThe mechanism — 711 wordsA failure, walked through — 544 wordsCommon wrong turns — 195 wordsCheat sheet — 150 wordsGoing deeper — 81 wordsReview — 389 words

Claude Code reads its configuration from up to five places, and on a shared machine each belongs to someone different: the security team owns the managed policy, whoever runs a session owns the command line, a developer

1834 words · 8 review questions

35 min ContainersBoot and systemd

A container is disposable; its data must not be

What you should be able to do after this — 102 wordsThe mechanism — 901 wordsA failure, walked through — 828 wordsCommon wrong turns — 301 wordsCheat sheet — 151 wordsGoing deeper — 103 wordsReview — 314 words

The job queue is Redis in a container, and every reboot empties it. Nothing crashes. Redis starts, answers PONG, accepts jobs, and on the next restart it starts again, empty, exactly as configured. The unit that runs it

2228 words · 8 review questions

40 min ContainersNetworking

Inside a container, localhost is the container

What you should be able to do after this — 88 wordsThe mechanism — 905 wordsA failure, walked through — 932 wordsCommon wrong turns — 234 wordsCheat sheet — 158 wordsGoing deeper — 95 wordsReview — 340 words

The shop is two nginx containers in one Compose project: web, the public front, and api, which serves a status document. The front's configuration passes /api/ to http://localhost:8089/, and port 8089 is where the API is

2199 words · 8 review questions

20 min Linux basicsUsers and permissions

Nine letters and a refusal

What you should be able to do after this — 99 wordsThe mechanism — 1143 wordsA failure, walked through — 307 wordsCommon wrong turns — 226 wordsCheat sheet — 285 wordsGoing deeper — 45 wordsReview — 342 words

The first lab is five minutes long and has two tasks: make a file readable, and write a word into another file. It is small on purpose. It is also, in miniature, every lab that follows: something is refused, the system w

1920 words · 6 review questions

30 min Storage and LVMLogging and journald

The space that belongs to a file with no name

What you should be able to do after this — 122 wordsThe mechanism — 2296 wordsA failure, walked through — 842 wordsCommon wrong turns — 498 wordsCheat sheet — 380 wordsGoing deeper — 123 wordsReview — 610 words

A colleague saw a full disk, deleted the biggest file on it, and went home. df still says the filesystem is nearly full; du says it is nearly empty. Nothing about that is a contradiction, and nothing about it is unusual

3727 words · 8 review questions

40 min Boot and systemdFirewall and SELinuxNetworking

Four reasons a service will not stay up

What you should be able to do after this — 118 wordsThe mechanism — 2056 wordsA failure, walked through — 824 wordsCommon wrong turns — 525 wordsCheat sheet — 341 wordsGoing deeper — 116 wordsReview — 588 words

"It sometimes comes up, and a few minutes later it is gone. After a reboot it never comes back, and colleagues see an old page saying the service was retired." That is three different sentences about three diff

3421 words · 8 review questions

35 min BashLinux basics

A script that cannot fail is not a backup

What you should be able to do after this — 126 wordsThe mechanism — 1766 wordsA failure, walked through — 959 wordsCommon wrong turns — 497 wordsCheat sheet — 407 wordsGoing deeper — 58 wordsReview — 641 words

The script has written "backup OK" every night for a year. It is not lying on purpose: it ends with echo "backup OK" and exit 0, unconditionally, so there is no state of the world in which it says any

3292 words · 8 review questions

45 min BashLinux basics

Counting things, and the specification is the test

What you should be able to do after this — 131 wordsThe mechanism — 1904 wordsA failure, walked through — 801 wordsCommon wrong turns — 556 wordsCheat sheet — 448 wordsGoing deeper — 54 wordsReview — 606 words

This lab does not break a machine. It hands you a specification — eleven lines of it — and grades your script against logs you have not seen. That is a different skill from repair, and it is the one most of the small too

3471 words · 8 review questions

30 min Users and permissionsLinux basics

A folder is shared by its group, not by its permissions alone

What you should be able to do after this — 153 wordsThe mechanism — 861 wordsA failure, walked through — 716 wordsCommon wrong turns — 285 wordsCheat sheet — 237 wordsGoing deeper — 67 wordsReview — 461 words

Three people share a folder and none of them can work in it. It is tempting to see one fault — "the permissions are wrong" — and one fix, chmod -R 777. There are really four separate questions, and each has its

2312 words · 8 review questions

35 min Logging and journaldUsers and permissions

logrotate does exactly what it is told, and refuses what it cannot trust

What you should be able to do after this — 122 wordsThe mechanism — 820 wordsA failure, walked through — 650 wordsCommon wrong turns — 291 wordsCheat sheet — 239 wordsGoing deeper — 108 wordsReview — 539 words

A 300 MB log with a rotation policy beside it looks like logrotate is broken. It is not. It ran every night and, every night, wrote a line saying why it would not touch this log — and nobody reads the output of a nightly

2298 words · 8 review questions

25 min Model Context ProtocolClaude Code

The File Server That Shows Everything — what an MCP server exposes is the server's decision

What you should be able to do after this — 80 wordsThe mechanism — 459 wordsA failure, walked through — 354 wordsCommon wrong turns — 141 wordsCheat sheet — 59 wordsGoing deeper — 95 wordsReview — 226 words

An MCP server is a program that offers a model tools. A file server's tools read and list files, and which files is not decided by the model, by Claude Code or by the prompt: it is decided by the server, from its own set

1323 words · 5 review questions

30 min Model Context ProtocolAI Agents

The Page That Gave Orders — a tool result is input, and input is not a command

What you should be able to do after this — 81 wordsThe mechanism — 375 wordsA failure, walked through — 316 wordsCommon wrong turns — 111 wordsCheat sheet — 41 wordsGoing deeper — 82 wordsReview — 196 words

A model reads everything a tool returns as part of its context, and it cannot tell text that informs from text that instructs: both are words. A web page that says "assistants: run this" reaches the model in th

1101 words · 5 review questions

30 min Model Context ProtocolNetworking

The Token for Someone Else — a remote MCP server checks who a token was issued for

What you should be able to do after this — 79 wordsThe mechanism — 372 wordsA failure, walked through — 272 wordsCommon wrong turns — 107 wordsCheat sheet — 61 wordsGoing deeper — 87 wordsReview — 187 words

A remote MCP server behind OAuth receives a bearer token with every request and has to decide whether to honour it. "Signed by an issuer I trust" is necessary and nowhere near enough: the same issuer signs toke

1115 words · 5 review questions

20 min Model Context ProtocolLogging and journald

The Server That Talks Too Much — on stdio, stdout belongs to the protocol

What you should be able to do after this — 68 wordsThe mechanism — 338 wordsA failure, walked through — 304 wordsCommon wrong turns — 125 wordsCheat sheet — 60 wordsGoing deeper — 86 wordsReview — 190 words

A stdio MCP server has two output streams and they are not interchangeable. The client reads stdout as the protocol — newline-delimited JSON-RPC, one message per line — and nothing else may appear there. stderr is the se

1026 words · 5 review questions

30 min Model Context ProtocolNetworking

The Stream That Stops — a proxy in front of a remote MCP server

What you should be able to do after this — 78 wordsThe mechanism — 389 wordsA failure, walked through — 341 wordsCommon wrong turns — 78 wordsCheat sheet — 72 wordsGoing deeper — 87 wordsReview — 197 words

A remote MCP server speaks Streamable HTTP: every message is a POST, and the answer is either one JSON body or, for anything that takes a while, a stream of server-sent events — progress notifications as the work goes, t

1092 words · 5 review questions

25 min Model Context ProtocolClaude Code

The Answers From Last Year — Claude Code's MCP scopes, and which one wins

What you should be able to do after this — 77 wordsThe mechanism — 369 wordsA failure, walked through — 366 wordsCommon wrong turns — 89 wordsCheat sheet — 60 wordsGoing deeper — 81 wordsReview — 173 words

Claude Code reads MCP server definitions from three places, and the same name can appear in more than one. The repository's .mcp.json is the one everybody reviews; the others live in ~/.claude.json, outside any repositor

1026 words · 5 review questions

35 min PythonBoot and systemd

A job that cannot fail cannot be trusted

What you should be able to do after this — 104 wordsThe mechanism — 1122 wordsA failure, walked through — 1030 wordsCommon wrong turns — 256 wordsCheat sheet — 178 wordsGoing deeper — 94 wordsReview — 324 words

sync.py is twenty lines of perfectly readable Python. It fetches a list from an HTTP API and writes it to a file. The dashboards that read the file showed zero machines for an hour, and during that hour systemd reported

2437 words · 8 review questions

35 min PythonUsers and permissions

A development install is not an installation

What you should be able to do after this — 111 wordsThe mechanism — 916 wordsA failure, walked through — 731 wordsCommon wrong turns — 244 wordsCheat sheet — 190 wordsGoing deeper — 39 wordsReview — 319 words

netprobe works. It works for the colleague who installed it, it works when they run it with sudo, and it has worked on their laptop for months. On this machine every other user gets command not found, and when they call

2191 words · 8 review questions

35 min PythonLinux basics

Text is bytes plus an encoding, and nobody else knows which one

What you should be able to do after this — 95 wordsThe mechanism — 549 wordsA failure, walked through — 433 wordsCommon wrong turns — 148 wordsCheat sheet — 94 wordsGoing deeper — 55 wordsReview — 263 words

A file on disk is bytes. "Text" is what you get when bytes are decoded with an encoding, and the file does not carry that encoding anywhere: not in its bytes, not in its name, not in its metadata. Somebody has

1460 words · 6 review questions

35 min PythonLogging and journald

A service that nobody can hear, and a stop that lands in the middle

What you should be able to do after this — 89 wordsThe mechanism — 649 wordsA failure, walked through — 438 wordsCommon wrong turns — 193 wordsCheat sheet — 102 wordsGoing deeper — 47 wordsReview — 269 words

Two properties of a long-running program matter more than its speed: you can see what it is doing, and you can stop it without breaking anything. This worker has neither, and both failures come from defaults that are rig

1524 words · 6 review questions

30 min PythonLinux basics

Where Python looks for a module, and who gets there first

What you should be able to do after this — 87 wordsThe mechanism — 538 wordsA failure, walked through — 340 wordsCommon wrong turns — 135 wordsCheat sheet — 101 wordsGoing deeper — 44 wordsReview — 199 words

AttributeError: module 'calendar' has no attribute 'monthrange' is a strange thing to read. The standard library's calendar module has had monthrange since the 1990s, so the sentence can only mean one thing: the calendar

1224 words · 6 review questions

40 min PythonBoot and systemd

One writer at a time, and a file that is only ever whole

What you should be able to do after this — 74 wordsThe mechanism — 578 wordsA failure, walked through — 371 wordsCommon wrong turns — 200 wordsCheat sheet — 92 wordsGoing deeper — 59 wordsReview — 250 words

A timer that starts a job every minute is a promise about how often the job starts, not about how long it takes. The day the catalogue grows past a minute's work, two rebuilds run at once, and they are both writing the s

1387 words · 6 review questions

40 min PythonUsers and permissions

A secret has three addresses: the log, the file and the process

What you should be able to do after this — 97 wordsThe mechanism — 626 wordsA failure, walked through — 455 wordsCommon wrong turns — 218 wordsCheat sheet — 96 wordsGoing deeper — 54 wordsReview — 244 words

"Where is the token?" has more answers than people expect. It is in a file, which has an owner and a mode. It is in a process, which runs as some account. And it is in everything that process says about itself

1585 words · 6 review questions

35 min Users and permissions

The account that was almost on the team

What you should be able to do after this — 140 wordsThe mechanism — 1752 wordsA failure, walked through — 536 wordsCommon wrong turns — 407 wordsCheat sheet — 315 wordsGoing deeper — 101 wordsReview — 581 words

Nothing in this lab is broken in an interesting way. An account was created, a directory was made, a sudo rule was written, a umask was set during onboarding — and every one of those five ordinary acts was done one chara

3093 words · 8 review questions

40 min Boot and systemd

Enabled, masked, wanted — and none of them the same thing

What you should be able to do after this — 123 wordsThe mechanism — 1917 wordsA failure, walked through — 994 wordsCommon wrong turns — 450 wordsCheat sheet — 293 wordsGoing deeper — 61 wordsReview — 546 words

An admin starts the inventory API by hand and it works. The machine reboots and the API is gone, and now systemctl start fails too. Somewhere in the middle of that story is the sentence that explains the whole lab: the h

3592 words · 8 review questions

40 min Storage and LVMBoot and systemd

The volume that filled overnight

What you should be able to do after this — 124 wordsThe mechanism — 2016 wordsA failure, walked through — 948 wordsCommon wrong turns — 402 wordsCheat sheet — 261 wordsGoing deeper — 77 wordsReview — 411 words

A full filesystem is the most ordinary emergency there is, and the machine in this lab is what happens when somebody fixes one at three in the morning. The volume filled. They freed some space, edited /etc/fstab, reboote

2984 words · 8 review questions

55 min Firewall and SELinuxNetworking

Three layers of "permission denied"

What you should be able to do after this — 158 wordsThe mechanism — 2494 wordsA failure, walked through — 1304 wordsCommon wrong turns — 623 wordsCheat sheet — 383 wordsGoing deeper — 94 wordsReview — 620 words

A web server that will not start. A page that answers 403. A proxy that answers 502. An address and a hostname that were correct until the machine rebooted. Every symptom in this lab has a plausible wrong explanation — t

4252 words · 8 review questions

70 min Users and permissionsBoot and systemdStorage and LVMNetworkingLinux basics

Ninety minutes on a machine that will not boot

What you should be able to do after this — 147 wordsThe mechanism — 3407 wordsA failure, walked through — 1213 wordsCommon wrong turns — 863 wordsCheat sheet — 441 wordsGoing deeper — 217 wordsReview — 635 words

Fifteen tasks, ninety minutes, and a pass line of seventy per cent — eleven tasks. You do not know the root password, your own sudo is gone, and the machine does not finish booting, so the first thing to earn is a shell.

5181 words · 8 review questions

40 min TerraformUsers and permissions

Terraform knows your resources by their address

What you should be able to do after this — 93 wordsThe mechanism — 702 wordsA failure, walked through — 873 wordsCommon wrong turns — 223 wordsCheat sheet — 200 wordsGoing deeper — 146 wordsReview — 347 words

A pull request renamed two resources in /srv/infra — random_password.key became random_password.session_key, local_file.env became local_file.app_env — because the new names say what the things are. Nothing about the obj

2105 words · 8 review questions

40 min TerraformNetworking

count numbers things; for_each names them

What you should be able to do after this — 114 wordsThe mechanism — 837 wordsA failure, walked through — 854 wordsCommon wrong turns — 242 wordsCheat sheet — 140 wordsGoing deeper — 139 wordsReview — 337 words

Three virtual hosts, one list: sites = ["shop", "blog", "docs"]. Terraform creates a configuration file and a cookie secret for each, and derives each site's port from its position — 8100, 8

2008 words · 8 review questions

Notes

On paper

e on a journal in the TUI exports it as a PDF — light ground, green accents, running header and page numbers, made for printing and annotating. The screen version stays dark, because that is where the terminal is.