Introduction
What SikkerKey is, how it works, and the mental model behind secrets, machines, and access control.
This page explains the SikkerKey model end to end. Read it top to bottom to build a mental picture of how vaults, machines, secrets, and grants fit together. For a hands-on walkthrough, see Quickstart. For lookup of specific terms, see Concepts.
SikkerKey is a secrets management platform where machines authenticate with Ed25519 cryptographic signatures on every request. Your servers, containers, and CI runners prove their identity by signing each request with a private key that never leaves the machine.
The Core Model
A SikkerKey vault is your account's encrypted secrets storage, identified by a vault ID like vault_a1b2c3d4e5. Inside a vault, projects group secrets and machines into logical environments (e.g. production, staging), and each project has its own independent encryption key — compromising one project's encryption has no effect on any other. Secrets are the values you store (API keys, passwords, database credentials, tokens) and each belongs to exactly one project. Machines are the servers, containers, and CI runners that fetch secrets; each holds its own Ed25519 keypair. A grant is the explicit row connecting one machine to one secret — there is no wildcard, no inheritance, no implicit access. Every machine-to-secret relationship is recorded individually.
A separate identity class, AI agents, lets AI clients (Claude Code, Codex, Cursor, Continue) manage your vault — provision machines, plant canaries, configure policies, query the audit log — but holds no path to read the plaintext content of any stored secret. The two identity classes never cross at the route or database layer.
A Secret's Journey
You store a secret. You paste a value into the dashboard. SikkerKey generates a fresh random 32-byte data key, encrypts the value with it using AES-256-GCM (with the secret ID bound as authenticated additional data), encrypts that data key with the project's master key, and stores both encrypted blobs. The raw data key is wiped from memory in a finally block.
You register a machine. You create a one-time bootstrap token in your dashboard and run it on the target machine:
curl -sSL https://api.sikkerkey.com/v1/bootstrap/<token> | sh
The script generates an Ed25519 keypair locally, sends only the public key to SikkerKey, and writes the private key to ~/.sikkerkey/vaults/{vaultId}/private.pem with permissions set to owner-only. The machine appears in the dashboard as pending. You approve it, add it to a project, and grant access to specific secrets.
Bootstrap scripts exist for Linux, macOS, Windows (PowerShell), generic CI/CD, and Kubernetes. The one-time token expires after 10 minutes and is destroyed on first use.
The machine reads a secret. The SDK or CLI reads the local private key, signs the request, and retrieves the plaintext value:
val sk = SikkerKey("vault_a1b2c3d4e5")
val apiKey = sk.getSecret("sk_a1b2c3d4e5")
The signed payload is {method}:{path}:{timestamp}:{nonce}:{bodyHash}. The request carries four headers: X-Machine-Id, X-Timestamp, X-Nonce, X-Signature. SikkerKey verifies the signature against the stored public key, runs the access checks below, decrypts the secret, and returns the plaintext over HTTPS.
SDKs are available for Kotlin, Go, Python, Node.js, .NET, and PHP. The CLI provides equivalent access from shells, scripts, and CI jobs.
The Access Model
Five conditions must all hold for a machine to read a single secret. The signature on the request must verify against the machine's stored public key, and it must carry a timestamp within five minutes of server time and a nonce that hasn't been used before — nonces are persisted in the database and survive server restarts, so an intercepted request can't be replayed even moments later. The machine itself must be both approved (the vault owner explicitly accepted it after registration) and enabled (not subsequently disabled). The project containing the secret must not be frozen — a canary trigger or manual freeze blocks every read in the project until the vault owner clears it. The machine must be added to the project containing the secret. And it must hold an explicit grant to that specific secret. Adding a machine to a project does not, on its own, grant it access to any secret in the project; each secret requires its own grant.
Optional: IP Allowlist
You can add a sixth layer by enabling the vault's IP allowlist. When enabled, machine requests are rejected unless the source IP matches one of the CIDR ranges you have configured, regardless of whether the other five conditions are satisfied. The check runs before signature verification, so blocked IPs never reach the cryptographic path at all. With allowlisting enabled and an empty list, every machine request is denied.
Optional: Access Policies
Project-scoped access policies can be bound to specific secrets to add finer-grained conditions on each read. Each policy carries up to six configurable axes — time window, per-secret IP allowlist, read-rate cap, co-sign requirement, TTL destruction, and rotate-after-N — composable in any combination. Bindings are opt-in: a secret with no policy bound to it behaves as the standard five-requirement model. See Access Policies.
Encryption
SikkerKey uses three-layer envelope encryption:
- Per-secret data keys are random AES-256 keys, one per secret, used to encrypt the value itself
- Per-project master keys encrypt the data keys, so each project's encryption is independent of every other project
- Root key encrypts the master keys, held on separate, isolated infrastructure rather than on the systems that store your data
Every AES operation uses AES-256-GCM with a fresh random IV and a 128-bit authentication tag. The secret ID is bound as authenticated additional data during encryption, so an encrypted blob cannot be moved between database rows without decryption failing.
Secret Types
SikkerKey supports five secret types, each suited to a different access pattern. Secrets store a single encrypted value (API keys, tokens, signing secrets, connection strings) with optional scheduled rotation. Structured secrets store multiple named fields as one encrypted unit (e.g. a database credential with host, port, username, password) and can rotate per-field, leaving static fields untouched. Managed secrets are database credentials that SikkerKey rotates and pushes to your database via a local CLI agent — SikkerKey itself never accepts inbound connections from your database, and the agent applies new credentials in place using the appropriate SQL command for PostgreSQL, MySQL, MariaDB, Redis, or MongoDB. Canary secrets are tripwires planted alongside real credentials: any granted machine read triggers a critical audit entry, freezes the surrounding project, dispatches every alert configured for the canary action, and still returns the value so the attacker keeps going while the operator investigates. TTL secrets are one-time self-destructing share links for handing credentials to people outside your vault — they use AES-256-GCM at rest with an Argon2id-hashed passphrase, view-once on the correct passphrase or destroy on the wrong one, and aren't readable by machines at all.
See Concepts → Secret Types for per-type detail and the dashboard pages under "Secrets" in the sidebar for hands-on guides.
CI/CD with Ephemeral Machine Identity
Every CI run is its own machine. SikkerKey treats it that way. Create an enrollment token in the dashboard scoped to the projects and secrets your pipeline needs, add the token's plaintext to your CI provider's secret store as SIKKERKEY_ENROLLMENT_TOKEN, and copy the bootstrap script and workflow snippet the dashboard generates for GitHub Actions, GitLab CI/CD, or Bitbucket Pipelines.
At runtime, the script generates a fresh Ed25519 keypair on the runner, registers a machine under the token's policy, fetches the secrets it was granted, and exposes them as environment variables for subsequent steps. The keypair lives only on the runner's filesystem and is gone when the runner is destroyed. The enrollment token can only register machines within its configured policy; it cannot read secrets directly, so a leaked token still cannot exfiltrate values outside the projects, secrets, source CIDR, or hostname pattern you set.
Serverless
Serverless and other ephemeral or read-only-filesystem runtimes (AWS Lambda, Google Cloud Run, Vercel, Netlify, Fly.io, and similar) have nowhere to persist a machine identity, so the disk-based bootstrap above does not fit. The SDKs cover this with an in-memory bootstrap: on cold start the SDK generates an Ed25519 keypair in memory, enrolls a short-lived ephemeral machine with an enrollment token, fetches the secrets that token grants, and writes nothing to disk. When the instance is torn down, the keypair goes with it.
You create the enrollment token the same way as for CI, scoped to the projects and secrets the function needs. Leave the source-CIDR restriction unset, since serverless egress IPs are dynamic, and give the token a name pattern so each cold-start machine gets its own identifiable name in the audit log.
See the Node.js SDK for the memory-only bootstrap API; the same pattern is available in every SDK.
Docker Pre-Provisioning
For Docker containers where running an interactive bootstrap inside the image is impractical, SikkerKey pre-provisions a machine identity from the dashboard. You select the project and the specific secrets the container should access, and SikkerKey generates an Ed25519 keypair server-side, approves the machine, and grants access to each selected secret.
You download the resulting bundle (identity.json, private.pem, cli.json) as a ZIP via a single-use link that expires after 15 minutes. You extract it onto your host, mount the directory into the container at /etc/sikkerkey/, and the SDK or CLI picks up the identity automatically via the SIKKERKEY_IDENTITY environment variable.
A pre-provisioned machine uses the same Ed25519 authentication as any other. The only difference is how the keypair was created and delivered. For Kubernetes, use the standard bootstrap script, which emits a kubectl create secret command you apply to your cluster.
Organizations
By default a vault has a single human owner: you. When more than one person needs to act on the same vault, you convert it to an organization. The conversion is one-way, and the vault, its projects, secrets, and machines stay exactly where they are; what changes is who can act on them and what they are allowed to do.
You invite members by email. Each must already have their own SikkerKey account, because membership joins an existing identity to your vault rather than creating a shared login. Members sign in as themselves, with their own password and 2FA, and pick your vault from a post-login vault picker. Every action a member takes is attributed to them individually in the audit log.
What a member can do is set by a template the owner authors: a bundle of capabilities (managing secrets, viewing the audit log, managing machines, authoring templates, and so on) paired with a project scope that decides which projects those capabilities apply to, either every project or a specific list. One template can be assigned to many members. A member with no template can sign in and see the vault in their picker but take no action until the owner assigns one.
Membership is a dashboard-plane concept only. Even a member with full secret management acts on metadata and configuration, never plaintext: reading a secret's value still requires an authenticated machine with its own per-secret grant, and the dashboard never displays a decrypted value to anyone. Machines that read secrets at runtime keep authenticating with their own Ed25519 keypair exactly as before, so a member's access has no bearing on how a machine proves itself or what it can read. A compromised dashboard session never yields a machine identity, and a compromised machine never grants dashboard access.
See Organizations for converting a vault, inviting and scoping members, authoring templates, and enterprise single sign-on.
AI Agents
SikkerKey ships an MCP server that lets AI clients (Claude Code, Codex, Cursor, Continue) manage the vault through structured tool calls. The MCP server runs locally next to the AI client and authenticates with the same Ed25519 signed-request scheme machines use, but with one critical difference: AI agents are a separate identity class and can never read the plaintext content of a stored secret.
An AI agent can manage projects, plant canaries, configure access policies, approve machines, audit recent activity, set up alerts and webhooks, and draft support tickets. It cannot fetch a secret's value through any tool. Write actions like creating or rotating a secret accept a plaintext input from the AI, encrypt it server-side, and never round-trip the value back. The one exception is the temporary-secret share-link primitive, which intentionally returns one-shot delivery credentials for handoff to a human recipient.
Each AI agent holds a flat set of scopes (e.g. projects.secrets.write, audit.read) granted at provisioning time and revocable from the dashboard at any time. An optional project allowlist further constrains where those scopes apply. Scope-set and allowlist mutation are dashboard-only by design, so an agent cannot expand its own privileges. Every tool call is signed with the agent's private key and recorded in the audit log with the agent's identity attached.
See MCP Server Overview to install the binary and register it with your AI client, and the MCP Security Model for the full management-plane contract.
Audit, Alerts, and Webhooks
Every vault operation writes to an append-only audit log: secret reads, writes, rotations, machine registrations and approvals, permission changes, grant modifications, authentication failures. Each entry records the user, machine ID, secret ID, source IP, action name, severity (info, low, medium, high, critical), a human-readable detail string, and a millisecond timestamp.
The audit log streams to your dashboard in real time via server-sent events. Per-action email alerts can be enabled for any event type. Webhooks fire with HMAC-SHA256 signatures in the X-SikkerKey-Signature header and are retried with exponential backoff, auto-disabling after ten consecutive delivery failures.
Audit log retention, alert delivery, and webhook availability depend on your subscription plan.
Next Steps
- Quickstart: register a machine and fetch a secret in five minutes
- Concepts: deeper coverage of the model, access control, and invariants
- Dashboard secrets: managing secrets from the web interface
- Managed secrets: automated database credential rotation
- CLI Guide: single-binary command-line interface
- SDK Reference: Kotlin, Go, Python, Node.js, .NET, and PHP
- Integrations: GitHub, GitLab, Bitbucket, Docker, Kubernetes
- MCP Server: manage the vault from Claude Code, Codex, Cursor, and other AI clients
- Encryption details: the full cryptographic model
- Access policies: per-secret time, IP, rate, co-sign, TTL, and rotate-after-N constraints
- Audit logging: severity classification, retention, alert integration