Skip to the content
Krizaka Blog
All posts

SecurityBuilding Krizaka · part 3 of 3

How many accounts and keys does a one-person software company need?

Twelve services, more than 80 secrets, and a few mistakes that taught me how to keep them. How I keep them out of code and chats, and what I automate around them with agents and CI.

Diagram: twelve services grouped by role around a small software company: code and CI, packages, cloud and databases, GPU, media, e-mail, domains, anti-robot, mobile apps; in the middle, more than 80 secrets kept out of the code

When I started Krizaka, I thought I needed a GitHub account and a host. This week I counted. Twelve services, and more than 80 secret values: API keys, tokens, database passwords. For a company where I'm alone, with AI agents writing a large part of the code.

This post is about how you get there, how I keep them, and the mistakes that taught me how. It contains no key, no account id, no path of my folders. That's sort of the point.

Twelve services, for what

Each service answers a simple need. Code and CI live on GitHub. Packages are published on npm and Maven Central, with a signing key for the latter. The apps and the databases run at DigitalOcean. GPUs are rented by the hour at RunPod. Images and videos are served by Bunny. E-mails go out through Mailgun. The domain names sit with a registrar. Cloudflare provides the anti-robot check on forms. For mobile you need Expo to build the apps, Firebase for notifications and an Apple developer account.

None of them is a luxury. But each brings at least one key, often several: one per environment, one per app, one with fewer rights for CI. That's how twelve accounts become more than 80 secrets.

Where to keep them

I wrote the basic rule very early: a secret is never in code, never in a repository, never in a chat. Not even in a chat with an AI agent, and especially not there.

In practice, secrets live in a private folder, outside the repositories, on my machine. Deployed apps receive them as secrets of the platform that hosts them, never in clear in a versioned file. The repository's configuration file just holds a placeholder word instead of each value.

To read a secret there's a small script that fetches one key at a time and never prints it: you put it in a variable, you use it, that's all. And when I want to check it's there, I look at its length, not its value.

Environment variables are named by their role, not by the provider. You write MAIL_PROVIDER=mailgun rather than a variable named after the vendor:

bash
MAIL_PROVIDER=mailgun
MAIL_API_KEY=unset
MAIL_DOMAIN=unset

Switching providers then means changing a value, not renaming variables across ten repositories.

The mistakes that taught me

I didn't come up with these rules out of caution. I wrote them after mistakes.

An agent session printed a database's full address in its output, password included. It only wanted to check a configuration. The password had to be changed right away. Since then, a guard runs before every agent command: if the command could print a secrets file, it is refused, with a message explaining how to do it otherwise. Even a home-made "masking" is refused, because that's often where it leaks.

A rented GPU stayed on about two hours after the work was done. Between $7 and $8, for nothing. Its watchdog was supposed to shut it down, but it didn't have the key to do it. I tell the story in the post about costs. Since then, a watch loop stops the machine after twenty minutes without work.

A password stayed at its old value somewhere after a rotation. The lesson: a rotation is only done when every place that uses the key has the new one, and you check each place, not just the first.

What I automate around them

When you're alone, you can't watch everything. So you automate what can be, with agents and CI.

A pull request merges itself when every check is green, and never before. A lock stops two heavy jobs from running at the same time on my machine. A cap limits what AI can spend per day in the development environment. Public forms have an anti-robot check. And every key has as few rights as possible: the one that sends e-mails can only send, it can't even read a list.

The agents write code, but they never see a key. They know it exists, they know its name, they use it through the small script. It's the best way I've found to work fast without being afraid.

What you can take from it

List your accounts and keys today, even if you're just starting: you'll be surprised by the number. Keep secrets in a separate place, outside your repositories, and read them one key at a time without ever printing them. Name your variables by their role. Give each key as few rights as possible. And when a mistake happens, turn it into a rule right away, then into a tool that prevents it.

Keep it, pass it on

Related posts

AI · 7 min read

The anatomy of an AI prompt: what each added line really changes

A six-word prompt, then three layers of detail, on my Mac with the same seed. What gets better, what gets worse, what a negative prompt can do, and what I didn't prove.

Measured