Documentation

Everything you need to deploy and operate Lockwave.

Quick Start

Get running in three steps:

  1. [Create your account]({{ route('register') }}) and set up your first team
  2. Generate an SSH key or import your existing public key
  3. Enroll your first host using the install command below
curl -fsSL https://get.lockwave.io/install.sh | sudo bash -s -- \
  --token YOUR_ENROLLMENT_TOKEN \
  --api-url https://lockwave.io \
  --os-user deploy

The enrollment token is generated in the dashboard when you enroll a new host. It expires after 15 minutes.

Architecture

Lockwave consists of two components:

  • Control Plane — The Lockwave web application that stores teams, SSH public keys, hosts, and assignments. It computes the desired state for each host and serves it via a REST API.
  • Daemon (lockwaved) — A statically compiled Go binary that runs on each managed host. It polls the control plane over outbound HTTPS, computes the delta between current and desired state, and atomically rewrites the authorized_keys file.

The daemon never opens inbound ports. All communication flows from the daemon to the control plane, never the reverse. This means you don't need to modify firewall rules or open SSH tunnels.

Daemon Installation

The install script downloads the correct binary for your architecture, creates a systemd service, and registers the host with the control plane.

Supported Platforms

  • Linux (amd64, arm64)
  • macOS / Darwin (amd64, arm64)
  • FreeBSD (amd64)

Verifying Installation

systemctl status lockwaved
journalctl -u lockwaved -f

The host should appear in your dashboard with a "healthy" status within 60 seconds.

Uninstalling

To remove the daemon from a host, run the install script with --uninstall. It stops the service, removes the binary, systemd unit, sshd drop-in config, and the config directory.

curl -fsSL https://get.lockwave.io/install.sh | sudo bash -s -- --uninstall

Daemon behavior

The daemon can apply optional security hardening and key modes per host:

  • Block password authentication — When enabled for a host in the dashboard, the daemon writes a drop-in file under /etc/ssh/sshd_config.d/ (e.g. 99-lockwave.conf) to set PasswordAuthentication no and KbdInteractiveAuthentication no. It runs sshd -t to validate, then reloads sshd. The file is overwritten on the next sync.
  • Exclusive keys — When the server sends exclusive_keys: true for a managed OS user, the daemon replaces the entire authorized_keys file with only the Lockwave-managed keys (no keys outside the block are preserved). Configure per host or per OS user in the dashboard.
  • IP binding — The server records the IP address used when the daemon first registers. This IP is never automatically updated. On each sync, the server compares the daemon's request IP to the registered IP. On mismatch, an audit event (host.ip_mismatch) is logged and the dashboard shows a warning. The registered IP only changes when you manually accept the new IP from the host detail page.

For full daemon documentation including configuration, self-update, and troubleshooting, see the Lockwave daemon README on GitHub.

Key Management

Lockwave supports two key types:

  • ed25519 — Default and recommended. Smaller, faster, and more secure than RSA.
  • RSA 4096 — For legacy compatibility with older SSH clients or servers.

Keys can be generated server-side (the private key is shown once and never stored) or imported by pasting your existing public key. Each key has a source (e.g. generated or imported) and optional tags for filtering and reporting.

Keys are scoped to teams. Visibility options:

  • Personal — Only visible to the key owner
  • Shared — Visible to team admins and owners

Assignments

Assignments map SSH keys to hosts and OS users. They define the desired state of each authorized_keys file.

Create an assignment to grant access. Delete it to revoke. Changes propagate to all affected hosts on the next daemon sync cycle. Assignments can include an optional description and record who created them for audit.

Sync intervals depend on your plan: Free (5 min), Standard (60 sec), Business (30 sec), Enterprise (15 sec).

API Reference

The Lockwave REST API lets you manage all resources programmatically. All endpoints are versioned under /api/v1/.

Authentication

Create an API token from your profile settings. Include it as a Bearer token in every request:

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
     -H "Accept: application/json" \
     https://lockwave.io/api/v1/ssh-keys

Team Context

All endpoints operate in the context of a team. By default, your current team is used. To target a different team, pass the X-Team-Id header:

curl -H "Authorization: Bearer YOUR_API_TOKEN" \
     -H "X-Team-Id: YOUR_TEAM_UUID" \
     -H "Accept: application/json" \
     https://lockwave.io/api/v1/hosts

Base URL

https://lockwave.io/api/v1/

Endpoints

User & Teams

Method Path Description
GET /api/v1/user Authenticated user profile
GET /api/v1/teams List your teams
GET /api/v1/teams/{team} Show team details

SSH Keys

