The Period Is the Whole Design: Reading the Small Lowercase ‘meh.’ Shirt

The garment preview shows a dark shirt with a single word centered on the chest: meh. Lowercase, with a period. The lettering is very small — small enough that from a few feet away it reads as a texture rather than a message. There is no animal illustration, no pride variant, no secondary graphic. Just four characters and a full stop, set in the middle of an otherwise empty field of dark fabric.

That scale is the argument. A shirt that says MEH in foot-high block letters is a costume; it announces a mood to the room before you have said anything. A shirt that says meh. in ten-point type is closer to a private note that happens to be legible. The period does the rest of the work. Without it, meh is a sound. With it, meh. is a complete sentence — a verdict, delivered flatly, with no exclamation mark to soften it and no question mark to invite discussion.

What the period actually does

I keep coming back to the punctuation because it is the only piece of design on the shirt that carries any ambiguity. The word itself is settled: meh has meant mild indifference for long enough that nobody needs the definition. The period is where the interpretation lives. In a text message, a period after a short reply is often read as coldness — the difference between ok and ok. is the difference between a shrug and a closed door. On a shirt, the same mark reads differently: it is not a reply to anyone, so it functions as a kind of self-contained closure. The sentence is finished. There is nothing to add.

That is a useful thing to have on a garment if your job involves a lot of people asking you to be enthusiastic about things. I do not mean that as a complaint about colleagues; I mean it as an observation about the register of technical work. A great deal of operational communication is deliberately flat — a status page that says degraded, a commit message that says revert, a monitoring alert that says disk full. The culture rewards terseness because terseness is auditable. meh. belongs to that family. It is a one-word status update with a terminator.

Small type as a boundary, not a billboard

The other thing the scale does is make the shirt non-confrontational. A large slogan shirt asks the room to react; a small one asks the room to lean in. That is a meaningful difference for readers who spend their days in text channels and their evenings recovering from them. The design does not perform introversion as a personality trait — there is no cartoon animal, no sorry I’m late I didn’t want to come copy, no wink. It simply declines to fill the space. The empty dark fabric around the word is doing as much work as the word itself.

I would not read the shirt as a statement about mental health, productivity, or the ethics of disengagement. It is a piece of typography with a mood attached. But it is a well-made piece of typography in the sense that every choice is load-bearing: lowercase rather than caps, period rather than ellipsis, small rather than large, centered rather than offset. Change any one of those and you get a different joke. An ellipsis would make it wistful. Caps would make it loud. A larger point size would make it a bumper sticker.

Where it fits, and where it doesn’t

The obvious use case is off-duty wear — the shirt you put on for a grocery run or a low-stakes Friday. It is also the kind of thing that works as a gift for the colleague who has perfected the art of the one-word reply in chat. What it is not is a uniform for a customer-facing role, and I would not wear it to a meeting where the point is to convey momentum. The design is honest about its own energy level, which is precisely why it reads as funny rather than passive-aggressive.

If you want the exact object, it is listed as the Meh Funny Sarcastic Introvert Minimalist Saying shirt from Quirky Cotton Collective. The listing title is longer than the design, which is its own small joke. The preview shows the small centered lowercase lettering on a dark garment; that is the thing to check before ordering, because the title’s adjectives describe a mood, not a graphic.

The difference between a slogan and a usable message

Most novelty shirts fail because they try to say too much. They stack a setup and a punchline, or they pair a phrase with an illustration that explains the phrase. This one trusts a single word and a punctuation mark to carry the whole idea, and it works because the idea is small enough to fit. That is a harder design problem than it looks. Restraint is easy to describe and difficult to execute, and the proof is in how many meh shirts exist with a cartoon sloth attached. This one has none.

The period is the tell. It says the sentence is over, and it says it without raising its voice. For a certain kind of reader — the one who has sent ack. in a channel and meant it kindly — that is the whole appeal.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The Element Tiles Don’t Spell It: Reading the ‘I Wear This Shirt Periodically’ Shirt

The shirt reads I WEAR THIS SHIRT PERIODICALLY in plain caps, and beneath that sentence sit four periodic-table-style tiles: 53 I, 74 W, 22 Ti, 16 S. The tile symbols are I, W, Ti, S. They do not spell the sentence. They spell a fragment that the sentence has already told you how to read.

That gap is the design. The joke is not that the tiles encode the phrase. The joke is that they almost do, and the almost is the point. You read the tiles left to right, hit the mismatch, and then the word periodically in the line above retroactively explains the whole arrangement. The shirt is a small exercise in reading order: sentence first, then diagram, then the diagram’s failure to be a diagram of the sentence.

I keep coming back to this because it is a useful object for people who spend their days around notation. A periodic table tile is a compressed label: atomic number, symbol, and the implicit promise that the symbol stands for the element. Here the tiles are borrowed for their visual grammar, not their chemistry. I is iodine at 53. W is tungsten at 74. Ti is titanium at 22. S is sulfur at 16. Those are the real element associations for those numbers and symbols, and the design uses them as letterforms. The shirt is not making a claim about iodine, tungsten, titanium, or sulfur. It is making a claim about how a reader’s eye wants to assemble a message from labeled boxes.

That is the argument I want to make about this shirt: it is a joke about compression and its limits. The sentence is the uncompressed version. The tiles are the compressed version. The compressed version does not decompress cleanly, and the word periodically is the checksum that tells you the mismatch is intentional. If you have ever written a terse status message, a one-line commit subject, or a monitoring alert that was technically accurate and still required a paragraph of context to be useful, the shirt is describing your working life in four boxes.

The phrase I wear this shirt periodically is also doing boundary work. It is a sentence about frequency, not identity. It does not say I am a chemistry person or I am a periodic-table person. It says the wearing happens periodically, which is a modest and slightly evasive claim. The tiles then make the word periodically literal in a way the sentence did not ask for. The result is a shirt that is funny in the same register as a dry changelog: the information is there, the format is familiar, and the meaning depends on which layer you read first.

I would not wear this to a job interview, and I would not wear it as a substitute for explaining what I actually do. But as an off-duty object for technical readers, it earns its place. It is a diagram joke that does not pretend to be a diagram. It is a slogan that does not pretend to be a promise. The difference matters. A slogan says trust me. A usable promise says here is the condition under which I will be true. This shirt is closer to the second: it tells you exactly how often it is making its claim, and then it gives you four tiles that refuse to spell it out.

The shirt is listed as I Wear This Shirt Periodically Funny Chemistry Science Pun from Quirky Cotton Collective. The visual observation is the sentence plus the four tiles: 53 I, 74 W, 22 Ti, 16 S. The tile symbols are I W Ti S, not a literal spelling of the sentence. That is the whole design, and it is enough.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The Crossed-Out Hand Is the Whole Contract: Reading the ‘Not Friendly Do Not Touch’ Warning Sign

