A private internal documentation set (infrastructure notes, runbooks, the kind of thing you write for future-you at 2am during an incident) is kept completely separate from this public site. It’s never merged in, never templated into a post, never referenced by path. That separation isn’t incidental; it’s the reason every one of these log posts exists in the form it does, describing real decisions and real trade-offs without describing the real infrastructure those decisions were made about.
Every one of these twenty posts came from somewhere. Some are close to pure architecture reasoning I can write directly. Others started as a private note about something that broke, or a decision that got made, and had to go through a real classification step before any of it became a paragraph on a public page. That step is the actual subject of this post: not what’s in the private notes, but the discipline of deciding what’s safe to say out loud.
The wrong question and the right one
The instinct when reviewing private material for public reuse is to ask “is this a secret?” It’s the wrong question, because it invites a narrow, technical answer (a password is a secret, an internal joke is not) and most of what matters lives in between. “It’s not a secret, it’s just an internal detail” is the sentence that lets people ship the wrong paragraph, because secret implies something formally classified, and most identifying detail was never formally anything. It’s just specific.
The question that actually sorts material correctly is: does this make an attacker’s job easier, even slightly, for zero benefit to the reader?
That framing does two things the “is it a secret” question doesn’t. First, it weighs cost against benefit instead of checking a binary label: a real IP address costs the reader nothing to lose (the lesson doesn’t depend on which IP it was) but could cost something if it leaks, so it fails the test even though nobody would call an IP address a “secret” in the credentials sense. Second, it scales down to details nobody would think to protect individually: a specific internal hostname naming convention, the exact directory layout of a private doc set, which port a management interface listens on. None of those are secrets. Every one of them is a small, free gift to someone building a map of your infrastructure, and the reader loses nothing if you generalize them away.
What never appears, what gets abstracted, what’s fine as-is
Three buckets, and most of the actual work is sorting things correctly between the second and third rather than agonizing over the first: the first bucket is usually obvious once you’re looking for it.
Never appears, full stop: credentials of any kind, real hostnames and IP addresses, internal-only URLs, hardware identifiers and model numbers, anything that narrows an attacker’s search space for a system that still exists and still runs the way the note describes. This bucket doesn’t get “generalized” — it gets deleted, because there’s no version of the specific detail that’s both accurate and safe to publish.
Needs abstraction before it’s usable: the shape of most operationally interesting material. “A managed production environment” instead of a real IP or hostname preserves the entire lesson (here’s how we handled a failure, here’s the trade-off we made) while dropping the one detail that would let a reader who is not the intended audience use the post as reconnaissance instead of as writing. This is the bucket that requires judgment, because abstraction can go wrong in both directions: too little, and you’ve just renamed the leak; too much, and you’ve abstracted away the thing that made the post worth reading. “A service had an outage” with no other detail teaches nothing. “A service in a specific network tier lost connectivity when a specific upstream provider had a routing issue, and the fix was X” teaches something, and none of that sentence needs a real hostname to be true and useful.
Fine to publish as-is: the reasoning itself. Why a trade-off was made, what the alternatives were, what broke and why, what the fix changed about the architecture. None of that requires identifying detail to be worth reading — if anything, identifying detail usually dilutes the lesson, because the specific IP address was never the interesting part of the story.
Why this is a discipline, not an audit
The failure mode of treating this as a one-time audit is obvious once you say it out loud: you review a document once, decide it’s safe, and then keep writing new sentences into contexts you’ve already cleared. A note that was accurate and safe in isolation stops being safe the moment it’s combined with three other cleared notes that, together, reconstruct something none of them exposed alone. Classification has to happen at the point of use — every time private material becomes source text for something public — not at some earlier point when the private material was first written down.
That’s a heavier practice than it sounds like, because it means the check runs on every post, every talk, every open-sourced tool, not just the first one. It’s the same reason a security review of a system isn’t a thing you do once and then trust forever — the system changes, and so does what “safe to expose” means for it. The private notes behind this site get updated regularly; a detail that was fine to abstract-and-publish six months ago might describe an architecture that no longer exists, which makes it more dangerous to reuse carelessly, not less: an out-of-date detail can mislead an attacker into wasted effort, sure, but it can just as easily describe a weakness that got fixed in a way the public post never mentions, leaving readers with a stale mental model of a system that’s different now.
What this means for a post like this one
I’m not going to describe the structure of the private documentation, its filenames, or what it says about any specific system: doing that here would be the exact failure this post is arguing against, using this post as the example. What I can say honestly, because it’s just a description of the practice and not a description of the material: every post in this collection that touches something operational passed through this filter before it became public. A post like the backup gap this platform hasn’t closed is exactly the kind of admission this discipline has to get right: a real, named risk, with none of the real infrastructure detail that would make it useful to anyone but the reader. Some ideas didn’t survive it in a form worth publishing at all, and that’s fine, a lesson that can’t be told without the identifying detail that makes it dangerous is a lesson that stays private. That’s not a failure of the writing process. It’s the process working as intended.
The uncomfortable part of this discipline is that it never produces a satisfying “done.” There’s no checklist you complete once and file away. Every new post is a new instance of the same question, asked fresh, about material that keeps changing underneath you. That’s not a flaw in the method — it’s what it means to treat your own notes as material that will eventually inform something public, consistently, rather than as a one-time source you mine and move past.
A practical pass, not a vibe check
Saying “ask whether it helps an attacker for zero reader benefit” is the right test, but applying it well needs more structure than holding the question loosely in mind while skimming a draft. In practice, a real pass over a candidate post involves a few concrete moves, done in order rather than all at once.
The first is a plain read for anything that looks like an identifier — anything that would let someone match this post to a specific real system if they went looking. That includes the obvious categories (IPs, hostnames, credentials) but also the less obvious ones: a distinctive error message copy-pasted verbatim from a real log, a timestamp precise enough to correlate against other public information, a screenshot with a window title or file path visible in the corner. Screenshots are a particularly easy way to leak something the surrounding prose never mentions, because the identifying detail rides along in the image rather than in anything that gets proofread as text.
The second move is asking, for each remaining specific detail, whether the sentence still teaches its lesson if that detail gets replaced with a generic placeholder. If “the service ran on a specific piece of hardware in a specific rack” becomes “the service ran on dedicated hardware” and the paragraph’s real point (resource contention, a capacity decision, whatever it was) survives that substitution intact, the specific hardware detail was never doing real work in the writing. It was just left over from the source material because that’s how the original note happened to describe it, not because the public version needed it.
The third move, and the one that’s easiest to skip under time pressure, is reading the finished draft once more as if it were the only public information the reader has — not as the author who already knows the private context. That shift in perspective catches things the first two passes miss, because it’s the only point in the process where you’re checking combination effects: does this post, read alongside the previous nineteen, start to sketch an outline of the private infrastructure that no single post gives away on its own? That question only has a chance of getting a real answer if it’s asked from the reader’s vantage point, not the author’s.
Abstraction that keeps the lesson honest
There’s a failure mode on the other side of this discipline worth naming, because it’s just as real as under-redaction: abstracting so aggressively that the post stops being true in any useful sense. “A system had a problem and we fixed it” is safe and worthless. The goal isn’t maximum vagueness, it’s finding the specific level of description that carries the real engineering content (what broke, why, what the fix changed, what trade-off got made) while dropping only the coordinates that would let someone locate the real system behind it. That’s a narrower target than “be vague,” and hitting it consistently is most of what this discipline is in practice, post after post.