Jetkvm
Operate a JetKVM from swamp: health checks and Tailscale updates. The JetKVM web UI does almost everything over a WebRTC data channel, so video, USB, version and settings are not on HTTP and there is no snapshot endpoint; this model reads the unauthenticated /metrics page for the app version and NTP state, and everything else over SSH as root (developer mode, key auth, host key pinned or already known; never trust-on-first-use). health flags app and system firmware updates (via JetKVM's release API), USB gadget not enumerated, low disk, clock skew, and Tailscale down, offline, out of date or missing its boot script; with the optional tailnetIp it also fetches /metrics over the tailnet, which catches a node deleted from the tailnet that tailscaled still reports as Running. Reads and writes are separate methods: tailscale reports status or plans an update and never changes the device; tailscaleUpdate always acts, behind labeled live pre-flight checks (installed, boot script, free space, tailnet path, no swap already running). The device has no CA store, so tailscale update cannot run on it: tailscaleUpdate downloads the official arm tarball on the swamp host, checks its sha256, streams it over SSH, backs up the running binaries, swaps them in the layout tailscale configure jetkvm expects, restarts tailscaled without a reboot, and rolls back by itself unless the node rejoins Running and online with the same tailnet IP (when the old one was readable) and, with tailnetIp, answers over the tailnet from the swamp host. Every update outcome is recorded as its own update instance, so a later status run never hides a failed update.
Global Arguments
| Argument | Type | Description |
|---|---|---|
| host | string | Address of the JetKVM: a LAN IP or a hostname that resolves from wherever |
| scheme? | enum | Scheme of the web UI, used only for the unauthenticated /metrics page. |
| sshUser? | string | SSH user. JetKVM developer mode authorises keys for root. |
| sshPort? | number | |
| sshKeyFile? | string | Private key for SSH. Omit to use the ssh agent and ~/.ssh/config. |
| hostKey? | string | Pin the device's SSH host key ('ssh-ed25519 AAAA...'). Without it, the |
| timeoutMs? | number | Timeout for one HTTP request or SSH command (uploads take their own). |
| tailnetIp? | ipv4 | The JetKVM's Tailscale IPv4 address. When set, `health` checks that the |
| Argument | Type | Description |
|---|---|---|
| checkUpdates? | boolean | Ask api.jetkvm.com and pkgs.tailscale.com for the latest versions. A failure there is logged, not counted. |
| strictSecurity? | boolean | Promote developer_mode_enabled from info to warn. |
| maxClockSkewSeconds? | number | |
| minFreeDiskPercent? | number |
| Argument | Type | Description |
|---|---|---|
| action? | enum | |
| apply? | boolean | Removed in 2026.10.19.1: true is refused. Use tailscaleUpdate. |
Resources
Modified 1 behaviors
First release. health: web UI reachability and app version from /metrics, plus a read-only SSH probe for system version, USB gadget state, disk, clock and Tailscale; app/system firmware checked against api.jetkvm.com, Tailscale against pkgs.tailscale.com. tailscale: status, or update with sha256 checks on host and device, a detached swap that keeps the 'tailscale configure jetkvm' layout, a rejoin check on the same tailnet IP, automatic rollback, and an optional reboot check by kernel boot id. Dry run unless apply is true.
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented1/1earned
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit2/2earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License2/2earned
- Verified public repository2/2earned
Spawns a subprocess with Deno.Command().
- models/jetkvm.ts:182 — no reason given