The shirt reads NOT FRIENDLY DO NOT TOUCH in warning-sign lettering, with a yellow caution triangle and a crossed-out hand symbol. The triangle is the familiar hazard shape — the one that usually means wet floor, high voltage, forklift traffic. The hand inside it is a flat pictogram, palm out, with a diagonal bar through it. The words are set in the blunt, condensed register of industrial signage: no please, no thank you, no softening punctuation. It is a boundary written in the grammar of public safety infrastructure.

That grammar is the interesting part. A warning sign is not a request. It is a unilateral declaration of a condition, posted in advance, meant to be read by strangers who have no other context for you. The shirt borrows that authority and applies it to a person. The joke — and the useful argument — is that the sign is doing exactly what a good sign does: it removes ambiguity before contact, rather than negotiating after it.

What the artwork actually claims

Look closely at the three elements and what each one asserts.

The caution triangle is a shape with a specific job. In signage systems, the triangle is the warning class: it says hazard exists, proceed with attention. It does not say prohibited — that is the red circle with a slash. The shirt uses the triangle, not the prohibition roundel, which is a subtle but real distinction. The design is not claiming access is forbidden by rule. It is claiming that contact carries a risk the wearer is flagging in advance. That is a more honest claim than a hard no, and it is also funnier, because it treats a social interaction as a hazard class.

The crossed-out hand is the prohibition layer, and it is doing the specific work of naming the prohibited action. Not no talking, not no eye contact, not no standing near me. The hand. The design has picked one concrete, physical gesture and barred it. That specificity is what keeps the shirt from being a vague misanthrope slogan. It is a boundary with an object.

The lettering is the third element, and it is the one that carries the tone. NOT FRIENDLY is a self-description, stated as fact, in the same typeface as DO NOT TOUCH. The two clauses are parallel and equal. The shirt is not saying I am shy or I am tired or I am having a day. It is saying: here is the condition, here is the rule, both are posted, both are legible, neither is up for discussion. That is a terse message in the tradition of terse messages — the kind technical people tend to appreciate, because it front-loads the constraint instead of burying it in a paragraph.

The difference between a slogan and a usable promise

Most novelty shirts are slogans. They assert an identity — introvert, sysadmin, coffee — and leave the reader to do the interpretive work. A slogan is a mood. It does not commit to anything.

This design is closer to a promise, and the reason is structural. A usable promise has three properties: it is stated in advance, it is specific about what is being promised, and it is legible to the person it applies to. The shirt has all three. The warning is posted before contact. The prohibited action is named — the hand. The sign is written in a visual language any adult in a public space can read without training. That is not nothing. It is, in fact, the same set of properties you want in a maintenance window notice, a rate limit header, or a Retry-After response: state the condition, name the constraint, make it readable to the party it affects.

I am not claiming the shirt is a software artifact, or that wearing it improves anything, or that it demonstrates an engineering result. It is a piece of printed cotton. But the design logic is legible to people who spend their working lives writing constraints that other people have to obey without reading the documentation. The crossed-out hand is a 404 with a body. The triangle is the status class. The lettering is the error message, and it is refreshingly free of sorry for the inconvenience.

Why the bluntness is the point

There is a version of this shirt that would be softer. It would say Please Ask Before Hugging, or I’m Socially Selective, or Quiet Please. Those are all fine shirts. They are also all requests, and requests invite negotiation. The person who reads Please Ask may ask. The person who reads DO NOT TOUCH has been told the answer in advance.

The bluntness is not rudeness for its own sake. It is the removal of a step. In work culture terms, it is the difference between a team that says we value focus time and a team that posts no meetings before 11:00 on the shared calendar. The first is a value. The second is a constraint. Constraints are easier to honor because they do not require the other person to infer your preferences from a stated principle. The shirt is a calendar block you can wear.

That is also where the introvert framing in the listing title sits, and it is worth being precise about it. The design does not say introvert. It says not friendly, which is a different and more defensible claim. Introvert is a disposition; it describes how someone recharges. Not friendly is a boundary; it describes what someone is offering right now. The shirt picks the boundary, and the boundary is the thing a stranger can actually act on. You cannot honor someone’s disposition from across a room. You can honor a posted sign.

Reading it as a work-culture object

The shirt is available from Quirky Cotton Collective as the Not Friendly Do Not Touch warning-sign tee, and the design is what it is: lettering, triangle, crossed-out hand. What makes it worth a column rather than a passing glance is that it belongs to a small family of objects technical readers tend to like — the diagram joke, the terse status message, the boundary stated in the visual language of infrastructure rather than the visual language of feeling.

Those objects share a bias. They prefer the constraint to the explanation. They assume the reader is competent and will act on a clearly posted condition. They do not soften the message to protect the sender’s likability. That bias is not always right — in a lot of human contexts, the soft version works better, and the blunt version reads as hostile. But in the specific context of a stranger approaching a stranger in public, the blunt version has a real advantage: it is unambiguous, it is pre-emptive, and it does not require the wearer to perform friendliness in order to be left alone.

The crossed-out hand is the whole contract. Everything else — the triangle, the lettering, the yellow — is formatting. The hand is the clause that says what is not permitted, and the design is smart enough to put the clause in the center of the hazard shape, where the eye goes first. That is good signage practice, applied to a t-shirt. Whether it works in practice is not something a printed garment can guarantee, and the shirt does not claim otherwise. It just posts the notice.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The Period After ‘meh’ Is the Whole Design: Reading the Large Lowercase Shirt

The native garment preview shows four characters and a period: meh. — lowercase, bold, white, set large on a dark shirt. No illustration, no secondary line of copy, no animal mascot. The word is the entire graphic, and the period is the entire argument.

I want to be precise about what that period does, because it is the only thing on the shirt that isn’t the word itself. A bare meh is a sound. It’s the noise you make when someone asks how the deploy went and the answer is technically “fine.” It’s ambient. It doesn’t commit to anything. Add the period and the sound becomes a sentence — a short, declarative, grammatically complete one. Meh. Subject implied, verb implied, verdict delivered. The punctuation is what turns a shrug into a ruling.

That’s the design’s whole trick, and it’s worth sitting with because it’s the opposite of how most slogan shirts work. The typical joke tee escalates: bigger type, more words, an exclamation point, a cartoon to make sure you got it. This one de-escalates. It takes the most noncommittal word in English and gives it the formal closure of a full stop. The visual loudness — large bold lowercase lettering on a dark field — is doing something deliberately at odds with the word’s meaning. The shirt shouts a whisper.

Lowercase is doing work too

The lettering is lowercase, and that matters as much as the period. MEH. in caps would read as anger or a brand. meh. in lowercase reads as fatigue — the specific, recognizable fatigue of someone who has opinions but has decided, today, not to spend them. Lowercase is the typographic equivalent of not getting up. Combined with the bold weight, you get a strange but coherent signal: emphatic indifference. The shirt is not unsure. It is very sure that it does not care.

