Secrets management for any application that needs a credential at runtime.

Store database URLs, API keys, OAuth tokens, and certificates. Applications fetch them by signing each request with a key generated on the host. The application never holds a credential that could leak from a CI log or a checked-in env file.

signed request · public key registry
your app
api-server-1
priv keyheld
SikkerKey · public keys
mch_8f3a··c7e1
api-server-1
  Each request is signed with the machine's private key. SikkerKey verifies the signature against the public key.

Most secrets leak because they live somewhere they shouldn't.

API keys end up in source control. Database URLs sit in .env files copied between developers. Long-lived tokens hang around in CI logs and Slack messages. Service accounts get baked into Docker images that get pushed to public registries by accident.

Anything that proves access by being a string of characters can leak the moment someone reads it. The breach reports keep listing the same root cause: a credential ended up in a place where someone who shouldn't have it could read it.

.env.productioncommitted to repo · 2 days ago
DATABASE_URL=postgres://prod:hunter2@db… STRIPE_SECRET_KEY=sk_live_4eC39H… AWS_ACCESS_KEY_ID=AKIA3F7… JWT_SIGNING_SECRET=5d3e8f2a9c…
build-prod-1442.logCI artifact · public
# run integration tests + docker run -e DB_PASSWORD=hunter2 app:test + echo "$API_KEY" | curl -X POST... ›   exposed to anyone with the CI link

Machines authenticate by signing each request.

Setting up a machine is one command. The bootstrap script generates an Ed25519 keypair on the host. The public half is registered with SikkerKey. The private half is written to a file readable only by its owner, and never leaves the machine.

From then on, every request the application makes is signed locally with that private key. SikkerKey checks the signature against the public key it has on file. The signed payload includes the HTTP method, path, a timestamp, and a one-time random value — so even a request captured on the network can't be re-sent by anyone else.

There's no bearer token for an attacker to steal from a CI log. There's no API key to commit to a repo by accident. The thing that proves a machine is allowed to read a secret is the same kind of artifact that protects an SSH session — a private key sitting on one disk.

on the host you're authorizing
$ curl -sSL https://api.sikkerkey.com/v1/bootstrap/T9Kx... | sh SikkerKey Bootstrap =================== Directory: ~/.sikkerkey Generating Ed25519 keypair... Registering... Machine registered successfully. Vault: vault_a1b2c3d4 Machine ID: 9daae125-1f61-4eca-bde6-70aaa40db018 Name: api-server-1 Identity: ~/.sikkerkey/vaults/vault_a1b2c3d4/identity.json The machine is pending approval. Approve it from the dashboard.

Fetching a secret is one SDK call, or one CLI command.

Your code asks for a secret by ID. The decrypted value comes back on the same line. Signing, replay protection, and key resolution happen inside the SDK or CLI without configuration.

SDKs for Python, Node.js, Go, Kotlin, and .NET. The CLI is a single binary installed with npm install -g sikkerkey or go install, with no runtime dependencies.

from sikkerkey import SikkerKey sk = SikkerKey() db_url = sk.get_secret("sk_db_prod") # one signed request, decrypted on return
import { SikkerKey } from '@sikkerkey/sdk' const sk = SikkerKey.create() const dbUrl = await sk.getSecret('sk_db_prod') // one signed request, decrypted on return
import sikkerkey "github.com/SikkerKeyOfficial/sikkerkey-go" sk, _ := sikkerkey.NewAutoDetect() dbURL, _ := sk.GetSecret("sk_db_prod") // one signed request, decrypted on return
import com.sikker.key.sdk.SikkerKey val sk = SikkerKey() val dbUrl = sk.getSecret("sk_db_prod") // one signed request, decrypted on return
using SikkerKey; var sk = SikkerKeyClient.Create(); var dbUrl = await sk.GetSecretAsync("sk_db_prod"); // one signed request, decrypted on return
cli
$ sikkerkey connect vault_a1b2c3d4 connected: vault_a1b2c3d4 $ sikkerkey get sk_db_prod postgres://[email protected]:5432/app

The mechanism doesn't change with team size — what you turn on alongside it does.

A solo developer running a Discord bot bootstraps one machine and never touches secrets again. A team running fifty production services bootstraps each one the same way, scopes access per project, and reviews the audit log. The authentication model is the same; the controls layered on top scale with the room you're operating in.

Per-secret access grants
A machine can read only the secrets it's been explicitly granted, by ID. No path wildcards.
Time windows & IP allowlists
Restrict access to business hours or known networks per secret, not per credential.
Co-sign requirements
Sensitive secrets can require a second machine's signature before they're released.
Append-only audit log
Every access, grant change, and rotation is recorded. Rows cannot be updated or deleted, even by a database admin.
Canary secrets
Decoy secrets that freeze the whole project the moment they're read. A request that shouldn't happen tells you so.
Ephemeral & temporary machines
Short-lived hosts and contractor access expire automatically, no cleanup script required.
Try it on something small first.
Free tier covers a personal project. Setup is one command.