← Back to Blog

A One-Day Security Baseline for a Solo Fleet

About this artifact

essayon-the-recordmaintained

automation · since 2026

When you run production by yourself, security advice written for companies is mostly noise. It assumes a team to watch dashboards, a budget for tooling, a compliance regime to satisfy. I have none of those, and neither does anyone else operating a small fleet alone. So the question is not "how do I build a security program." It is "what is the smallest set of controls that stops the failures that would actually end me," and the honest answer is that it fits in an afternoon.

Two principles run under the whole afternoon. The threats that realistically kill a solo operation are a short, boring list with cheap, set-once defenses, so the goal is a catastrophic floor, not coverage. And the highest-leverage controls run themselves: log everything, alarm on the catastrophes, and make the irreversible mistakes structurally hard, because anything that depends on you watching fails the day you are not watching.

A thick floor line held up by eight green set-once controls, with the three catastrophic failures below it in red and survivable failure above it.

The real threat model is boring#

Start by being honest about what actually goes wrong for a one-person operation. The real list is mundane:

  • A secret (an API key, a token) pasted into a repo and pushed.
  • A credential that leaks and gets used to run up a bill or poke at your resources.
  • A cost that runs away, from a mistake or a compromise, while you are asleep.
  • A destructive git accident: a force-push that erases a main branch's history.
  • A dependency with a known vulnerability sitting in your build.

None of these require a movie villain. They are the accidents that happen to careful people on ordinary days. And every one of them is cheap to defend against, which is the whole opportunity: a small operation cannot afford a security team, but it does not need one to handle this list.

There is one way a solo operator is genuinely more exposed than a team, and it shapes the whole approach. On a team, a second person reviews the change and sometimes catches the secret in the diff, the over-broad permission, the bucket left open. Alone, that second pair of eyes does not exist. So the automated controls below are the substitute for the review redundancy a team gets for free. The machine has to be the colleague who catches the mistake, because there is no colleague.

The baseline, set up once#

Here is what I stood up, what each piece defends, and crucially whether it prevents a problem or just makes sure I find out fast.

Control What it defends against Prevent or detect
CloudTrail logging across the account "What happened, and when" after anything odd Detect
GuardDuty threat detection on that trail Credential misuse, unusual API patterns Detect
IAM Access Analyzer A resource accidentally open to the world Detect
An AWS Budgets alarm, set low Runaway cost from error or compromise Detect, early
GitHub secret scanning + push protection A secret reaching the repo at all Prevent
Dependabot alerts Known-bad packages in the build Detect
Branch protection on every repo Force-push or deletion of main history Prevent
Scoped IAM identities for daily work Blast radius if one credential leaks Prevent, limit

That is the entire baseline. Most of it is managed services you enable, a couple of alarms you point at your email, and a protection rule you apply across every repository. The cost is an afternoon of setup and a few dollars a month, and in exchange the boring catastrophes either cannot happen or cannot happen quietly.

Two principles do the heavy lifting#

The specific services matter less than the two ideas underneath them, because those ideas tell you what to reach for next as the fleet grows.

The first is detection over prevention for anything you cannot fully prevent. I cannot guarantee that no secret will ever be committed, that no credential will ever leak. What I can guarantee is that if it happens, I will know in minutes, not months. Security for a small operation is less about higher walls than about shortening the time between "something went wrong" and "I know about it." A budget alarm is the purest version of this: it does not stop a compromised key, but it turns a five-figure surprise at the end of the month into a text message tonight.

The second is guardrails over discipline for anything irreversible. Force-pushing over main, pushing a secret to a public repo, working as an unrestricted root identity: these are mistakes you do not get to undo, so the defense cannot be "remember not to do that." It has to be structural. Branch protection makes the destructive git mistake impossible rather than discouraged. Push protection blocks the secret at the gate instead of trusting me to notice. Scoped identities mean a leaked credential cannot reach what it was never given. This is the same lesson I keep relearning everywhere: a control a tired human has to remember is not a control.