I read the dark background as part of the same move. White type on a dark shirt is high contrast, which is why it reads at a distance — but the dark field also mutes the whole thing. It’s not a cheerful shirt. It’s a shirt that has been asked to attend a meeting.

Why this lands with people who run infrastructure

I spend a lot of my working life writing messages that have to be short and unambiguous: alert titles, commit messages, the one-line summary in a ticket, the status update in a channel at 2 a.m. The hard part is never the long explanation. The hard part is compressing a real judgment into something terse without it becoming either vague or rude. meh. is a masterclass in that compression, even though it’s a joke. It is a complete verdict in five characters, and it is unmistakably a verdict because of the period.

There’s a useful distinction hiding in here between a slogan and a usable promise. A slogan is designed to be repeated; a promise is designed to be relied on. Most novelty shirts are slogans. This one is closer to a boundary marker — a small, legible statement of where the wearer’s energy currently sits. It doesn’t promise anything. That’s the point. It’s the rare garment that under-promises and then delivers exactly that.

I’m not going to pretend the shirt demonstrates anything about engineering, security, or uptime. It’s a shirt. But the design instinct — say the short thing, punctuate it so it can’t be misread, and don’t decorate it — is an instinct technical readers tend to recognize, because we spend all day trying to get terse messages to mean exactly one thing.

What the design is not

Worth stating plainly, since the retail title stacks up a few adjectives: the preview shows no animal illustration and no secondary graphic. The shirt is the word and the period on a dark field. The title’s framing — sarcastic, introvert, dry humor — is retail prose, not printed copy. What’s actually printed is meh., and the design trusts that to carry the joke without help. It does.

If you want the object itself, it’s the Meh Funny Sarcastic Saying Introvert Dry Humor shirt from Quirky Cotton Collective. The design is the argument: a dismissive word given the full stop it never asked for, printed loud enough that the dismissal reads as intentional rather than accidental.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The Notification Is the Joke: Reading the Doorbell-Camera Cat Shirt

The shirt shows a white rounded notification banner with a small bell icon. Inside the banner, in plain sans-serif, the words read: There is motion at your front door. Below the banner sits a circular, green-tinted image — the unmistakable framing of a doorbell camera — and inside that circle is a wide-eyed orange tabby, nose nearly touching the lens, porch siding and a light fixture visible behind it.

That is the whole design. No punchline caption underneath, no second panel, no speech bubble. The joke lives entirely in the collision between the flat, procedural language of the alert and the specific, absurd thing that triggered it.

I keep coming back to the wording. There is motion at your front door. Not “a cat is at your door.” Not “your cat has escaped.” Motion. The notification is written for a system that cannot know what it is looking at, only that pixels changed in a region it was told to watch. It reports the lowest-level fact it can verify and leaves the interpretation to you. That is, if you have ever written a monitoring check, an alert rule, or a log line, a deeply familiar sentence.

What the alert can and cannot say

A doorbell camera is a motion detector with a camera bolted on. The motion detection is the cheap part: frame differencing, a threshold, a region of interest. The camera is what lets a human resolve the ambiguity after the fact. The notification text in the artwork is the output of the cheap part. It is technically true and practically useless on its own, which is exactly why the image below it is doing the comedic work.

This is the same gap that shows up in every alerting system I have maintained. A check fires because a threshold crossed. The check does not know whether the threshold crossed for a boring reason or an interesting one. So the alert says motion, and the on-call human opens the dashboard and discovers it was a cat. Or a cron job. Or a backup that ran at the wrong hour. The alert was correct. The alert was also not the thing you needed.

The shirt is funny because it stages that gap in the most domestic possible setting. The system did its job. The system reported motion. The motion turned out to be a cat pressing its face against the glass. Nobody is harmed; the alert was simply outclassed by the situation.

The framing is the argument

Look at how the design is composed. The notification banner is rectangular, white, rounded, and sits above. The camera view is circular and green-tinted, sitting below. The two shapes are different on purpose. The banner is the system’s voice — clean, declarative, formatted. The circle is the system’s eye — distorted, tinted, slightly fish-eyed, the way a cheap wide-angle lens renders a porch. The design is not just showing you a cat; it is showing you the difference between what the system says and what the system sees.

The green tint matters too. It reads as night vision or low-light mode, the palette a camera falls into when the porch light is not enough. That tint is a visual shorthand for “this is a machine’s rendering of the scene, not a photograph.” The cat is real, but the image of the cat has been through a pipeline. The shirt is honest about that pipeline in a way that most notification-themed designs are not.

The cat itself is doing something specific: it is very close to the lens, eyes wide, filling most of the circle. That proximity is what makes the image read as a surprise rather than a portrait. The camera was not placed to photograph the cat. The cat arrived at the camera. The alert fired because the cat got close enough to register as motion, and the resulting frame is the least flattering, most immediate possible view of a cat that a porch camera can produce.

Why the wording travels

The phrase there is motion at your front door is not a slogan anyone wrote for a shirt. It is the kind of sentence that appears in a push notification because it was the shortest accurate string a product team could ship. That is what makes it reusable as a joke: it is already slightly stiff, already slightly over-formal for the situation, and already detached from the thing it describes. Putting it on a shirt next to the cat does not add a punchline. It just puts the two halves of the same event side by side and lets you notice the mismatch.

I have a soft spot for designs that trust the reader to complete the joke. This one does. There is no caption explaining that the cat is the motion. There is no arrow. The banner says motion; the circle shows cat; the reader supplies the connection. That is a more durable kind of humor than a caption, because it survives being seen at a distance, in a mirror, or on a stranger in a checkout line. The words are legible from across a room; the cat resolves as you get closer; the joke lands in the second before you look away.

If you want the object itself, the listing is here: There Is Motion At Your Front Door Funny Cat Doorbell Meme. It is a standard t-shirt with the design described above, sold under the Quirky Cotton Collective brand.

The difference between a slogan and a usable promise

Most shirts with text on them are making a claim about the wearer: I am this kind of person, I do this job, I have this opinion. This one is making a claim about a system. The sentence on the banner is a report, not an identity. The wearer is not saying I am motion or I am a cat. The wearer is wearing a small diagram of a specific kind of event: a low-information alert followed by a high-information image.

That is a more interesting thing to put on a shirt than a slogan, because it is a structure rather than a stance. You can read it as a joke about doorbell cameras, or as a joke about alerting, or as a joke about the gap between what a system reports and what is actually happening. The design does not insist on any of those readings. It just presents the two halves and lets the mismatch do the work.

The shirt does not claim the cat is a security threat, and it does not claim the camera is smart. It claims only what the banner claims: there was motion. The cat is the evidence. The joke is that the evidence is more informative than the alert, and funnier, and also the reason the alert fired in the first place.

