diff --git a/docs.json b/docs.json
index 419a643..dcaedc3 100644
--- a/docs.json
+++ b/docs.json
@@ -77,6 +77,17 @@
"repositories"
]
},
+ {
+ "group": "Explainers",
+ "pages": [
+ "explainers/overview",
+ "explainers/what-is-a-hypervisor",
+ "explainers/clusters-and-quorum",
+ "explainers/staying-up-when-a-machine-dies",
+ "explainers/one-login-for-everything",
+ "explainers/secrets-that-expire"
+ ]
+ },
{
"group": "Architecture",
"pages": [
diff --git a/explainers/clusters-and-quorum.mdx b/explainers/clusters-and-quorum.mdx
new file mode 100644
index 0000000..8cdd7cd
--- /dev/null
+++ b/explainers/clusters-and-quorum.mdx
@@ -0,0 +1,91 @@
+---
+title: "Clusters and quorum"
+description: "Why several hypervisor hosts are joined into one system, and why the number of votes matters more than the number of machines."
+page_type: explanation
+---
+
+> Two machines that disagree about who is in charge will each confidently do the wrong thing. Quorum is how you stop that.
+
+A **cluster** is several hypervisor hosts managed as one system. You get one place to see everything, guests can move between hosts, and — the real prize — the cluster can react automatically when a host disappears.
+
+Joining machines together creates a problem that does not exist with one machine: they now have to agree on things, and the network between them can fail.
+
+## The split-brain problem
+
+Picture two hosts and a network cable between them. The cable is cut. Neither host is broken; each simply cannot reach the other.
+
+From inside each host, that is indistinguishable from *the other one died*. So each concludes it is the survivor and starts the guests it thinks were lost. Now the same guest is running twice, on two hosts, both writing to what they believe is the same disk.
+
+That is **split-brain**, and it corrupts data rather than merely causing downtime. It is the failure that cluster design exists to prevent.
+
+{/* Shape: parallel convergence. The severed link forces two independent verdicts. 5 nodes. */}
+{/* Subgraphs are physical machines — a real co-location, not a role grouping. */}
+
+```mermaid
+%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
+flowchart LR
+ subgraph A["node-a"]
+ HostA([Hypervisor A])
+ GuestA([Guest, running])
+ end
+
+ Link{Network link}
+
+ subgraph B["node-b"]
+ HostB([Hypervisor B])
+ GuestB([Guest, also running])
+ end
+
+ HostA --> Link
+ Link --> HostB
+ HostA --> GuestA
+ HostB --> GuestB
+
+ classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
+ classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6;
+ classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2.5px,color:#F4EFE6;
+
+ class HostA,HostB host
+ class Link gate
+ class GuestA,GuestB sink
+
+ linkStyle 0,1 stroke:#E06B4A,stroke-width:2px,stroke-dasharray:4 4;
+```
+
+## Quorum is the fix
+
+Each host gets a vote. A host may only run guests if it can see **more than half** of all votes. Not half — *more than* half.
+
+With four hosts, four votes, a majority is three. Split them two-and-two and neither side has three, so **both sides stop**. That sounds like a worse outcome than split-brain until you remember the alternative was silent data corruption. Downtime is recoverable; two writers on one disk often isn't.
+
+| Hosts | Votes needed | Can survive losing |
+| --- | --- | --- |
+| 2 | 2 | nothing — losing either stops the cluster |
+| 3 | 2 | one host |
+| 4 | 3 | one host |
+| 5 | 3 | two hosts |
+
+
+Read the two-host row carefully. Adding a second machine for redundancy, with no other change, makes things **worse** — you go from one machine that can fail to two machines that each can take the cluster down. This surprises nearly everyone.
+
+
+## Why odd numbers
+
+Four hosts survive exactly as many failures as three do, and cost you an extra machine to reach that identical result. Five survive two. So the useful counts are odd, and the sizes that actually buy something are 3 and 5.
+
+An even count is not wrong — it is simply paying for a machine that adds no fault tolerance. Where an even count exists, it is usually because the extra host was added for capacity rather than resilience, which is a perfectly good reason.
+
+
+Some clusters solve the two-host case with a **witness** — a tiny third voter that holds no guests and exists only to break ties. It can be something as small as a Raspberry Pi. Three votes, two machines' worth of hardware.
+
+
+## Where to go next
+
+
+
+ Quorum decides who may act. This is what they actually do.
+
+
+ The layer underneath, if clusters are getting ahead of you.
+
+
diff --git a/explainers/one-login-for-everything.mdx b/explainers/one-login-for-everything.mdx
new file mode 100644
index 0000000..1b4d517
--- /dev/null
+++ b/explainers/one-login-for-everything.mdx
@@ -0,0 +1,89 @@
+---
+title: "One login for everything"
+description: "What single sign-on actually does when you click a service, and why one login for twenty apps is safer than twenty passwords."
+page_type: explanation
+---
+
+> Twenty self-hosted apps means twenty login screens, twenty password policies, and twenty chances for one of them to store your password badly.
+
+Single sign-on replaces all of that with one identity that every application trusts. You log in once. Every service afterwards recognises you without ever seeing a password.
+
+The instinctive objection — *isn't one login a single point of failure?* — is worth taking seriously, and the answer is the opposite of what it looks like.
+
+## Why one login is safer than twenty
+
+Twenty applications each storing your password means twenty implementations of password hashing, twenty databases that could leak, and twenty places a reused password becomes a breach everywhere else. Self-hosted software varies enormously in how carefully it does this, and you generally cannot tell which is which from outside.
+
+With SSO, only one system ever handles the password. That one system can afford strong protections — hardware-backed second factors, passkeys, rate limiting, real audit logging — because you configure it once rather than twenty times. The applications never see the password at all, so they cannot leak it.
+
+## What happens when you click
+
+There are two mechanisms doing different jobs, and both are usually present.
+
+**A gate at the front door.** A reverse proxy sits in front of every service. Before passing a request through, it asks the identity provider: is this person logged in? If not, the request never reaches the application — it is redirected to a login page instead. The application isn't merely unauthenticated at that point; it is unreachable.
+
+**An identity handshake.** Once past the gate, the application often wants to know *who* you are, to show your own dashboard. It bounces you to the identity provider, which hands back a signed statement — you are this person, in these groups. Because it is signed, the application can verify it without trusting the browser.
+
+{/* Shape: linear chain with a gate. 6 nodes covering both mechanisms in one pass. */}
+{/* Boundary crossings: 0. The identity provider is reached from the gate, not the app. */}
+
+```mermaid
+%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
+flowchart LR
+ You((You))
+ Proxy([Reverse proxy])
+ Gate{Logged in?}
+ Idp([Identity provider])
+ App([Application])
+ Done([Your dashboard])
+
+ You --> Proxy
+ Proxy --> Gate
+ Gate -->|no| Idp
+ Idp --> Gate
+ Gate -->|yes| App
+ App --> Done
+
+ classDef external fill:#102937,stroke:#E6B35A,stroke-width:2px,color:#F4EFE6;
+ classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
+ classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6;
+ classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2.5px,color:#F4EFE6;
+
+ class You external
+ class Proxy,Idp,App host
+ class Gate gate
+ class Done sink
+```
+
+## The header trap
+
+The gate tells the application who you are by adding a header to the request — something like `Remote-User: you`. The application trusts it completely.
+
+Which means: if a browser could *send* that header itself, anyone could claim to be anyone.
+
+So the proxy must **strip those headers from every incoming request before doing anything else**, then re-add the real values only after authenticating. Order matters absolutely here. Strip-then-authenticate is secure. Authenticate-then-strip erases the real identity and leaves the forged one. The two configurations look nearly identical and behave completely differently.
+
+
+This is worth testing rather than assuming. Send a request with a forged identity header to a gated path and confirm you are challenged rather than logged in. It is a one-line check that catches a total authentication bypass.
+
+
+## Machines don't use this
+
+API clients, scripts and integrations do not log in through a browser, so making them traverse a login page breaks them. They authenticate with their own credential — a token scoped to what that client may do — and bypass the browser gate entirely.
+
+That bypass is exactly why the header strip has to be unconditional. If an API path skips the gate, and headers are only stripped on gated paths, then the API path will happily accept a forged identity.
+
+
+Groups are the other half. The identity provider states which groups you belong to, and applications use those for permissions. The trap is that applications disagree about the *shape* they expect — some want a bare group name, some want it qualified with an organisation. Emit the wrong shape and login succeeds while permissions silently do not, which reads as a broken app rather than a config error.
+
+
+## Where to go next
+
+
+
+ How the machine credentials mentioned above are issued.
+
+
+ The technical view of secrets handling across the stack.
+
+
diff --git a/explainers/overview.mdx b/explainers/overview.mdx
new file mode 100644
index 0000000..fcb5e0b
--- /dev/null
+++ b/explainers/overview.mdx
@@ -0,0 +1,78 @@
+---
+title: "Homelab explainers"
+description: "Plain-language explanations of what a homelab is and how this one works — no prior infrastructure knowledge assumed."
+page_type: explanation
+---
+
+> Everything else on this site assumes you already know what a hypervisor is. These pages don't.
+
+A **homelab** is a small set of computers you run yourself, at home, to host the software you'd otherwise rent from someone else — photo storage, dashboards, a password manager, a media library, monitoring for your own network.
+
+People build them for three reasons that usually arrive in this order: curiosity, then cost, then control. Curiosity gets you the first machine. Cost keeps you going when you notice how many monthly subscriptions one box replaces. Control is the one that lasts — your data stays on hardware you can physically touch, and nothing gets discontinued because a company changed direction.
+
+The tradeoff is real and worth saying plainly: **you become the operations team.** When it breaks at 2am, nobody else is paged. Most of what's described in these pages exists to make that happen less often, and to make it recoverable when it does.
+
+## Start here
+
+
+
+ How one physical machine safely pretends to be many separate ones.
+
+
+ Why several machines are joined together, and why the count is odd.
+
+
+ Backup, replication and failover are three different things.
+
+
+ What single sign-on actually does, and why it's safer than it sounds.
+
+
+ Why passwords here are minted on demand instead of stored.
+
+
+
+## The shape of it
+
+Four layers, each depending on the one below. Most homelab problems are a layer confusion — a networking problem being debugged as an application problem, or vice versa.
+
+{/* Shape: linear chain. 4 nodes, top to bottom dependency order. Boundary crossings: 0. */}
+{/* Aspect ratio ~3:1 horizontal, within tolerance for a 4-node chain. */}
+
+```mermaid
+%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
+flowchart LR
+ Hw([Physical machines])
+ Hv([Hypervisor])
+ Gst([Guests])
+ App([Applications])
+
+ Hw --> Hv
+ Hv --> Gst
+ Gst --> App
+
+ classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
+ classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2.5px,color:#F4EFE6;
+
+ class Hw,Hv,Gst host
+ class App sink
+
+ click Hv "/explainers/what-is-a-hypervisor" "One machine, many guests"
+```
+
+**Physical machines** are the actual computers. **The hypervisor** is the software that divides each one into isolated slices. **Guests** are those slices, each behaving like its own computer. **Applications** are what you actually wanted — the photo library, the dashboard.
+
+
+Throughout these pages, internal names appear as placeholders — `example.local` for the internal domain, `node-a` and `node-b` for machines. That's deliberate: the concepts are the point, and publishing a real map of a private network isn't.
+
+
+## Where to go next
+
+
+
+ The technical view of the same stack, once these pages make sense.
+
+
+ The six surfaces this site is organised around.
+
+
diff --git a/explainers/secrets-that-expire.mdx b/explainers/secrets-that-expire.mdx
new file mode 100644
index 0000000..13bc11f
--- /dev/null
+++ b/explainers/secrets-that-expire.mdx
@@ -0,0 +1,97 @@
+---
+title: "Secrets that expire"
+description: "Why passwords and API keys here are issued on demand and die shortly after, instead of being stored in a file someone has to remember to rotate."
+page_type: explanation
+---
+
+> A password stored in a file is a password you will still be finding in five years, in places you forgot you put it.
+
+Automation needs credentials. A backup job needs the storage password, a deployment needs an API token. The obvious approach is to put them in a config file and lock it down.
+
+That approach fails in a specific, predictable way, and it is not usually a dramatic breach. It is entropy.
+
+## How stored credentials rot
+
+They spread. A credential in a file gets copied into a second file for a second job, then into someone's notes to debug something at 1am, then into a CI variable. Nobody tracks the copies because each copy seemed reasonable at the time.
+
+They outlive their purpose. The token issued for a one-off migration two years ago still works, still has full access, and nobody remembers it exists.
+
+And rotation becomes frightening. Changing a credential means finding every copy, and since nobody knows where they all are, the rational choice is to leave it alone. So credentials get older and more widely spread, permanently.
+
+## Issue on demand instead
+
+Flip the model. Instead of storing credentials, store the *authority to create them*, and mint one when needed.
+
+
+
+ A job starts and needs to read from storage.
+
+
+ Not with the target credential, but with its own identity — one that says what role it plays, not what it may read.
+
+
+ The secrets manager generates a brand-new one, valid for this job, scoped to exactly what this role may do, and set to expire in an hour.
+
+
+ The job finishes. Shortly after, the credential stops working — whether or not anyone remembered to clean it up.
+
+
+
+{/* Shape: linear chain, request through to expiry. 5 nodes, one gate. */}
+{/* Boundary crossings: 0. The store is a cylinder; the policy check is the gate. */}
+
+```mermaid
+%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
+flowchart LR
+ Job([Automation job])
+ Check{Allowed?}
+ Store[(Secrets manager)]
+ Cred([Short-lived credential])
+ Gone((Expires))
+
+ Job --> Check
+ Check --> Store
+ Store --> Cred
+ Cred --> Gone
+
+ classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
+ classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6;
+ classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2.5px,color:#F4EFE6;
+ classDef external fill:#102937,stroke:#E6B35A,stroke-width:2px,color:#F4EFE6;
+
+ class Job,Cred host
+ class Check gate
+ class Store sink
+ class Gone external
+```
+
+## What this buys
+
+**Leaks have a deadline.** A credential found in a log tomorrow expired an hour after it was issued. This does not make a leak fine — it makes it survivable.
+
+**Rotation stops being an event.** Every credential is new. There is no rotation project because there is nothing old to rotate.
+
+**Access becomes visible.** Every issue is logged: which identity, which path, when. "Who read this?" becomes a query rather than an investigation.
+
+**Revocation is real.** Remove a role's permission and the next request fails. You are not hunting copies, because there are no copies to hunt.
+
+## Where it bottoms out
+
+Something has to be trusted first. The job needs *some* credential to prove its identity, and that one cannot itself be issued on demand — this is the bootstrapping problem, and it does not fully disappear.
+
+What it does is shrink. Instead of dozens of long-lived secrets spread across dozens of files, there is one small starting credential, and everything else derives from it. One thing to protect carefully is a much better position than fifty.
+
+
+The property worth insisting on is that a helper which cannot obtain a credential must **fail loudly**. A script that exits successfully having quietly exported nothing produces a confusing failure much later, in a different system, with no connection to the real cause. Silence is the expensive outcome, not the error.
+
+
+## Where to go next
+
+
+
+ The human-facing half of the same problem.
+
+
+ The concrete tooling this describes in the abstract.
+
+
diff --git a/explainers/staying-up-when-a-machine-dies.mdx b/explainers/staying-up-when-a-machine-dies.mdx
new file mode 100644
index 0000000..891a1bd
--- /dev/null
+++ b/explainers/staying-up-when-a-machine-dies.mdx
@@ -0,0 +1,111 @@
+---
+title: "Staying up when a machine dies"
+description: "Backup, replication and failover are three different things solving three different problems — and having one does not give you the others."
+page_type: explanation
+---
+
+> "It's replicated" and "it recovers" are not the same sentence. The gap between them is where outages live.
+
+Three mechanisms get discussed as though they were one. They are not, and the difference matters at exactly the moment you cannot afford to be confused.
+
+| | Protects against | Recovery time | Data lost |
+| --- | --- | --- | --- |
+| **Backup** | Deletion, corruption, ransomware, "last Tuesday" | Hours | Since the last backup |
+| **Replication** | Losing the disk or the machine | Minutes, and manual | Since the last sync |
+| **Failover** | Losing the machine | Automatic, minutes | Same as replication |
+
+The column that catches people is the last one. None of these gets you to zero data loss — that needs synchronous writes to two places at once, which costs latency on every single write forever.
+
+## Backup: a copy from the past
+
+A backup is a point-in-time copy kept somewhere separate. Its defining feature is that it is **old on purpose** — that is what lets you recover from a mistake that replication would have faithfully copied.
+
+If a bad deploy wipes a database at 3pm, replication has already dutifully wiped the copy. Only the backup still has the data.
+
+
+A backup you have never restored is a hypothesis, not a backup. The failure mode is discovering during a real incident that the archive was empty, the credentials expired months ago, or nobody knows the procedure. Rehearse restores on a schedule, from the archive, to a scratch target.
+
+
+## Replication: a copy from moments ago
+
+Replication continuously copies a guest's disk to another host. Set to sync every few minutes, the second copy is never more than a few minutes behind.
+
+This protects against losing hardware. It does **not** protect against a mistake, because it copies mistakes perfectly and immediately.
+
+Critically: replication on its own is **passive**. If the host dies, a healthy, current copy sits on another machine and does absolutely nothing. Someone has to notice, decide, and start it by hand.
+
+## Failover: the part that acts
+
+Failover is the piece that turns a copy into a recovery. The cluster notices a host has stopped answering, confirms it holds enough votes to act, and starts the affected guests elsewhere.
+
+{/* Shape: linear chain. Detection through to service restored. 5 nodes, one gate. */}
+{/* Boundary crossings: 0. Aspect ratio ~4:1, acceptable for a pure sequence. */}
+
+```mermaid
+%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
+flowchart LR
+ Fail((Host stops))
+ Detect([Cluster notices])
+ Vote{Enough votes?}
+ Start([Start on partner])
+ Live([Service restored])
+
+ Fail --> Detect
+ Detect --> Vote
+ Vote --> Start
+ Start --> Live
+
+ classDef external fill:#102937,stroke:#E6B35A,stroke-width:2px,color:#F4EFE6;
+ classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
+ classDef gate fill:#102937,stroke:#E06B4A,stroke-width:2.5px,color:#F4EFE6;
+ classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2.5px,color:#F4EFE6;
+
+ class Fail external
+ class Detect,Start host
+ class Vote gate
+ class Live sink
+
+ click Vote "/explainers/clusters-and-quorum" "Why votes decide this"
+```
+
+The gate in the middle is the quorum check. Without it, this diagram is the split-brain machine.
+
+## The pin nobody expects
+
+Failover has a constraint that is easy to miss: **a guest can only be restarted on a host that actually holds a copy of its disk.**
+
+If replication sends a guest's disk from `node-a` to `node-b`, then `node-b` is the only viable destination. Allowing the cluster to start it on `node-c` — which has no copy — produces a guest that boots into an empty disk, or refuses to boot at all.
+
+So each replicated guest is *pinned* to the pair of hosts that hold its data. Getting this wrong is worse than having no failover, because the automation confidently does something broken instead of leaving it for a human.
+
+
+Testing this is the only way to know it works. Deliberately move a guest to its partner and back, during a planned window, and watch whether the service stays reachable. "Configured for high availability" and "observed to survive" are different claims, and only the second one is evidence.
+
+
+## What to actually build
+
+
+
+ Everything else is optimisation. Backups are the only layer that recovers from mistakes, and an untested backup is not one.
+
+
+ A few minutes of drift is fine for most things. Not everything needs it — replicating a guest you could rebuild from scratch in ten minutes is effort spent for nothing.
+
+
+ The services other things depend on — DNS, authentication, the ingress that fronts everything. If those are down, being awake to fix the rest doesn't help.
+
+
+ Pick a service, fail it deliberately, time the recovery. Do it again after any change to the setup.
+
+
+
+## Where to go next
+
+
+
+ The same three ideas applied concretely to the shared application database.
+
+
+ The filesystem-level mechanics that make the snapshots cheap.
+
+
diff --git a/explainers/what-is-a-hypervisor.mdx b/explainers/what-is-a-hypervisor.mdx
new file mode 100644
index 0000000..013bf79
--- /dev/null
+++ b/explainers/what-is-a-hypervisor.mdx
@@ -0,0 +1,93 @@
+---
+title: "What a hypervisor is"
+description: "How one physical machine safely runs many isolated computers, and why that is the foundation everything else sits on."
+page_type: explanation
+---
+
+> A hypervisor is software whose entire job is convincing other software that it has a computer to itself.
+
+Buy a server and you get one machine. Install a hypervisor on it and you get as many machines as its memory will allow — each with its own operating system, its own network address, its own reboot button. They cannot see each other's files. One crashing does not disturb the others.
+
+This is not a trick of naming. The isolation is enforced by the processor itself, which has instructions designed for exactly this.
+
+## Why bother
+
+Because software is territorial. Two applications that each want to own port 443, or each want a different version of the same library, will fight forever on one operating system and coexist happily on two.
+
+The alternative — one physical machine per application — wastes almost everything. A typical service uses a few percent of a modern CPU. Running twenty of them on twenty machines means twenty power supplies, twenty sets of fans, and nineteen machines' worth of idle capacity.
+
+## Two kinds of guest
+
+The slices are called **guests**, and they come in two flavours that are easy to confuse.
+
+| | Virtual machine | Container |
+| --- | --- | --- |
+| What it virtualizes | The whole computer, down to fake hardware | Just the operating system's view of itself |
+| Runs its own kernel | Yes | No — shares the host's |
+| Boot time | Tens of seconds | Under a second |
+| Memory overhead | Hundreds of MB before your app starts | Almost none |
+| Isolation | Stronger | Strong, but a shared kernel is a shared risk |
+| Use when | You need a different OS, or a hard security boundary | You want density and speed, same OS family |
+
+Most guests here are containers, because most of what runs is Linux software on a Linux host and the overhead of a full virtual machine buys nothing. Virtual machines are used where something genuinely needs its own kernel, or where a vendor supports nothing else.
+
+{/* Shape: hierarchy. One host, two guest types, three leaf apps. 8 nodes. */}
+{/* Subgraph is a physical machine, which is a real co-location. Boundary crossings: 1 per edge max. */}
+
+```mermaid
+%%{init: {'theme':'base','look':'handDrawn','themeVariables':{'fontFamily':'Geist','fontSize':'14px','primaryColor':'#102937','primaryTextColor':'#F4EFE6','primaryBorderColor':'#4FB3A9','lineColor':'#4FB3A9','secondaryColor':'#0B1D2A','tertiaryColor':'#1A2A38','clusterBkg':'rgba(79,179,169,0.08)','clusterBorder':'#4FB3A9'}}}%%
+flowchart TB
+ subgraph Node["node-a"]
+ direction LR
+ Hv([Hypervisor])
+ Vm([Virtual machine])
+ Ct([Container])
+ end
+
+ Db[(Database)]
+ Web([Web app])
+ Api([API service])
+
+ Hv --> Vm
+ Hv --> Ct
+ Vm --> Db
+ Ct --> Web
+ Ct --> Api
+
+ classDef host fill:#102937,stroke:#4FB3A9,stroke-width:2px,color:#F4EFE6;
+ classDef sink fill:#102937,stroke:#F4EFE6,stroke-width:2.5px,color:#F4EFE6;
+
+ class Hv,Vm,Ct host
+ class Db,Web,Api sink
+```
+
+## What the hypervisor actually owns
+
+Three things, and knowing which layer owns what saves hours of misdirected debugging:
+
+
+
+ How much memory and how many CPU cores each guest may use. Overcommitting is allowed — guests can be promised more memory in total than physically exists, on the bet that they won't all want it at once. That bet occasionally loses.
+
+
+ Each guest gets a virtual disk. The hypervisor decides where that really lives — local drives, a shared array, or a filesystem that can snapshot it instantly.
+
+
+ A virtual switch inside the host. Guests plug into it and get addresses as though they were physical machines on a real network, which is why a guest can sit on a different network segment from its own host.
+
+
+
+
+When something breaks, identify the layer first. A guest that won't start is a hypervisor problem. A guest that starts but serves nothing is an application problem. They look identical from a browser showing a connection error.
+
+
+## Where to go next
+
+
+
+ What happens when you join several of these hosts together.
+
+
+ The technical version of the comparison above.
+
+