What this is not#

Being honest about the floor means being honest about the ceiling. This baseline is detection and blast-radius control. It will not stop a determined, targeted attacker who wants specifically you. There is no continuous monitoring, no penetration testing, no compliance posture. For a personal fleet that is the correct scope: a month spent building those would be effort stolen from the actual product to defend against threats I do not face.

There is one piece of discipline the automation cannot replace, and it is the easy one to skip: test that the alerts actually reach you. An alarm you never confirmed is not an alarm, it is a comforting belief. The afternoon is not done when the services are enabled. It is done when you have watched a test alert actually land in your inbox, and rotated any credentials you minted along the way so none of them outlive the setup that needed them.

The floor, and why it holds#

Both halves are deliberately unambitious: build the catastrophic floor, stop there, and skip the enterprise coverage you cannot staff. The floor holds precisely because it does not depend on you. Detection for what you cannot prevent, guardrails for what you cannot undo, both running without supervision, because you are the one component guaranteed to be unavailable the day it matters. It took an afternoon. It removed the failure modes that would actually have been fatal.


Related:

Questions this post answers

Which security risks did you prioritize for a solo fleet?
For my solo fleet, I prioritized exposed secrets, misused credentials, runaway cloud spend, destructive changes to main branch history, and dependencies with known vulnerabilities. This is the threat set I chose for the baseline, not a claim that it covers every attacker or operation.
Which controls make up your solo-fleet security baseline?
My baseline uses CloudTrail for account history, GuardDuty for suspicious activity, Access Analyzer for unintended public access, and a budget alarm for cost surprises. GitHub secret scanning and push protection, Dependabot, branch protection, and scoped IAM cover repository secrets, dependencies, destructive history changes, and credential blast radius. Each control is labeled as prevention, detection, or blast-radius limitation. This is a deliberately minimal baseline for a one-person operation, not a complete security posture.
When do you use detection instead of structural prevention?
I favor detection when I cannot guarantee prevention, and structural guardrails when the mistake is hard to reverse. A budget alarm reveals spend; branch and push protection block specific repository mistakes; scoped identities limit what a leaked credential can reach.
How do you verify that security alerts actually work?
I do not count an alerting control as finished until a test alert reaches the intended inbox. I also rotate credentials created during setup so temporary access does not outlive the work that required it.

Keep reading

Case study

Enterprise MFA Self-Service Platform: Web, Mobile, and QR Code Enrollment

Built three interconnected authentication platforms used by the entire enterprise workforce.

Read
Post

Institutional Memory for a Team of One

A team holds its hard-won knowledge across many heads. A solo operator holds it in one, and that one forgets. The fix is to externalize memory into structured records the tools read by default, so the system remembers what the person cannot.

Read
Post

When CI Costs More Than It Saves

GitHub Actions' default minute allowance is priced for a team that types at human speed. At agent velocity the bill breaks before the engineering does. Here is how a forced workaround, a local CI mirror plus local deploys, became the better default.

Read
Post

How this site is organized

The navigation on caskeycoding.com is a build artifact: one public content graph, several switchable views projected from it, and CI checks that keep the graph and the routes from drifting apart.

Read
Post

The caskeycoding.com tech stack at a glance

A high-level tour of the technologies running this site: Next.js on CloudFront, Python Lambdas behind API Gateway, DynamoDB plus S3, Anthropic's API with a Bedrock fallback, and AWS CDK wiring it together.

Read
Post

Welcome: Building Platforms for Scale

Where this blog started: owning enterprise monitoring at Prudential and Amazon, an automation mishap that paged a whole support queue for ten minutes, and the throughline that still runs through everything I build, make the safe path the only path and then prove it.

Read

Follow the work

New tools and writing as they ship — pick a channel.

Written by Eric Caskey. I build AI tools you can actually use. Explore the Tools or see the case studies.