What the design gets right

The restraint is the strongest part. A lesser version of this shirt would add a caption like “cat detected” or “false alarm” or a second notification banner. That would explain the joke and kill it. This design leaves the banner exactly as a real notification would read and lets the image contradict its vagueness. The contradiction is the whole point, and it only works if neither half is over-explained.

The color choices support that restraint. White banner, black text, green-tinted circle, orange cat. Four colors, no gradients, no drop shadows, no decorative flourishes. The design reads at a glance and rewards a second look, which is roughly the specification for a good shirt graphic. It also means the joke does not depend on the shirt being a particular color or fit; the composition carries it.

I would not call this a design about surveillance, and I would not call it a design about pets. It is a design about the moment a system tells you something true and unhelpful, and the moment right after, when you find out what it meant. That moment happens on porches and in dashboards and in log files, and it is funnier on a shirt than it has any right to be.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The Ball Is Already at the Bottom: Reading the ‘I Had Potential’ Ramp Diagram

The shirt shows four words in white capitals: I HAD POTENTIAL. Beneath them, a white curved ramp descends from an upper-left ledge to a lower-right flat ledge. At the top of the ramp, on the upper-left ledge, sits a dashed empty circle. At the bottom, on the lower-right flat ledge, rests a solid white ball. The ramp is curved, not a straight diagonal. That is the entire design.

Most readings of this shirt stop at the phrase. The joke is taken to be the gap between what the wearer once was and what the wearer now is — a self-deprecating caption with no further structure. But the drawing is doing something more specific than that, and the specificity is what makes the object worth looking at closely. The dashed circle and the solid ball are not decoration. They are a before-and-after in a single frame, and the ramp between them is the part that carries the argument.

In physics, potential energy is stored energy — the energy an object has by virtue of its position in a field. A ball at the top of a ramp has gravitational potential energy relative to the bottom. Release it, and that potential converts into kinetic energy as it rolls down. The phrase I had potential borrows the vocabulary of that conversion and applies it to a person. The joke is that the conversion has already happened, and the result is a ball sitting still on a flat ledge.

What the drawing adds is the direction of travel. The dashed circle is at the upper left, empty — a position once occupied, now vacated. The solid ball is at the lower right, resting. The ramp curves between them. Read left to right, the diagram is a trajectory: something started high, descended, and stopped. The dashed outline is the ghost of the starting position. The solid ball is the current state. The curve is the path, and the flat ledge at the bottom is where motion ends.

That is a more precise joke than the phrase alone. I had potential is a sentence about the past. The diagram is a diagram about conversion — potential becoming motion becoming rest. The shirt is not just saying the potential is gone; it is showing the mechanism by which it went. The ball did not evaporate. It rolled down a curved ramp and came to rest on a flat surface. The potential was real. The conversion was real. The result is a ball that is no longer moving.

There is a second reading available, and it depends on the same visual facts. The dashed circle is empty. The solid ball is present. If you read the diagram right to left — from the resting ball back up the ramp to the empty circle — you get the reverse: a ball at rest, a path upward, and a position that is now vacant. That reading is less natural, because ramps descend and balls roll down, but it is not impossible. The dashed circle could be a destination rather than an origin. The shirt does not resolve this. The ambiguity is part of what makes the drawing work as a drawing rather than as a caption.

The phrase itself is common enough that the shirt is not relying on novelty of wording. What distinguishes this object is the pairing: a terse self-description above a small physics diagram that literalizes the metaphor. The diagram is minimal — two ledges, one curve, two circles — and it is rendered in the same white as the text. There is no color coding, no labels, no axes. The viewer supplies the physics. That is the right amount of information for a shirt: enough to reward a second look, not so much that it becomes a lecture.

For technical readers, the appeal is probably not the physics itself, which is elementary, but the structure of the joke. It is a diagram that admits a failure mode. The ball is at the bottom. The potential is spent. The system has reached equilibrium, and equilibrium is another word for nothing further happening. That is a familiar shape of story in operations work: a system that once had headroom, a conversion that happened, and a steady state that is technically stable and practically inert. The shirt does not say any of that. It just shows a ball on a ledge and lets the viewer complete the analogy.

The design is available as a standard t-shirt from Quirky Cotton Collective: I Had Potential Funny Physics Pun Sarcastic Minimalist Quote. The retail title calls it a physics pun and a sarcastic minimalist quote, which is accurate as far as it goes, but the drawing is the part that earns the description. A shirt with only the words would be a slogan. The ramp and the two circles make it a small argument about what happens to potential after it converts.

Disclosure: This publication and Quirky Cotton Collective share an owner.

The Roots Are the Argument: Reading the ‘Let’s Root for Each Other’ Shirt

The shirt reads LET’S ROOT FOR EACH OTHER AND WATCH EACH OTHER GROW, set in a ring around four smiling root vegetables: a carrot, a radish, a beet, and an onion. Each one is drawn with its roots visible in soil. The roots are not decorative. They are the visual hinge on which the whole sentence turns.

That sentence contains two meanings of root, and the artwork knows it. To root for someone is to support them from the sidelines. To put down roots is to establish yourself in place. The design stacks both readings on top of each other and then adds a third: the vegetables are literally roots, pulled from the ground, smiling anyway. The pun is not just a pun. It is a small argument about what mutual support actually looks like when it is not a slogan.

Most workplace encouragement is directional. One person with more authority or more visibility cheers on another person with less. The cheer is real, but the relationship is asymmetric. The shirt’s phrasing is not. Each other appears twice, and both times it is reciprocal. The support runs in both directions, and so does the growth. The carrot is not mentoring the radish. The beet is not sponsoring the onion. They are all in the same soil, and the sentence treats that shared position as the precondition for everything else.

The second half of the line is where the design gets more interesting. Watch each other grow is a strange thing to promise. Watching is passive. Growth is slow. The phrase does not say make each other grow or help each other grow. It says watch. That is a lower-commitment verb, and I think it is the more honest one. You cannot actually make a colleague get better at their job. You can notice when they do. You can say so. You can leave room for the part of growth that happens underground, where nobody can see it yet.

The roots in the illustration make that point visually. They are drawn below the soil line, visible to the viewer but not to the other vegetables. Each root system is its own tangle. The carrot’s root is long and tapered. The beet’s is rounder, more fibrous. The onion’s is a spray of thin threads. They are not sharing a root system. They are sharing soil. That distinction matters. Mutual support does not mean merging into one organism. It means four separate organisms, each with its own underground work, occupying the same patch of ground and not crowding each other out.

I keep coming back to the onion. It is the only vegetable in the group that is a bulb rather than a taproot, and it is drawn with its papery skin and its green shoots still attached. It looks slightly out of place next to the carrot and the beet, which are classic root crops. The radish is somewhere in between. The design does not smooth over that difference. It puts four different root architectures in a row and gives them all the same smile. The visual message is not we are all the same. It is we are all rooted, and we are all here.