Method Path Description
GET /api/v1/ssh-keys List team keys
POST /api/v1/ssh-keys Import or generate key
GET /api/v1/ssh-keys/{id} Show key details
PATCH /api/v1/ssh-keys/{id} Update key name/comment
DELETE /api/v1/ssh-keys/{id} Soft-delete key
POST /api/v1/ssh-keys/{id}/block Block key
POST /api/v1/ssh-keys/{id}/unblock Unblock key

Hosts

Method Path Description
GET /api/v1/hosts List team hosts
POST /api/v1/hosts Create host
GET /api/v1/hosts/{id} Show host detail
PATCH /api/v1/hosts/{id} Update host (including security settings: block_password_auth, exclusive_keys_default, enforce_ip_binding, tags)
DELETE /api/v1/hosts/{id} Delete host

Host Users

Method Path Description
GET /api/v1/hosts/{id}/users List OS users
POST /api/v1/hosts/{id}/users Create OS user
PATCH /api/v1/hosts/{id}/users/{uid} Update OS user
DELETE /api/v1/hosts/{id}/users/{uid} Delete OS user

Enrollment & Credentials

Method Path Description
POST /api/v1/hosts/{id}/enrollment-tokens Generate enrollment token
POST /api/v1/hosts/{id}/credentials/rotate Rotate daemon credentials

Assignments

Method Path Description
GET /api/v1/assignments List team assignments
POST /api/v1/assignments Create assignment
GET /api/v1/assignments/{id} Show assignment
DELETE /api/v1/assignments/{id} Delete assignment

Break Glass

Method Path Description
GET /api/v1/break-glass List events
POST /api/v1/break-glass/activate Activate break glass
POST /api/v1/break-glass/{id}/deactivate Deactivate break glass

Audit Events

Method Path Description
GET /api/v1/audit-events List paginated audit log
GET /api/v1/audit-events/{id} Show single event

Reports

Method Path Description
GET /api/v1/reports List reports
POST /api/v1/reports Request new report
GET /api/v1/reports/{id}/download Download report file

Webhook Endpoints

Method Path Description
GET /api/v1/webhook-endpoints List webhook endpoints
POST /api/v1/webhook-endpoints Create webhook endpoint
GET /api/v1/webhook-endpoints/{id} Show webhook endpoint
PUT /api/v1/webhook-endpoints/{id} Update webhook endpoint
DELETE /api/v1/webhook-endpoints/{id} Delete webhook endpoint
GET /api/v1/webhook-endpoints/{id}/deliveries List delivery attempts
POST /api/v1/webhook-endpoints/{id}/test Send test webhook

Notification Channels

Method Path Description
GET /api/v1/notification-channels List notification channels
POST /api/v1/notification-channels Create notification channel
GET /api/v1/notification-channels/{id} Show notification channel
PUT /api/v1/notification-channels/{id} Update notification channel
DELETE /api/v1/notification-channels/{id} Delete notification channel
POST /api/v1/notification-channels/{id}/test Send test notification

Audit Log Stream

Method Path Description
GET /api/v1/audit-stream Show stream configuration
PUT /api/v1/audit-stream Create or update stream
DELETE /api/v1/audit-stream Delete stream
POST /api/v1/audit-stream/test Send test event to stream

Request Examples

List SSH Keys

curl -s -H "Authorization: Bearer $TOKEN" \
     -H "Accept: application/json" \
     https://lockwave.io/api/v1/ssh-keys

Create a Host

curl -s -X POST \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -H "Accept: application/json" \
     -d '{"display_name":"web-01","hostname":"web-01.example.com","os":"linux","arch":"amd64"}' \
     https://lockwave.io/api/v1/hosts

Create an Assignment

curl -s -X POST \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -H "Accept: application/json" \
     -d '{"host_user_id":"HOST_USER_UUID","ssh_key_id":"SSH_KEY_UUID"}' \
     https://lockwave.io/api/v1/assignments

Cursor Pagination

All list endpoints use cursor-based pagination. Results include next_cursor and prev_cursor in the meta object. Pass ?cursor=VALUE to navigate pages. Default page size is 25 items.

Error Handling

All errors return a consistent JSON format:

{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name field is required."]
  }
}
Status Meaning
400 Bad request / malformed JSON
401 Missing or invalid token
403 Insufficient permissions
404 Resource not found
422 Validation error
429 Rate limit exceeded

Rate Limiting

The API allows 60 requests per minute per authenticated user. Rate limit status is returned in response headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57

When the limit is exceeded, a 429 Too Many Requests response is returned with a Retry-After header indicating seconds to wait.

Webhooks

Lockwave can send HTTP POST callbacks to your endpoints whenever events occur in your team. Use webhooks to integrate with your internal tooling, ChatOps pipelines, or SIEM systems.

Creating a Webhook Endpoint

