Open-source control plane for self-hosted AI agent fleets.
Sideplane is built for solo operators, one-person companies, and small teams running agents across local PCs, LAN servers, and VPS nodes. It starts with Hermes Agent and OpenClaw and focuses on a narrow operational promise:
Know what every self-hosted agent is running, safely change its configuration, and recover when a change goes wrong.
Sideplane is early, but the first control-plane path is implemented: a Go server, Go sidecar, SQLite store, compact React UI, Docker packaging, systemd units, enrollment flow, heartbeat/status reporting, audit history, metrics, and signed config-apply jobs.
Production operators should still treat it as pre-1.0 infrastructure. Run it on low-risk nodes first, keep backups, and review the dry-run/live apply docs before enabling live writes.
- Fleet inventory with node heartbeat, freshness state, runtime summary, and drift badges.
- Operator-managed node labels with exact selector filtering for fleet views and rollouts.
- Sidecar enrollment token flow with one-time tokens exchanged for long-lived node credentials.
- Sidecar delivery resilience for short server outages: latest-wins heartbeat retry and bounded in-memory job-result retry.
- Named, revocable operator tokens for API and Web sessions.
- Hermes and OpenClaw adapters for read-only runtime discovery, runtime version visibility, deployment-mode reporting (
container/systemd/local), config hash reporting, and provider/model snapshots. - Desired configuration layering with effective config preview and read-only actual-vs-desired diffs.
- Desired config history with explicit revert.
- Signed config apply plans, dry-run by default, with live apply gated behind explicit sidecar opt-in and rollback handling.
- Staged fleet rollouts for provider/model changes across node labels or explicit node lists, canary-first by default, with overlap protection.
- Deep-probe, config-apply, restart/rollback-aware job lifecycle with paginated recent job status in the UI.
- Operator audit log with node/action filtering and deletion audit events.
- Generic and Slack-compatible alert webhooks for important fleet and rollout events.
- Node removal API and UI flow for decommissioned fleet entries.
- Conservative retention pruning for old completed/failed jobs and audit events.
- Prometheus-compatible
/metrics, including job counters and fleet freshness/drift/version gauges. - Server-sent events for live Web refresh, with polling fallback when SSE is unavailable.
- Compact infrastructure-console Web UI served directly by
sideplane-server. - Docker Compose, server and sidecar systemd units, and a Linux install script for local systemd setup.
- Server hardening with optional built-in TLS, security response headers, and structured request logging.
Sideplane is not a chat UI, prompt workspace, autonomous task board, marketplace, or generic multi-agent collaboration product.
From the repository root:
export SIDEPLANE_OPERATOR_TOKEN='replace-with-a-long-random-token'
docker compose -f deployments/docker-compose/docker-compose.yml up -d --buildOpen http://localhost:8080, enter the operator token in the sidebar, and create an enrollment token in the Enrollment view. Then enroll the compose sidecar:
docker compose -f deployments/docker-compose/docker-compose.yml exec sidecar \
sideplane-sidecar enroll --server http://server:8080 --token TOKEN --state /data/sidecar.jsonThe server container serves the embedded Web UI and exposes a /healthz
healthcheck. The sidecar starts after the server is healthy, waits quietly for
/data/sidecar.json, then begins outbound heartbeat and job polling with
env-var configuration.
Optional Prometheus and Grafana services are available through a compose override and do not change the default compose stack:
docker compose \
-f deployments/docker-compose/docker-compose.yml \
-f deployments/docker-compose/observability.override.yml \
--profile observability \
up -d --buildPrometheus scrapes server:8080/metrics and listens on
http://localhost:9090. Grafana listens on http://localhost:3001 with a
pre-provisioned Sideplane dashboard; set GRAFANA_ADMIN_PASSWORD before
starting the override if the default local password is not appropriate. The
dashboard includes fleet freshness, drift, heartbeat/job rates, active rollout
state, degraded runtime health, rollout outcomes, and alert webhook delivery
outcomes. Example Prometheus alert rules live at
deployments/observability/alert-rules.yml; copy or mount them into your
Prometheus deployment when you are ready to page on Sideplane signals.
Run the server with SQLite. By default the Go binary serves the embedded Web
assets compiled into sideplane-server:
export SIDEPLANE_OPERATOR_TOKEN='replace-with-a-long-random-token'
go run ./cmd/sideplane-server --db ./sideplane.dbRun the Web UI dev server in another terminal:
cd web
npm install
npm run devThe Vite dev server listens on http://localhost:3000 and proxies API requests to http://localhost:8080.
To override the embedded assets during local UI development, serve a built UI directory from the Go server:
npm --prefix web run build
export SIDEPLANE_OPERATOR_TOKEN='replace-with-a-long-random-token'
go run ./cmd/sideplane-server --db ./sideplane.db --web-dir ./web/distCreate an enrollment token from the UI or CLI:
go run ./cmd/sideplane enrollment create \
--server http://localhost:8080 \
--operator-token "$SIDEPLANE_OPERATOR_TOKEN"Enroll the sidecar:
go run ./cmd/sideplane-sidecar enroll \
--server http://localhost:8080 \
--token TOKEN \
--node-id worker-a \
--state ./sidecar-state.jsonStart heartbeat and job polling:
go run ./cmd/sideplane-sidecar --state ./sidecar-state.jsonThe sidecar tolerates brief server outages without silently losing the newest status: failed heartbeats are retried with latest-wins semantics, and failed job result submissions are retried from a bounded in-memory buffer. The retry buffer is intentionally not persisted across sidecar restarts.
Server flags can be configured with a flat YAML file and environment variables.
The default config file path is ~/.config/sideplane/server.yaml; override it
with SIDEPLANE_SERVER_CONFIG or sideplane-server --config PATH. To inspect
the resolved path:
sideplane-server config-file pathPrecedence is explicit CLI flags, then environment variables, then the config file, then built-in defaults. Config-file keys use the same names as server flags, for example:
addr: ":8080"
db: /var/lib/sideplane/sideplane.db
base-path: /sideplane
stale-after: 2m
offline-after: 10m
rollout-interval: 5s
backup-dir: /var/lib/sideplane/backups
backup-interval: 6h
backup-retention: 7
tls-cert: /etc/sideplane/tls/server.crt
tls-key: /etc/sideplane/tls/server.keyKeep raw secrets out of the config file. Use SIDEPLANE_OPERATOR_TOKEN for the
operator bearer token and SIDEPLANE_SIGNING_KEY or --signing-key for the
config-plan signing key file path.
| Env var | Default | Purpose |
|---|---|---|
SIDEPLANE_SERVER_CONFIG |
~/.config/sideplane/server.yaml |
Server config file path. |
SIDEPLANE_ADDR |
:8080 |
HTTP listen address. |
SIDEPLANE_DB_PATH |
sideplane.db |
SQLite database path. |
SIDEPLANE_TLS_CERT |
empty | TLS certificate file. Set together with SIDEPLANE_TLS_KEY to serve HTTPS directly. |
SIDEPLANE_TLS_KEY |
empty | TLS private key file. Set together with SIDEPLANE_TLS_CERT. |
SIDEPLANE_TLS_REDIRECT_ADDR |
empty | Optional plain-HTTP listener that sends 301 redirects to the HTTPS address. Requires cert/key. |
SIDEPLANE_BASE_PATH |
empty | Optional URL path prefix to serve Sideplane under. |
SIDEPLANE_WEB_DIR |
empty | Built Web UI directory to serve instead of embedded assets. Empty uses embedded assets. |
SIDEPLANE_OPERATOR_TOKEN |
empty | Bearer token required for mutating operator APIs. |
SIDEPLANE_SIGNING_KEY |
empty | Ed25519 config-plan signing key path. Empty uses ephemeral in-memory key. |
SIDEPLANE_BACKUP_DIR |
empty | Directory for periodic online SQLite backups. |
SIDEPLANE_BACKUP_INTERVAL |
0 |
Interval between periodic online SQLite backups. Set with backup dir to enable. |
SIDEPLANE_BACKUP_RETENTION |
7 |
Number of recent periodic DB backups to retain. |
SIDEPLANE_STALE_AFTER |
2m |
Heartbeat age before a node is stale. |
SIDEPLANE_OFFLINE_AFTER |
10m |
Heartbeat age before a node is offline. Must exceed stale duration. |
SIDEPLANE_HEARTBEAT_RETENTION |
100 |
Number of recent heartbeat records retained per node. |
SIDEPLANE_JOB_RETENTION |
720h |
Age to retain completed and failed jobs. Pending and claimed jobs are never pruned. Set 0 to disable. |
SIDEPLANE_AUDIT_RETENTION |
4320h |
Age to retain audit events. Set 0 to disable. |
SIDEPLANE_ROLLOUT_INTERVAL |
5s |
Background rollout reconciliation interval. Set 0 to disable. |
SIDEPLANE_ENROLLMENT_RATE_LIMIT |
20 |
Enrollment attempts per remote address per rate-limit window. Set 0 to disable. |
SIDEPLANE_OPERATOR_AUTH_RATE_LIMIT |
60 |
Failed operator auth attempts per remote address per rate-limit window. Set 0 to disable. |
SIDEPLANE_RATE_LIMIT_WINDOW |
1m |
Fixed window for enrollment and operator auth rate limits. |
SIDEPLANE_ALLOW_UNAUTHENTICATED_OPERATOR_API |
false | Development-only escape hatch for mutating operator APIs. |
Matching flags are available on sideplane-server: --addr, --db,
--config, --tls-cert, --tls-key, --tls-redirect-addr, --base-path,
--web-dir, --operator-token, --signing-key, --stale-after,
--offline-after, --heartbeat-retention, --job-retention,
--audit-retention, --rollout-interval, --backup-dir,
--backup-interval, --backup-retention, --enrollment-rate-limit,
--operator-auth-rate-limit, --rate-limit-window, and
--allow-unauthenticated-operator-api.
Sidecar runtime flags also support env vars. Explicit CLI flags take precedence over env vars, then values loaded from the sidecar state file.
| Env var | Purpose |
|---|---|
SIDEPLANE_SERVER_URL |
Server URL used for heartbeat, job polling, and enrollment commands. |
SIDEPLANE_NODE_ID |
Node ID override after enrollment. |
SIDEPLANE_SIDECAR_STATE |
Sidecar state file path. |
SIDEPLANE_HEARTBEAT_INTERVAL |
Heartbeat loop interval. |
SIDEPLANE_JOB_POLL_INTERVAL |
Job polling interval. |
SIDEPLANE_HERMES_CONFIG_PATHS |
Read-only Hermes config search paths. |
SIDEPLANE_OPENCLAW_CONFIG_PATHS |
Read-only OpenClaw config search paths. |
SIDEPLANE_HERMES_DOCKER_CONTAINER |
Optional Hermes Docker container for read-only status/log inspection and allowlisted restart target. |
SIDEPLANE_HERMES_SERVICE_UNIT |
Optional Hermes systemd service unit restart target. |
SIDEPLANE_SERVER_PUBLIC_KEY |
Server public key used to verify signed config plans. |
SIDEPLANE_APPLY_WORK_DIR |
Sidecar-controlled work directory for config apply dry runs and backups. |
There is intentionally no env var for --allow-live-apply or --node-credential. Live writes require an explicit flag, and node credentials are read from the state file.
Sideplane uses an external sidecar model:
Sideplane Server
- Web UI, REST API, metrics
- SQLite store
- desired configuration state
- job planner and audit log
Sideplane Sidecar
- node enrollment and heartbeat
- runtime discovery
- Hermes/OpenClaw adapters
- signed config plan verification
- backup/apply/restart/health-check/rollback path
Managed Runtimes
- Hermes Agent
- OpenClaw
Sidecars connect outbound to the server, which works for LAN, public, and private/NATed nodes without requiring inbound management ports. The sidecar is a controlled executor, not a general remote shell.
Core endpoints:
GET /healthz,GET /readyz, andGET /metrics.POST /api/enrollment-tokenscreates one-time enrollment tokens with operator auth.GET /api/operator-tokens,POST /api/operator-tokens, andDELETE /api/operator-tokens/{tokenId}manage named operator tokens.POST /api/enrollexchanges an enrollment token for a node credential.POST /api/heartbeatrecords node status with node credential auth.GET /api/nodes?selector=role=canarylists freshness-adjusted nodes with drift state and optional exact label filtering.GET /api/nodes/{nodeId}/labelsandPUT /api/nodes/{nodeId}/labelsread and replace operator-managed labels.DELETE /api/nodes/{nodeId}removes a node with operator auth and recordsnode.delete.GET /api/nodes/{nodeId}/jobs?limit=50&status=completedlists node jobs with optional boundedlimitandstatusfilters.POST /api/nodes/{nodeId}/jobscreates adeep_probejob with operator auth.POST /api/nodes/{nodeId}/config-applycreates a signed config apply job with operator auth.GET /api/nodes/{nodeId}/backupslists server-known rollback backup references.POST /api/nodes/{nodeId}/restartandPOST /api/nodes/{nodeId}/rollbackcreate allowlisted restart and explicit rollback jobs.GET /api/rollouts,POST /api/rollouts,GET /api/rollouts/{rolloutId}, andPOST /api/rollouts/{rolloutId}/actionsmanage staged rollouts, including the default overlap guard.POST /api/jobs/bulkandPUT /api/nodes/labelsperform bulk deep probes and label assignment by selector or node set.GET/POST /api/rollout-templatesandDELETE /api/rollout-templates/{templateId}manage reusable rollout templates.GET/POST /api/webhooksandDELETE /api/webhooks/{webhookId}manage generic or Slack-compatible outbound alert webhooks.GET /api/audit/export?format=ndjson|csvstreams the filtered audit log.GET/PUT /api/settingsreads and updates server settings such as expected sidecar and runtime versions.GET /api/config/desired/historylists desired config history;POST /api/config/desired/revertrestores a history entry.GET /api/audit?nodeId=...&action=...&limit=...lists audit events with additive filters.POST /api/events/ticketscreates a short-lived browser SSE ticket;GET /api/eventsstreamsnode,job, androlloutevents astext/event-stream.GET /api/sidecar/jobs/next?nodeId=...andPOST /api/sidecar/jobs/{jobId}/resultpower sidecar polling.
The full machine-readable API contract, including request and response schemas,
is published in docs/openapi.yaml and drives the generated
TypeScript client in web/src/generated/api.ts.
All operator API endpoints — both reads (fleet, audit, and configuration) and
mutations — require an operator bearer token unless the server is explicitly
started with the development-only unauthenticated operator API flag
(--allow-unauthenticated-operator-api). A readonly token is sufficient for
reads. Operator tokens carry a scope: admin (full access) or readonly
(GET/list endpoints only; mutating endpoints return 403). The env/flag
bootstrap token is always admin. The probe endpoints (/healthz, /readyz,
/metrics) and the public signing verification key (/api/signing-key) remain
reachable without a token. Enrollment and failed operator-auth attempts are rate
limited by remote address and return 429 with Retry-After when the fixed
window is exhausted.
Sideplane serves plain HTTP by default. To have sideplane-server terminate TLS
directly, set both a certificate and private key:
sideplane-server \
--addr :8443 \
--tls-cert /etc/sideplane/tls/server.crt \
--tls-key /etc/sideplane/tls/server.keyIf only one of --tls-cert or --tls-key is set, startup fails before the
database is opened. Sideplane validates that both files are readable and that
the pair can be loaded. It does not request certificates or run ACME/auto-cert.
An optional redirect listener can send plain HTTP clients to the HTTPS address:
sideplane-server \
--addr :8443 \
--tls-cert /etc/sideplane/tls/server.crt \
--tls-key /etc/sideplane/tls/server.key \
--tls-redirect-addr :8080The redirect listener only returns 301 redirects and shuts down with the main
server. It requires the TLS cert/key pair so it cannot accidentally point users
at an HTTPS endpoint the server is not serving.
Running Sideplane behind Caddy, nginx, Traefik, or another reverse proxy is also
supported: terminate TLS at the proxy and keep sideplane-server on plain HTTP
bound to localhost or a private interface. Health, readiness, metrics, REST API,
SSE, and Web UI traffic can all be proxied to the same server address.
To serve everything under a subpath (for example https://host/sideplane), set
--base-path /sideplane (or SIDEPLANE_BASE_PATH). The REST API, SSE stream, and
embedded Web UI are mounted under the prefix and the Web client discovers the base
automatically; /healthz, /readyz, and /metrics stay at the root for probes.
See docs/operations.md for base-path, node maintenance mode,
scheduled rollouts, and runtime health details.
The SQLite store can be snapshotted online while the server runs:
- On demand:
sideplane-server backup --db ./sideplane.db --out ./sideplane-backup.dbwrites a transactionally consistent copy (SQLiteVACUUM INTO) without serving HTTP. The destination must not already exist. - Scheduled: start the server with
--backup-dir <dir>and a positive--backup-interval(for example1h). Each tick writes a timestamped copy into the directory and prunes all but the most recent--backup-retentionbackups (default7). Periodic backups are off unless both are set.
To restore, stop the server, replace the database file with a backup copy, then start the server again:
sudo systemctl stop sideplane-server # or stop the container
cp ./sideplane-backup.db ./sideplane.db
sudo systemctl start sideplane-serverRestoring while the server is running is not supported; the server is the source of truth for desired state and must not be reading the file mid-swap.
Labels are operator-managed node metadata. Set them with the Web node detail
view, sideplane node label, or PUT /api/nodes/{nodeId}/labels. Selector
queries use exact comma-separated key=value matches and require every supplied
label to match.
Rollouts apply one provider/model target to nodes selected by labels or by
explicit IDs. Batches run sequentially, batchSize defaults to 1, dry-run is
the default, and live mode still requires the signed config-apply pipeline plus
sidecar --allow-live-apply. A failed, timed-out, or offline batch pauses the
rollout with failing node IDs. Opt into autoRollbackOnFailure (CLI
--auto-rollback) to roll back already-applied nodes of a failed live batch
before pausing. New rollouts are rejected with 409 when their resolved nodes
overlap another non-terminal rollout; use allowOverlap or CLI
--allow-overlap only when that concurrency is intentional. Reusable specs can
be saved as rollout templates and referenced by templateId when creating a
rollout. See
Fleet rollouts.
The Web UI uses SSE when an operator token is present. Browser clients request a
short-lived event ticket, then connect to /api/events; API clients can also
use a bearer token directly. When SSE is unavailable, the UI falls back to
bounded polling for fleet, rollout, audit, and active job state.
The sideplane CLI is a compact operator client for the REST API. Defaults
resolve in this order: explicit flag, environment variable, CLI config file,
then built-in default. The default config file is
~/.config/sideplane/config.yaml; set SIDEPLANE_CONFIG to use another path.
server: http://localhost:8080
operatorToken: replace-with-a-long-random-token
runtimeType: hermes
profile: defaultThe CLI also reads SIDEPLANE_SERVER_URL, SIDEPLANE_OPERATOR_TOKEN,
SIDEPLANE_RUNTIME_TYPE, and SIDEPLANE_PROFILE.
Generate shell completion with sideplane completion bash or
sideplane completion zsh.
| Command | Purpose | Key flags |
|---|---|---|
sideplane fleet status |
Show fleet node status. | --server, --operator-token, --selector, --json |
sideplane whoami |
Show authenticated operator scope and token name. | --server, --operator-token, --json |
sideplane status |
Show server version, uptime, schema, and fleet counts. | --server, --operator-token, --json |
sideplane probe <nodeId> |
Create a deep-probe job, or a bulk probe with --selector. |
--server, --operator-token, --selector, --wait, --json |
sideplane restart <nodeId> |
Create a dry-run or live restart job. | --server, --operator-token, --runtime-type, --profile, --live, --yes, --wait, --json |
sideplane rollback <nodeId> |
Create a dry-run or live rollback job from a backup ref. | --server, --operator-token, --backup-ref, --runtime-type, --profile, --live, --yes, --wait, --json |
sideplane jobs list <nodeId> |
List node jobs with optional filters. | --server, --operator-token, --limit, --status, --json |
sideplane audit list |
List audit events newest first. | --server, --operator-token, --node-id, --action, --limit, --json |
sideplane audit export |
Export the audit log as ndjson or csv. | --server, --operator-token, --format, --out, --node-id, --action, --limit |
sideplane token create |
Create a named operator token shown once. | --server, --operator-token, --name, --scope, --json |
sideplane token list |
List named operator token metadata. | --server, --operator-token, --json |
sideplane token revoke <id> |
Revoke a named operator token. | --server, --operator-token, --json |
sideplane rollout create |
Create a staged provider/model rollout, or use --template. |
--server, --operator-token, --template, --selector, --node, --provider, --model, --runtime-type, --profile, --batch-size, --start-at, --live, --yes, --auto-rollback, --allow-overlap, --health-timeout, --json |
sideplane rollout list |
List staged rollouts. | --server, --operator-token, --json |
sideplane rollout status <id> |
Show rollout batches and per-node progress. | --server, --operator-token, --watch, --json |
sideplane rollout pause/resume/abort <id> |
Control a rollout. | --server, --operator-token, --json |
sideplane rollout template create/list/delete |
Manage reusable rollout templates. | --server, --operator-token, --name, --json |
sideplane config preview <nodeId> |
Show effective desired config and diff. | --server, --operator-token, --runtime-type, --profile, --actual-hash, --json |
sideplane config apply <nodeId> |
Create a dry-run or live config apply job. | --server, --operator-token, --runtime-type, --profile, --config-path, --live, --yes, --wait, --json |
sideplane config get |
Show desired configuration. | --server, --operator-token, --json |
sideplane config set |
Update global desired provider/model. | --server, --operator-token, --provider, --model |
sideplane config history |
List desired config history. | --server, --operator-token, --limit, --offset, --json |
sideplane config revert <historyId> |
Revert desired configuration. | --server, --operator-token, --yes |
sideplane config-file path |
Print the resolved CLI config path. | none |
sideplane completion bash/zsh |
Print a shell completion script. | none |
sideplane node inspect <nodeId> |
Show detailed node state and runtime status. | --server, --operator-token, --json |
sideplane node label <nodeId> |
Set or remove labels, or apply in bulk with --selector. |
--server, --operator-token, --selector, --remove, --json |
sideplane node maintenance <nodeId> |
Enter or exit node maintenance mode. | --server, --operator-token, --on, --off, --json |
sideplane node remove <nodeId> |
Remove a decommissioned node record. | --server, --operator-token, --yes |
sideplane backups list <nodeId> |
List rollback backups for a node. | --server, --operator-token, --limit, --json |
sideplane enrollment create |
Create a one-time sidecar enrollment token. | --server, --operator-token, --expires-in |
sideplane webhook create/list/delete |
Manage alert webhooks. | --server, --operator-token, --url, --kind, --event, --sign, --json |
sideplane settings get/set |
Show or update server settings (expected sidecar and runtime versions). | --server, --operator-token, --expected-sidecar-version, --expected-hermes-version, --expected-openclaw-version, --json |
sideplane version |
Print CLI version. | --json |
The Web UI is intentionally a compact infrastructure console. It includes:
- Fleet overview metrics, search, label selector filtering, and sortable node columns.
- Node label editing and backup inventory discovery.
- Node job history with server-side
limitandstatusquery support. - Expandable job result rows for deep-probe and config-apply details.
- A signed config wizard with desired config history and revert controls.
- Rollout creation, batch progress, pause/resume/abort controls, and node drill-down.
- Activity history filters by node ID and action.
- Enrollment-token creation and named operator token management.
- Alert webhook management with generic/Slack kind selection.
- Live refresh over SSE with polling fallback.
- Keyboard shortcuts:
f/1opens Fleet,a/2opens Activity,e/3opens Enrollment,rrefreshes the current view, andEscreturns from a node detail view to Fleet.
/metrics exposes Prometheus text format, including HTTP request counters, job
counters, fleet freshness/drift gauges, sidecar/runtime version-outdated gauges,
runtime health, rollout state/outcome metrics, and alert webhook delivery outcomes. The optional Docker Compose
observability override adds Prometheus and Grafana with a pre-provisioned
Sideplane dashboard. The Web Fleet view mirrors the most important overview
numbers for operators who are not watching Prometheus directly.
Example alert rules are provided in
deployments/observability/alert-rules.yml for offline-node ratio,
configuration drift, degraded runtimes, paused rollouts, and webhook delivery
failures. They are examples for self-hosted deployments; review thresholds and
notification routing before enabling them.
For systemd deployment files, see deployments/systemd/. The root
install.sh creates the sideplane user/group, /etc/sideplane,
/var/lib/sideplane, and copies systemd units/env examples. Pass
--version vX.Y.Z to download release binaries from GitHub and verify them
against SHA256SUMS; pass --no-download to keep the local build-and-copy
workflow.
- Operator-token auth protects mutating operator endpoints.
- One-time enrollment tokens are stored hashed and exchanged for long-lived node credentials.
- Named operator tokens are stored hashed, listed as metadata only, and can be revoked independently.
- Enrollment attempts and failed operator auth are rate limited by remote address.
- Configuration plans are signed by the server and verified by the sidecar.
- The sidecar defaults to dry-run config apply; live apply requires explicit
--allow-live-apply. - The sidecar uses adapter-specific allowlisted operations and does not expose arbitrary shell execution.
- Provider secrets should be referenced through local env/files/SOPS/1Password/Vault-style backends, not stored inline in ordinary config.
- Server responses include
X-Content-Type-Options,X-Frame-Options,Referrer-Policy, and a restrictive Content Security Policy. CORS is not enabled by default because the server serves its own UI. - Server request logs are structured with method, path, status, duration, and remote address.
- Contributor guide
- Operations guide
- Fleet rollouts
- Signed config apply pipeline
- Operator recovery runbook
- Release runbook
- Pre-release checklist
- Live-write preflight
- Read-only sidecar deployment
- Real-machine read-only smoke test
Sideplane is licensed under the Apache License 2.0.