There is a version of this shirt that would be worse. It would say something like Teamwork Makes the Dream Work and put a cartoon sun in the corner. That shirt would be making a demand. This one is making an observation. The difference is in the verb. Root for is something you do from where you are. Watch is something you do with your attention. Neither one requires you to perform enthusiasm you do not feel. Neither one asks you to pretend that growth is fast or linear or evenly distributed. The vegetables are smiling, but they are also just sitting there in the dirt, which is what roots do.

The phrase let’s root for each other shirt is the kind of search that probably comes from someone looking for a gift for a gardener, a coworker, or a friend who has been quietly doing the unglamorous work for a while. The design suits that use because it does not overpromise. It is a shirt about the conditions that make growth possible, not a shirt about growth itself. The soil is the shared thing. The roots are the private thing. The smile is the part you can see.

If you want the object itself, it is listed here: Let’s Root For Each Other And Watch Each Other Grow Garden from Quirky Cotton Collective. The design is what the listing shows: the full sentence wrapping four smiling root vegetables with their roots visible in soil. I am not going to tell you how it wears, because I have not worn it. I am going to tell you what the artwork argues, because that is the part I can actually read.

The argument is this: support is not a transaction, and growth is not a deliverable. The shirt puts both ideas in the same sentence and then draws them as vegetables in the ground. The roots are the part you cannot see from above. The smile is the part you can. The sentence asks you to pay attention to both.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The Period After ‘meh’ Is the Whole Design: Reading the Small Lowercase Shirt

The garment preview shows a dark shirt with a single word centered on the chest: meh. Lowercase, very small, followed by a period. No illustration, no animal, no slogan stacked above or below it. The scale is the first thing I notice, because it is not the scale of a joke that wants to be read across a room. It is the scale of a message that expects you to be standing close enough to care, and then tests whether you actually do.

Most text shirts fail by overexplaining. They give you a setup, a punchline, and a font choice that says please laugh. This one gives you four characters and a punctuation mark, and the punctuation mark is doing more work than the letters. A period is a full stop. It is the typographic equivalent of closing a ticket with no comment. The word alone could be a shrug; the period makes it a verdict.

I keep thinking about this in the context of the messages technical people actually send each other. The best incident updates I have read are not eloquent. They are short, lowercase, and final: fixed. rolled back. meh. The last one is not a status you want in a postmortem, but it is an honest status for a lot of things that do not deserve a paragraph. The shirt is not making a software argument. It is making a typographic one, and the typographic argument happens to map onto a habit of mind that a lot of operators share: say less, mean it, stop.

Small type is a boundary, not a whisper

There is a common assumption that small print is timid. In practice, small print is often the most confident choice on a page. A large slogan asks for attention before it has earned it. A small one waits. It says: I am not going to shout at you, and I am not going to explain myself twice. That is a boundary statement, and boundaries are a recurring theme in the work-culture conversations technical readers tend to have — the difference between a slogan and a usable promise, between a team value and a thing a team actually does.

The meh. here is not a promise. It is a refusal to make one. That is what makes it usable as an off-duty object rather than a work object. You would not put it on a status page. You might put it on a shirt, where the stakes are low and the audience is whoever is close enough to read it. The smallness enforces the intimacy. If someone comments on it, they were standing near you and looking at your chest long enough to parse four lowercase letters. That is already a filter.

The meh shirt is sold under the Quirky Cotton Collective brand, and the listing title stacks up the usual retail adjectives — funny, sarcastic, introvert, minimalist. I would not treat those words as printed on the garment. The preview shows one word and a period. The rest is catalog prose, and catalog prose is not evidence of what the shirt says. What the shirt says is meh. What the listing says is a set of search-friendly descriptors. The gap between those two things is worth noticing, because it is the same gap between a service’s marketing page and its actual behavior under load.

The period is the part I would keep

Strip the period and you have a different object. meh without punctuation is a sound, an exhale, a verbal shrug that trails off. meh. with the period is a closed statement. It has a beginning and an end and no invitation to continue. In a work culture that runs on open loops — the follow-up, the check-in, the circling back — a closed loop printed at four-point scale is a small act of defiance. It is not rude. It is just done.

I do not think the design is making a claim about introversion, despite the listing title. Introversion is a psychological category, and a shirt is not a personality test. What the design actually does is borrow the visual grammar of understatement and apply it to a word that already means understatement. That is a tautology, but it is a well-executed one. The lowercase letters sit at the same weight as the period, so the whole thing reads as a single unit rather than a word with a dot after it. The centering is plain. There is no drop shadow, no distressed texture, no faux-vintage treatment. It is as bare as a design can be while still being a design.

That bareness is the argument. A shirt like this works only if you accept that the joke is the restraint. If you want the joke explained, you will be disappointed. If you want a shirt that says I have opinions but I am not going to spend the afternoon defending them, the restraint is the point. The period is the part I would keep if I were editing it. Without the period, it is a mood. With the period, it is a position.

What it is not

It is not an animal shirt. The preview shows no illustration, and the listing does not describe one. It is not a pride variant. It is not a diagram joke, a regex joke, or a reference to a specific protocol. Readers who come to this column for the diagram shirts will find less to unpack here, and that is fine. Not every object needs a hidden layer. The hidden layer, if there is one, is the punctuation, and I have already spent more words on it than the shirt spends on itself.

It is also not a cure for anything, a productivity system, or a statement about mental health. It is a word on a shirt. The useful question is not what it does for you but what it declines to do: it declines to elaborate, decline to perform enthusiasm, and decline to turn a mood into a manifesto. For a certain kind of technical reader — the one who has learned that the shortest accurate message is usually the one that survives the incident review — that refusal is legible. It is not a slogan. It is a full stop.

Editorial note: This publication and Quirky Cotton Collective share an owner.

Scheduling restic check and Borg check without locking out production backups

Integrity checks fail in two ways. The obvious one is that they find corruption. The less obvious one is that they never run, or run so rarely that a repository can rot for a year before anyone notices. For a small fleet — one to ten machines, one operator, a VPS or two and a homelab box — the second failure mode is the common one, and it is almost always a scheduling problem dressed up as a discipline problem.

The instinct is to bolt restic check or borg check onto the end of the nightly backup script. That instinct is wrong, but not for the reason usually given. The contention that matters is not between a read-only check and a backup. It is between the maintenance jobs that take exclusive locks — prune, forget, compact — and the backup that is trying to write while they hold the repository. A check scheduled carelessly next to a prune is how you get a backup that fails at 02:15 and a check that reports clean at 02:20, and nobody looks at either until a restore is needed.

The lock is the schedule