Navigate to your team settings and click Webhooks. Add a new endpoint with a publicly accessible HTTPS URL. Lockwave will send a POST request with a JSON payload for each event.

Verifying Signatures

Every webhook request includes an X-Lockwave-Signature header containing an HMAC-SHA256 hash of the request body, signed with your webhook secret. Always verify this signature before processing the payload.

$signature = hash_hmac('sha256', $requestBody, $webhookSecret);
if (! hash_equals($signature, $headerSignature)) {
    abort(401);
}

Event Types

Webhooks are dispatched for the following event types:

  • key.created, key.blocked, key.unblocked, key.deleted
  • host.enrolled, host.deleted, host.drift_detected
  • assignment.created, assignment.deleted
  • break_glass.activated, break_glass.deactivated
  • team.member_added, team.member_removed

Delivery & Retries

Lockwave expects a 2xx response within 10 seconds. Failed deliveries are retried up to 5 times with exponential backoff (1 min, 5 min, 30 min, 2 hr, 24 hr). All delivery attempts are logged and visible in the webhook delivery log.

Plan Limits

Webhooks are available on all plans with different endpoint limits: Free (3), Standard (10), Business (25), Enterprise (unlimited).

Terraform Provider

The official Lockwave Terraform provider lets you manage SSH infrastructure as code. Define hosts, keys, assignments, webhook endpoints, notification channels, and audit log streams in HCL and apply them through your existing IaC pipeline.

Installation

terraform {
  required_providers {
    lockwave = {
      source  = "lockwave-io/lockwave"
      version = "~> 0.1"
    }
  }
}

provider "lockwave" {
  api_token = var.lockwave_api_token   # required, sensitive
  team_id   = var.lockwave_team_id     # required
  # api_url = "https://lockwave.io"    # optional — defaults to https://lockwave.io
}

All three arguments can also be set via environment variables: LOCKWAVE_API_TOKEN, LOCKWAVE_TEAM_ID, LOCKWAVE_API_URL.

Example Usage

# Generate an ed25519 key — private key is returned once on creation
resource "lockwave_ssh_key" "deploy" {
  name     = "deploy-key"
  mode     = "generate"
  key_type = "ed25519"
}

# Create a host
resource "lockwave_host" "web01" {
  display_name = "web-01"
  hostname     = "web-01.example.com"
  os           = "linux"
  arch         = "x86_64"
}

# Add an OS user to the host
resource "lockwave_host_user" "ubuntu" {
  host_id = lockwave_host.web01.id
  os_user = "ubuntu"
}

# Assign the key to the host user
resource "lockwave_assignment" "deploy_to_web01" {
  ssh_key_id   = lockwave_ssh_key.deploy.id
  host_user_id = lockwave_host_user.ubuntu.id
}

# Subscribe to events via webhook
resource "lockwave_webhook_endpoint" "ops" {
  url         = "https://hooks.example.com/lockwave"
  description = "Operations alerts"
  events      = ["host.synced", "ssh_key.created", "assignment.created"]
}

# Alert on Slack
resource "lockwave_notification_channel" "slack" {
  type = "slack"
  name = "Engineering alerts"
  config {
    webhook_url = var.slack_webhook_url
  }
}

# Stream audit logs to SIEM
resource "lockwave_audit_log_stream" "siem" {
  type = "webhook"
  config {
    url = "https://siem.example.com/lockwave"
  }
}

Resources

  • lockwave_host — Manage hosts (provisions a one-time daemon credential on creation)
  • lockwave_host_user — Manage OS user records on hosts (authorized_keys targets)
  • lockwave_ssh_key — Generate or import SSH keys
  • lockwave_assignment — Map keys to host users (grant access)
  • lockwave_webhook_endpoint — Manage webhook endpoints for event notifications
  • lockwave_notification_channel — Manage notification channels (Slack, email)
  • lockwave_audit_log_stream — Stream audit events to webhook or S3

Data Sources

  • lockwave_team — Fetch the current team
  • lockwave_host / lockwave_hosts — Read host details
  • lockwave_ssh_key / lockwave_ssh_keys — Read SSH key details

All resources support terraform import. The provider wraps the Lockwave REST API v1. Full documentation is available on the Terraform Registry and OpenTofu Registry.

Integrations

Lockwave integrates with the tools your team already uses for communication, automation, and compliance.

Notification Channels

Connect notification channels to receive real-time alerts for security events. Available on Standard plans and above.

  • Slack — Send alerts to a Slack channel via incoming webhook
  • Discord — Post notifications to a Discord channel via webhook
  • Microsoft Teams — Deliver alerts to a Teams channel via connector
  • Email — Send notification emails to a distribution list or individual address

