QinCloud Learnings

This is a teaching vault. Every milestone we built while turning a bare rented server into QinCloud is written up as a story that ramps from plain English an intelligent non-engineer can follow all the way down to the systems level a practitioner can operate from — commands, configs, file:line. Threaded through those stories are atomic, reusable concepts: the load-bearing principles the builds kept hitting, written once so they compound as every new milestone links back into them.

The point is not a changelog. It’s that the reasoning survives the box — the approach we planned, where reality deviated, how we found the fix, and the transferable lesson underneath.

How to read this

Every milestone note is built the same way, so you can stop wherever your curiosity does:

  • §1–4 are plain English. What we were building and why it matters, the initial plan, where it went sideways, and how the real fix was found — each opened with an analogy. No prior knowledge assumed.
  • §5+ descend to the systems level — the exact happy path, the gotchas, the file:line provenance, how it compares to production best practice, and the one transferable lesson.

The difficulty field in each note’s frontmatter tells you the depth of the deep half: 1 = any reader, 5 = deep systems. It never gates the top of a note — §1 is always approachable — it just tells you how far the bottom goes.

Start here

  • New to the project? Read m0-host-baseline first — the foundation pour, and the clearest example of “the thing you assumed was guarding you wasn’t.”
  • Want the one piece we actually wrote? Read m4-controld-deploy-engine — the deploy engine, a single linear state machine with one unbreakable rule.
  • Want the spine that runs through everything? Read the concept root-cause-over-patch.

Milestones

The build, in order. Each is one note: the narrative and the teaching.

MilestoneNoteThe hook
M0m0-host-baselineTurn a raw, internet-exposed box into a locked, self-defending base with one rerunnable script — before any service lands.
M1m1-edge-and-tlsOne Caddy front door: auto-HTTPS and on-the-fly rerouting — with one trap, that after first boot the live config, not the file, is truth.
M2m2-data-and-backupsPostgres and Redis on private nets, nightly off-site backups to R2 — and the part most skip: rehearsing the restore.
M3m3-observability-and-alertingStand up metrics, logs, and alerts — then prove a page reaches a human by killing a real service and watching it land in Discord.
M4m4-controld-deploy-engineThe only bespoke code: a Go state machine that deploys apps, whose single rule is a failed deploy never takes down what was already running.
M5m5-dashboardA server-rendered dashboard with no JS framework — server draws the page, htmx re-fetches slices, all state in one Postgres table.
M6m6-first-app-umamiGo from “deploys a toy container” to running a real stateful product — which forces the deploy contract to grow secrets and a database.
M8m8-disaster-recoveryDeliberately destroy the whole server, then rebuild it from script, git, and offsite backups in ~12 minutes — proving the disposability claim.
Extrax1-public-dashboard-cloudflarePut the box-deleting dashboard on the public internet behind three independent locks — and the afternoon a stale config file stole.
Extrax2-per-app-observabilityAnswer “how much is this one app using, and what is it logging?” after the standard container-metrics agent went silent on Docker 29.
Extrax3-verified-edge-deploysOne idempotent command that applies an edge config change and proves it — validate, heal the mount, reload, restore routes, confirm each site responds.

Concepts

The atomic, reusable principles the milestones keep hitting. These are the compounding core — link into them, and they get richer with every build.

ConceptThe principle
root-cause-over-patchA failure is a pointer to a real defect — fix the origin so the whole class of bug can’t recur, not just the spot that hurt.
fail-loud-at-boundariesValidate at every trust boundary and stop at the cause — silently substituting a default for bad input is broken and lying about it.
single-source-of-truthEvery fact lives in exactly one place; copies drift. Derive from the source, never duplicate it.
make-invalid-states-unrepresentableDon’t guard against the bad state — make it impossible to construct in the first place.
adversarial-reviewPoint a fresh reviewer at your work whose only job is to make it lie or fall over — then test each finding against the running system.
layered-trust-defense-in-depthNo single wrong assumption should be fatal; stack independent controls so a gap in one is caught by the next.
idempotent-self-verifying-operationsBuild operations you can safely re-run and that prove their own success before exiting.
the-box-is-disposableThe server is cattle, not a pet — the blueprint is what matters; you must be able to lose the box and rebuild it exactly.
verify-the-artifact-under-testBefore debugging why a fix “doesn’t work,” confirm the running system is actually executing your fix — otherwise it’s a hypothesis, not a fix.
observe-what-mattersA metric or alert isn’t done until you’ve seen it fire correctly, labelled the way a human asks the question.

For agents

Extending this vault? Read agents for how to add and link notes, and conventions for the frontmatter, filename, and linking rules. The teaching contract is non-negotiable: every note ramps from plain English to the systems level, and links liberally with [[slug]] so the graph stays navigable.