Restic’s own documentation is blunt about this. In the section on removing snapshots: “During a prune operation, the repository is locked and backups cannot be completed. Please plan your pruning so that there’s time to complete it and it doesn’t interfere with regular backup runs.” The same page adds: “It is advisable to run restic check after pruning, to make sure you are alerted, should the internal data structures of the repository be damaged.”

That is the whole design constraint in two sentences. Prune is the disruptive job. Check is the job that should follow it, because prune is the operation most likely to expose a structural problem. If you schedule them as one maintenance window, you get the check for free at the moment it is most informative. If you schedule them as two independent cron entries an hour apart, you have created a race between a job that holds an exclusive lock and a job that needs to read the repository, and you have done so for no benefit.

Borg’s situation is different in detail and similar in shape. borg check is read-only by default: “The check command is a read-only task by default. If any corruption is found, Borg will report the issue and proceed with checking. To actually repair the issues found, pass --repair.” The retrieved Borg documentation does not state whether check takes a repository lock or blocks a concurrent create, so do not assume either way. What it does state is that check “always needs the key, --repository-only included: it loads the key (asking for the passphrase, if needed) before it checks anything and aborts if the key can not be loaded.” That matters for scheduling: a check that cannot read the key fails before it touches the repository, and a cron job that swallows that failure looks identical to a clean run.

Restic: separate the jobs, then spread the reads

The practical restic pattern for a small fleet is three jobs, not one:

  1. Backup, nightly, on the production host, with a credential that can write but not delete.
  2. Forget and prune, weekly, on a maintenance host that holds the delete-capable credential.
  3. Check, immediately after prune, on the same maintenance host, in the same window.

Keeping the delete-capable credential off the production host is the append-only pattern, and it is worth the extra host because it changes what a compromised production server can do to your history. It also means the maintenance host is the natural place to run the check: it already has the password, it already has the repository access, and it is not competing with a backup for I/O on the machine that is actually serving users.

The check itself does not have to read every pack every week. Restic’s check accepts --read-data-subset, which resticprofile’s reference documents as: “read a subset of data packs, specified as ‘n/t’ for specific part, or either ‘x%’ or ‘x.y%’ or a size in bytes with suffixes k/K, m/M, g/G, t/T for a random subset.” The n/t form is the one to use for a schedule, because it is deterministic: day 1 of 31, day 2 of 31, and so on. Over a 31-day month every pack is read once. Over a 30-day month, one group is skipped until the next long month — a real gap, but a bounded one, and far better than a full read-data check that never fits in the window and therefore never runs.

A percentage subset is simpler to write and worse to reason about. Restic’s own documentation notes that random subsets do not guarantee full coverage. If you use a percentage, you are choosing probabilistic coverage and you should say so in the runbook rather than pretending the schedule is exhaustive.

One more restic detail worth knowing before you panic at the output: restic check routinely reports pack files that are not referenced in any index. The FAQ is explicit that this is “not a source for concern” and is “with high probability this is duplicate data caused by an interrupted backup run or upload operation,” cleanable with restic prune. A check that exits clean but prints those lines is a pass, not an incident. Teach your alerting the difference, or you will page yourself at 3 a.m. for an interrupted upload from three weeks ago.

Borg: time-box the repository check, keep verify-data rare

Borg’s check splits into two phases that behave very differently under a schedule. The repository phase checks segment headers and the metadata and data of all objects, with size and CRC checks that catch bit rot. The archive phase checks archive metadata and, optionally with --verify-data, the actual file content.

The repository phase can be time-boxed. From the Borg 1.4 documentation: “The --max-duration option can be used to split a long-running repository check into multiple partial checks. After the given number of seconds the check is interrupted. The next partial check will continue where the previous one stopped, until the full repository has been checked.” The same page gives the arithmetic: a complete check that would take seven hours, run daily with --max-duration=3600, produces one full repository check per week.

There is a catch, and it is the one that bites people who skim. Partial repository checks cannot run archive checks. The 1.4 documentation states that with --max-duration “you must also pass --repository-only, and must not pass --archives-only, nor --repair.” The 2.x documentation repeats the constraint and adds the reason: partial checks “run neither archive checks nor repair mode.” So a time-boxed daily check verifies the repository’s bytes but says nothing about whether the archives’ metadata and chunk references are consistent. You need a separate, less frequent archive check to cover that half.

Borg 2.x adds --max-age, which lets a check reuse recent pack results: “packs whose intact result is younger than the given timespan (e.g. --max-age=4w or --max-age=12m) are skipped, spreading the verification cost over repeated checks.” This is not available in 1.x, so check which major version you are running before copying a schedule from a 2.x page. The 2.x documentation also notes that --max-age “affects only the repository check and cannot be combined with --archives-only or --repair.”

Then there is --verify-data. The 1.4 documentation calls it “a complete cryptographic verification and hence very time consuming, but will detect any accidental and malicious corruption.” The 2.x documentation is more emphatic: it “always verifies that each chunk’s content matches its chunk id, which normal reads do not do by default” and “running it periodically is therefore recommended.” Periodic does not mean nightly. For a small fleet, a monthly or quarterly --verify-data run, scheduled in a window long enough to finish, is the honest cadence. Putting it on a daily timer and hoping it completes is how you get a check that is killed halfway every night and never reports anything useful.

A schedule that fits one to ten machines

The following is a recommendation, not a finding. It assumes a nightly backup window, a maintenance host with delete rights, and a repository small enough that a full read-data pass is measured in hours rather than days. Adjust the cadences to your window; do not adjust the separation.

  • Nightly, production host: backup only. No check, no prune, no forget. The production host should not be able to delete its own history, and it should not be doing maintenance work while it is also serving.
  • Weekly, maintenance host: forget --prune, then restic check (structural, no --read-data) in the same window. This is the check the restic docs recommend after pruning.
  • Daily, maintenance host, staggered hours from the backup: restic check --read-data-subset=n/31, where n is the day of the month. Or, for Borg, borg check --repository-only --max-duration=3600 (1.x) or with --max-age=1w added (2.x).
  • Monthly, maintenance host: a full archive check. For Borg, borg check --archives-only without --max-duration. For restic, a full --read-data run if the repository is small enough, or accept the subset rotation as your coverage.
  • Quarterly, maintenance host: borg check --verify-data if you run Borg, in a window you have actually measured.

Stagger by hours, not minutes. If prune and check both need the repository and the prune takes longer than expected — and it will, the first time, because the first prune after a policy change repacks more than you think — a five-minute gap is a coin flip. A multi-hour gap is a schedule. Put the check after the prune in the same window, and put the daily partial check in a different window entirely, ideally at a time when no backup is running on any host that shares the repository.

Alert on “did not run” separately from “found errors”

This is the part that separates a schedule from a comfort ritual. A check that exits 0 because it found nothing and a check that exits 0 because it was skipped by a lock, or because the key was not readable, or because the wrapper swallowed a non-zero exit, look identical to a naive monitoring setup. They are not identical. One means the repository is intact. The other means you do not know.