Each channel supports granular event filtering so you only receive alerts for the events that matter to your team.

Audit Log Streaming

Stream your audit log to external destinations for long-term retention and SIEM integration. Available on Business plans and above.

  • Webhook delivery — Forward audit events in real time to an HTTPS endpoint
  • S3-compatible storage — Batch and deliver audit log files to an S3 bucket (AWS S3, MinIO, Cloudflare R2)

Dashboard

The Lockwave dashboard displays host sync status, daemon heartbeats, drift events, and assignment changes. Refresh the page to see the latest state from your daemons.

MCP Server

Lockwave exposes a Model Context Protocol (MCP) server so AI assistants and agents can interact with your team's data—hosts, SSH keys, assignments, break-glass, reports, and audit—using tools, resources, and prompts.

Endpoint

POST https://lockwave.io/mcp/lockwave

All MCP JSON-RPC requests (initialize, tools/list, tools/call, resources/read, prompts/get, etc.) are sent as POST to this URL.

Authentication

Use the same API token as the REST API. Send it as a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_TOKEN

Your user must have a current team set (the same team context as the REST API). All tools and resources are scoped to that team.

Capabilities

The Lockwave MCP server provides:

  • Tools — List and get hosts, SSH keys, assignments; create or delete assignments; list/activate/deactivate break-glass events; list or request compliance reports; list audit events.
  • Resources — Static docs (overview, team summary) and URI-templated resources for host and key details (lockwave://hosts/{id}, lockwave://keys/{id}).
  • Prompts — Reusable prompts to summarize the team or guide adding a key to a host.

Supported MCP clients

Add the Lockwave MCP server in any of these clients using the endpoint and Bearer token above.

Cursor Cursor
Claude Desktop Claude Desktop
Claude Code Claude Code
Gemini Gemini
OpenAI OpenAI

Client-specific setup

Cursor
  1. Open Settings (Cmd + , or Ctrl + ,) and go to Tools & MCP.
  2. Click Add new MCP server.
  3. Set Type to streamableHttp, URL to the endpoint above, and add header Authorization: Bearer YOUR_API_TOKEN.
  4. Restart Cursor for changes to take effect.
Claude (Desktop)
  1. In Claude Desktop, go to SettingsDeveloperEdit Config.
  2. Add an MCP server entry with the Lockwave endpoint URL and configure your API token (e.g. in headers or env depending on your client version).
  3. Restart Claude Desktop after saving the config.
Claude Code

Claude Code (VS Code / IDE) can use the same config file as Claude Desktop, or you can add the Lockwave server via the CLI:

  1. Open a terminal and run (--scope user saves to your user config):
claude mcp add --transport http --header "Authorization: Bearer YOUR_API_TOKEN" --scope user lockwave https://lockwave.io/mcp/lockwave
  1. Restart Claude Code, then verify with claude mcp list.

Alternatively, edit the config file directly (~/Library/Application Support/Claude/claude_desktop_config.json on macOS) and add an MCP server entry with the Lockwave URL and Authorization: Bearer YOUR_API_TOKEN in headers.

Gemini CLI
  1. From the terminal, add the Lockwave server with HTTP transport and Bearer token:
gemini mcp add --transport http --header "Authorization: Bearer YOUR_API_TOKEN" lockwave https://lockwave.io/mcp/lockwave

Or add the server in .gemini/settings.json or ~/.gemini/settings.json under mcpServers.

OpenAI (ChatGPT)
  1. Enable Developer mode in workspace settings (available on Business and Enterprise plans).
  2. Add an MCP app with the Lockwave server URL and set authentication to use your API token as a Bearer token.
  3. Only workspace admins or owners can publish MCP apps.

Protocol reference

Configure your MCP client with the URL above and add the Authorization: Bearer YOUR_TOKEN header. For protocol details, see the Model Context Protocol specification.

Security Model

Lockwave's security model is built on these principles:

  • Outbound-only — The daemon only makes outbound HTTPS requests. No inbound ports, no SSH tunnels.
  • No private keys — We only store public keys. Private keys are generated and delivered once, then discarded.
  • Atomic writes — POSIX file locking and rename prevent corrupted authorized_keys files.
  • Immutable audit — Every action is logged in an append-only log. Break-glass, drift events, and credential rotations are all recorded.
  • Optional SSH hardening — Disable password authentication at the SSH server level via a daemon-managed sshd drop-in so only key-based access is allowed.
  • Optional IP binding — Server records the registration IP, which is never automatically updated. On each sync it compares the daemon's IP and logs a mismatch event. You must manually accept a new IP from the host detail page.

Report security issues to security@lockwave.io.

Deploy in Under 5 Minutes

Start free. Run the install script on your first host and see keys sync.