Machines
Registering, approving, and managing long-lived machines that read secrets from your vault.
This page covers long-lived machines registered through bootstrap: servers, VMs, long-running containers, and other hosts that stay registered until you revoke them. For workloads that come and go too quickly to approve by hand, like CI runners, autoscaling fleets, short-lived containers, and preview environments, see Ephemeral Machines. That path uses enrollment tokens with a built-in expiration timestamp.
A machine is any long-lived server, VM, container, or process that reads secrets from SikkerKey. Each machine has its own Ed25519 keypair. The private key stays on the machine. SikkerKey only stores the public key.
Every machine request is signed with the private key. SikkerKey verifies the signature against the stored public key before returning anything.
Bootstrapping
From the Machines page, click the + icon (hover tooltip: "Validate machine") to open the bootstrap modal. Pick your OS, copy the command, and run it on the target machine.
Linux / macOS:
curl -sSL https://api.sikkerkey.com/v1/bootstrap/YOUR_TOKEN | sh
Windows (PowerShell):
irm https://api.sikkerkey.com/v1/bootstrap/YOUR_TOKEN/ps | iex
The token is single-use and expires after 10 minutes.
What the script does
- Generates an Ed25519 keypair locally using
openssl genpkey -algorithm Ed25519 - Extracts the raw 32-byte public key
- Sends the public key, the token, and the machine's hostname to SikkerKey
- Receives back the machine ID and vault ID
- Writes
identity.jsonandprivate.pemto~/.sikkerkey/vaults/{vaultId}/with owner-only permissions
Only the public key is transmitted. The private key never leaves the machine.
Requirements
- openssl: required on all platforms. On Windows, install via
winget install ShiningLight.OpenSSL. - curl: required on Linux and macOS. Windows uses PowerShell's built-in
Invoke-RestMethod. - No root or administrator is required. Files are written under the user's home directory.
Re-bootstrapping
If you run the bootstrap command on a machine already registered with the same vault, the script replaces the existing identity files. The old machine ID is no longer valid, and the new one appears in the dashboard as pending.
Multi-vault
A machine can hold identities for multiple vaults at once, one subdirectory per vault under ~/.sikkerkey/vaults/. The SDK and CLI select the identity by vault ID, or auto-detect when only one is registered.
Approval
Newly registered machines appear as pending and cannot authenticate. From the Machines page:
- Click Approve to allow the machine to authenticate.
- Click Deny to reject and permanently remove the registration.
Denying a pending machine also removes any project memberships or secret grants that may have been pre-configured for it.
Machine States
Each machine has two flags:
| Flag | Default | Effect |
|---|---|---|
| approved | false | Becomes true when you click Approve. Required for authentication. |
| enabled | true | Can be toggled off to immediately block the machine without revoking it. A disabled machine is rejected on every request. |
Both flags must be true for authentication to succeed. Disabling a machine is the fastest way to cut off a suspected compromise while preserving its configuration and audit history.
Authentication
Every machine request carries four headers:
| Header | Value |
|---|---|
X-Machine-Id | The machine's UUID |
X-Timestamp | Unix epoch seconds at the time of the request |
X-Nonce | 16 random bytes, base64 encoded |
X-Signature | Ed25519 signature of the signed payload, base64 encoded |
The signed payload is {method}:{path}:{timestamp}:{nonce}:{bodyHash}, where bodyHash is the SHA-256 hex digest of the request body.
The SDK handles signing automatically:
val sk = SikkerKey("vault_a1b2c3d4e5")
val secret = sk.getSecret("sk_a1b2c3d4e5")
Verification order
On each request, SikkerKey runs these checks in order:
- IP lockout: 3 failed attempts from the same IP within 5 minutes trigger a 30-minute lockout.
- Machine lockout: 3 failed attempts against the same machine ID (from any IP) trigger a 30-minute lockout.
- Machine exists: the machine ID must be registered with your vault.
- IP allowlist (if enabled for the vault): the source IP must match a configured CIDR range.
- Machine enabled and approved: both flags must be
true. - Timestamp window: must be within 5 minutes of server time, with up to 1 minute of forward clock skew allowed.
- Signature verification against the machine's stored public key. Invalid signatures are rejected before the nonce is consumed, so a flood of bogus requests cannot fill the nonce table.
- Nonce uniqueness: the nonce must not have been used before for this machine. Nonces are persisted and survive server restarts. Entries older than 6 minutes are cleaned up automatically.
A captured request cannot be replayed: the timestamp window closes after 5 minutes, and the nonce is permanently consumed on first use.
Renaming
Machines are registered with their hostname by default. On the Machines page, click the machine name to edit it inline, then press Enter to save. Every rename is timestamped and attributed to the vault owner or the AI agent that made the change. Click history next to the name to see the full rename log.
Revoking
Click Revoke on a machine to remove it permanently. This deletes:
- The machine registration
- All project memberships for the machine
- All per-secret access grants for the machine
The identity file on the machine becomes a dead artifact and can be removed from disk.
If the machine was created via the GitHub integration, the dashboard prompts you to also clean up the corresponding GitHub repository secrets in one step.
Revocation is immediate and cannot be undone. To temporarily block a machine instead, disable it.
Bulk Revocation
Select multiple machines with the row checkboxes and click the bulk revoke button to remove several at once. Each is revoked individually with the same cleanup as a single revocation.
Machines Page
The Machines page lists every machine registered with your vault. Columns:
| Column | Source |
|---|---|
| Name | Hostname captured during bootstrap, or custom name after rename |
| IP address | The IP the machine registered from |
| Status | pending (not approved), ok (approved + enabled), or disabled |
| Secrets | Number of secrets the machine has been granted access to |
| Projects | Number of projects the machine has been added to |
| Last seen | Updated on every authenticated request |
| Added | Timestamp of bootstrap |
Filters and sorts available:
- Search by name
- Status: pending, ok, or disabled
- Projects: machines that are in at least one of the selected projects
- Time ranges: last seen before/after, added before/after
- Numeric ranges: minimum or maximum secrets, minimum or maximum projects
- "Never seen" filter for machines that have never authenticated
- Sort by name, last seen, added, secret count, or project count
Identity File
The bootstrap script writes two files under ~/.sikkerkey/vaults/{vaultId}/.
identity.json — the machine's identity record:
{
"machineId": "9daae125-1f61-4eca-bde6-70aaa40db018",
"machineName": "api-server-1",
"vaultId": "vault_a1b2c3d4e5",
"apiUrl": "https://api.sikkerkey.com",
"privateKeyPath": "/home/deploy/.sikkerkey/vaults/vault_a1b2c3d4e5/private.pem"
}
private.pem — the Ed25519 private key in PKCS#8 PEM format.
The SDK reads identity.json to know which machine it is and which vault to authenticate against, then loads the private key from privateKeyPath to sign each request. Both files are owner-only readable. Protect them the way you would any other secret material.
Team Member Machines
Team members with the machine_add permission can attach their own machines to a project inside your vault. The machines originate from the team member's vault and are displayed on the project's Machines tab with an owner badge.
Removing a team member's machine from a project immediately revokes its access to the project's secrets. The machine itself remains registered in the team member's own vault. Both you and the team member receive an audit log entry.