Borg’s return codes are documented and worth wiring into your wrapper: 0 is success, 1 is a generic warning where “operation reached its normal end, but there were warnings — you should check the log,” 2 is a generic error, and with BORG_EXIT_CODES=modern the codes become more specific. A wrapper that treats anything other than 0 as a failure and anything other than 0 or 1 as a page is a reasonable starting point. Restic’s exit behavior is less granular, so the wrapper should also check that the check actually ran: a start timestamp, an end timestamp, and a duration that is not suspiciously short.

The failure mode to design against is the green check that never executed. If your monitoring only alerts on non-zero exits, a cron entry that silently stopped firing three months ago is invisible. Alert on the absence of a successful run, not just on the presence of a failed one.

What a clean check does not prove

A clean restic check or borg check proves the repository is internally consistent. It does not prove the repository contains what you need. A backup job that has been silently excluding the wrong directory for six months will produce a perfectly consistent repository with nothing useful in it, and every check will pass.

Pair the check schedule with a periodic restore test. Restore a file, restore a directory, restore a database dump, and time it. The check tells you the bytes are intact; the restore tells you the bytes are the right bytes. Neither substitutes for the other, and a schedule that only does the first is a schedule that will pass every test until the day it matters.

Before you trust the schedule

Three things to verify before you walk away from the cron file:

  1. Dry-run the policy. restic forget --dry-run and borg prune --dry-run print what would be removed without removing it. Run them once by hand, read the output, and confirm the retention rules match your intent. A policy that keeps nothing is a policy that will delete your history on the first real run.
  2. Confirm which host holds delete rights. If the production host can delete, the append-only split is not in place, and the check schedule is protecting a repository that a compromised server can still destroy.
  3. Restore something. Not a dry run, not a listing. An actual restore to a scratch directory, from the most recent snapshot, with the clock running. If it takes longer than your recovery objective allows, the check schedule is not the problem.

FAQ

Does restic check take an exclusive lock and block backups?

The retrieved restic documentation states that prune locks the repository and that backups cannot be completed during a prune. It does not state check‘s locking behavior. Do not assume either way; test it against your restic version, or simply schedule the check outside the backup window so the question does not matter.

Does borg check block a concurrent borg create?

The retrieved Borg check documentation does not state whether check takes a repository lock or blocks a concurrent create. It does state that check is read-only by default and that it always needs the key. Treat the lock question as open and schedule accordingly.

Can I use --max-duration with --archives-only?

No. Both the 1.4 and 2.x documentation state that --max-duration requires --repository-only and cannot be combined with --archives-only or --repair. A time-boxed check covers the repository phase only; archive checks need a separate, untimed run.

Is --max-age available in Borg 1.x?

It appears on the 2.x check documentation page and not on the 1.4 page. Check your version before using it in a schedule.

Why does restic check report packs not referenced in any index?

Restic’s FAQ describes this as uncritical, most likely duplicate data from an interrupted backup or upload, and cleanable with restic prune. It is not by itself a sign of corruption.

How often should I run --verify-data?

Borg’s 2.x documentation recommends running it periodically because normal reads do not verify chunk content against chunk IDs. The right cadence depends on your repository size and your window; for a small fleet, monthly or quarterly is a defensible starting point, provided the run actually completes. A daily --verify-data that gets killed halfway every night is worse than a quarterly run that finishes.

Monitoring Certificate Chains From the Inside: Three Probes, Three Failure Modes

A certificate check that returns a single boolean is not a monitor. It is a coin flip with extra steps. Expiry, trust-path validation, and revocation are three different questions, answered from three different data sources, and they fail in three different ways. Collapse them into one green light and the light will be wrong in at least one direction — usually the direction that gets you paged.

This is about probing your own endpoints from inside your network: the mail server, the reverse proxy, the internal API. It is not about watching Certificate Transparency logs for your domains. Those answer a different question — what has been issued in your name — and they fail differently. Keep them separate.

Why one check hides the interesting failures

RFC 5280 profiles the X.509 v3 certificate and the X.509 v2 CRL, and it describes an algorithm for certification path validation. That algorithm is the thing your TLS client actually runs. It checks signatures up the chain, validity periods at every depth, name constraints, key usage, and — if configured — revocation status. A monitor that only reads the leaf’s notAfter is checking one input to that algorithm and calling it a day.

The failure modes you care about are not the same failure:

  • Expiry is a property of each certificate in the chain, not just the leaf. An intermediate that expires before the leaf takes the whole endpoint down.
  • Trust-path failures are structural: a missing intermediate, a cross-signed alternate chain, a root that your trust store does not carry, a name mismatch. These are usually binary, but the reason is what you need.
  • Revocation is a network question with a third answer. The responder can say good, revoked, or unknown — and it can also fail to answer at all, which is not the same as good.

Each of these deserves its own probe, its own state model, and its own alert path.

Probe 1 — chain and trust

Verify the served chain against your own trust store, not the system default, and read the structured output rather than the exit status. The OpenSSL verify command verifies certificate chains and, per its manual, attempts to display all problems if a chain has multiple. That last property matters: a chain can have more than one defect, and fixing the first one you see may just reveal the second.

The output format is documented. The general shape is:

server.pem: /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit)
error 24 at 1 depth lookup: invalid CA certificate

The manual is explicit about depth: it starts at zero for the target (leaf) certificate, then 1 for the CA that signed it, and so on. That number is the difference between a five-minute fix and an hour of guessing. error 24 at 1 depth tells you the intermediate is the problem. error 10 at 0 depth tells you the leaf has expired. error 20 at 0 depth tells you the issuer cannot be found — usually a missing intermediate in what the server sends.

A probe that only checks $? throws that away. Parse the error number and the depth. Store both. Alert on the pair, not on the exit code.

Two practical notes on running this:

  • Fetch the chain the way a client would — openssl s_client -showcerts against the endpoint — and feed the leaf plus the served intermediates to verify with -untrusted, and your own roots with -CAfile or -CApath. If you verify against a different trust store than your clients use, you are testing a different system.
  • If you want the probe to also exercise revocation, verify accepts -CRLfile (a file or URI containing one or more CRLs) and -crl_download, which attempts to download CRL information via the certificates’ CDP entries. Both are useful, but see the revocation section below before you make them the primary signal.

Probe 2 — expiry, at every depth

The leaf is the certificate everyone watches. The intermediate is the one that surprises people, because it was issued years ago, renewed on someone else’s schedule, and is not in your renewal runbook.

The probe should extract notBefore and notAfter for every certificate in the served chain, compute the earliest expiry, and report which certificate at which depth owns it. A chain where the leaf has 200 days left and the intermediate has 12 is a chain with 12 days left.

