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, and .NET. 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 (paid plans)

Paid plans 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:

  1. Per-secret data keys are random AES-256 keys, one per secret, used to encrypt the value itself
  2. Per-project master keys encrypt the data keys, so each project's encryption is independent of every other project
  3. Server encryption key encrypts the master keys at rest, provided at server boot and held only in memory

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.

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.

Teams

You can invite other SikkerKey users to your vault by email. Team members get access per-project and see only the projects you have added them to.

Within an assigned project, a team member can fully manage secrets: create, update, delete, replace values, view version history, add notes. Secret access is implicit on project membership. "View" means metadata (name, version, machine count, last accessed timestamp). Reading the actual plaintext value always requires an authenticated machine with its own per-secret grant. The dashboard never displays decrypted secret values for anyone.

Machine permissions are self-scoped and granular. A team member can be granted independent permission to view, add, remove, or configure their own machines within a shared project. A separate machine_provision permission controls whether they can pre-provision new machine identities for the project. A third permission category, policy_manage, governs whether a member can create access policies in the project and bind secrets to them — gated separately because shaping the constraint layer can weaken security on credentials owned by the vault owner.

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, and .NET
  • 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