This is also where cross-signed and alternate chains complicate things. A server may present one chain; a client may build a different path using a cross-signed root or an alternate intermediate it already has cached. Your probe sees what the server sends. That is the right thing to monitor for your endpoints, because it is what most clients will receive — but be aware that a successful verification on your probe does not prove every client will build the same path. If you care about a specific client population, probe with that population’s trust store.

Probe 3 — revocation, and the state everyone forgets

OCSP is specified in RFC 6960 as a protocol for determining the current status of a certificate without requiring CRLs. It defines three definitive status values: good, revoked, and unknown. Read the definitions before you write alert rules, because two of them do not mean what the words suggest.

good is narrower than it sounds. The RFC states that a good response does not necessarily mean the certificate was ever issued, or that the time the response was produced falls within the certificate’s validity interval. It means the responder has no current record of revocation for that serial. It is not a statement that the certificate is valid for your use.

unknown means the responder does not know the certificate, usually because the request names an issuer that responder does not serve. It is not a revocation. It is not a clean bill of health either. It means the status could not be determined by this responder, and the client is left to decide whether to try another source.

revoked is the only one that is unambiguously bad news, and even that has a wrinkle: RFC 6960 permits a responder to return revoked for a certificate that was never issued, provided it includes the extended revoked definition extension and sets the revocation reason to certificateHold with a revocation time of January 1, 1970. If you are parsing responses by hand, do not assume revoked implies a real issuance history.

Then there is the fourth outcome, which the protocol does not call a status at all: the responder did not answer. RFC 6960 defines error responses — malformedRequest, internalError, tryLater, sigRequired, unauthorized — and states plainly that these messages are not signed. tryLater specifically indicates the service exists but is temporarily unable to respond.

This is where most homegrown probes go wrong. The HTTP request times out, the script catches the exception, logs a warning, and returns success — because the certificate itself is fine, right? The certificate may well be fine. You do not know. That is the point.

The design rule: every probe needs a third state

Every probe should return one of three things: healthy, failed, or could not determine. The third state must never be collapsed into healthy. A probe that cannot reach the OCSP responder has not established that the certificate is unrevoked. A probe that cannot reach the endpoint has not established that the certificate is valid. A probe whose own execution failed has told you nothing about the target.

This is not a stylistic preference. It is the difference between a monitor and a random number generator. The failure mode of a silent probe is identical, from the alerting system’s perspective, to a healthy endpoint: no page. You will discover the difference during the incident, which is the worst possible time.

Concretely, the three-state model means:

  • A timeout or connection error from the OCSP responder is could not determine, not healthy.
  • An OCSP unknown response is could not determine unless you have a documented policy that says otherwise for that issuer.
  • A verify invocation that fails to run — missing binary, unreadable trust store, malformed chain file — is could not determine, not a pass.
  • A verify run that completes with errors is failed, with the error code and depth attached.

Write the policy down before you write the code. What do you do with unknown? What do you do with tryLater? What do you do when the responder is reachable but its response is stale — outside the thisUpdate/nextUpdate window? If you do not decide, the default behavior is whatever your tool happens to do, which is usually to treat the absence of a clear failure as success.

A worked example of the failure this prevents

Consider a probe that does the following: fetch the chain, run verify against the local trust store, then query the OCSP responder named in the leaf’s AIA extension. If the OCSP query throws, catch it and continue. Return success if verify passed.

Now suppose the responder is down for maintenance, or the network path from your probe host to the responder is blocked by a firewall change nobody documented. The probe returns green. The certificate may in fact be revoked — you would not know, because you never got an answer. The monitor has reported health it did not observe.

Under the three-state model, the same probe returns could not determine with the responder URL and the error attached. That is a page, or at minimum a ticket, and it is the correct response: your revocation checking is broken, and you should know that before you need it.

What to log on every run

The value of a probe is not the current status. It is the record that lets you diagnose a failure six months from now without re-running against an endpoint that may have changed. Log, at minimum:

  • The chain as served: subject, issuer, serial, notBefore, notAfter, and depth for each certificate.
  • The verify result: exit status, every error number, and every depth reported.
  • The trust store used, by path and by content hash if you can manage it.
  • For revocation: the responder URL, the response status, thisUpdate, nextUpdate, and producedAt if present.
  • For any indeterminate result: the specific error — timeout, TLS failure, HTTP status, OCSP error name.

The thisUpdate/nextUpdate window is particularly worth keeping. A responder that is reachable but serving stale responses is a different problem from a responder that is unreachable, and the two require different fixes. If you only log “OCSP OK”, you cannot tell them apart later.

What this does not cover

Two things are deliberately out of scope, and it is worth being explicit about why.

Certificate Transparency. CT logs are append-only ledgers of certificates that anyone can query, and a monitor can compute an audit proof to verify that a particular certificate exists in a log. That is a valuable check — it tells you whether someone issued a certificate for your domain that you did not request. But it answers a question about the public record, not about the certificate your server is currently presenting. A CT monitor and a local endpoint probe fail in different ways and should be operated as separate concerns.

CAA records. RFC 8659 is explicit that relying parties must not use CAA records as part of certificate validation. CAA is an issuance-time control that CAs check before issuing. It is not a validation input, and a probe that reads CAA and treats it as a trust signal is doing something the specification forbids.

FAQ

Can I just use openssl verify with -crl_check and be done?

You can, and it will catch some things. But -crl_check depends on having a current CRL available, either via -CRLfile or via -crl_download against the certificate’s CDP entries. If the CRL cannot be fetched, you need to know whether the tool treated that as a failure or as a pass, and you need to know which. The three-state model applies here too: a CRL fetch failure is could not determine.

What is the difference between an OCSP unknown and a responder error?

unknown is a signed, definitive response saying the responder does not know the certificate — usually because it does not serve that issuer. A responder error is an unsigned message saying the request could not be processed. RFC 6960 lists the error types and states that error messages are not signed. They are different failure modes and should be logged differently.

Should I alert on unknown?

That is a policy decision, and you should make it deliberately. If your issuer’s responder returns unknown for certificates it should know about, that is a problem worth investigating. If it returns unknown for a certificate from a different issuer because you queried the wrong responder, that is a probe bug. Either way, treating unknown as healthy by default is the one option that is hard to defend.

Why not just check the leaf’s expiry and call it monitoring?

Because the intermediate can expire first, and because expiry is only one of the three questions. A chain with a valid leaf and an expired intermediate fails path validation. A chain with a valid leaf and a revoked intermediate fails revocation checking. Neither failure is visible from the leaf’s notAfter alone.

Does a successful verify mean the certificate is valid for my clients?

It means the chain validates against the trust store you gave it, at the time you ran it, with the revocation settings you configured. If your clients use a different trust store, a different revocation policy, or a different clock, the answer can differ. Probe with the configuration you actually care about.

Posts navigation

1 2 3 4
Scroll to top