kvm

package module
v0.0.0-...-41ea6b9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2026 License: GPL-2.0 Imports: 83 Imported by: 0

README

JetKVM is a high-performance, open-source KVM over IP (Keyboard, Video, Mouse) solution designed for efficient remote management of computers, servers, and workstations. Whether you're dealing with boot failures, installing a new operating system, adjusting BIOS settings, or simply taking control of a machine from afar, JetKVM provides the tools to get it done effectively.

Features

  • Ultra-low Latency - 1080p@60FPS video with 30-60ms latency using H.264 encoding. Smooth mouse and keyboard interaction for responsive remote control.
  • Free & Optional Remote Access - Remote management via JetKVM Cloud using WebRTC.
  • Optional Tailscale Networking - Built-in Tailscale status and control-server configuration, including custom Headscale-compatible endpoints.
  • Open-source software - Written in Golang on Linux. Easily customizable through SSH access to the JetKVM device.

Contributing

We welcome contributions from the community! Whether it's improving the firmware, adding new features, or enhancing documentation, your input is valuable. We also have some rules and taboos here, so please read this page and our Code of Conduct carefully.

I need help

The best place to search for answers is our Documentation. If you can't find the answer there, check our Discord Server.

I want to report an issue

If you've found an issue and want to report it, please check our Issues page. Make sure the description contains information about the firmware version you're using, your platform, and a clear explanation of the steps to reproduce the issue.

Development

JetKVM is written in Go & TypeScript. with some bits and pieces written in C. An intermediate level of Go & TypeScript knowledge is recommended for comfortable programming.

The project contains two main parts, the backend software that runs on the KVM device and the frontend software that is served by the KVM device, and also the cloud.

For comprehensive development information, including setup, testing, debugging, and contribution guidelines, see DEVELOPMENT.md.

For quick device development, use the ./dev_deploy.sh script. It will build the frontend and backend and deploy them to the local KVM device. Run ./dev_deploy.sh --help for more information.

Backend

The backend is written in Go and is responsible for the KVM device management, the cloud API and the cloud web.

Frontend

The frontend is written in React and TypeScript and is served by the KVM device. It has three build targets: device, development and production. Development is used for development of the cloud version on your local machine, device is used for building the frontend for the KVM device and production is used for building the frontend for the cloud.

Documentation

Index

Constants

View Source
const (
	// CloudWebSocketConnectTimeout is the timeout for the websocket connection to the cloud
	CloudWebSocketConnectTimeout = 1 * time.Minute
	// CloudAPIRequestTimeout is the timeout for cloud API requests
	CloudAPIRequestTimeout = 10 * time.Second
	// CloudOidcRequestTimeout is the timeout for OIDC token verification requests
	// should be lower than the websocket response timeout set in cloud-api
	CloudOidcRequestTimeout = 10 * time.Second
	// WebsocketPingInterval is the interval at which the websocket client sends ping messages to the cloud
	WebsocketPingInterval = 15 * time.Second
)
View Source
const (
	MaxMacrosPerDevice = 25
	MaxStepsPerMacro   = 10
	MaxKeysPerStep     = 10
	MinStepDelay       = 50
	MaxStepDelay       = 2000
)

Constants for keyboard macro limits

View Source
const (
	DefaultAPIURL = "https://api.jetkvm.com"
)
View Source
const MaxPasswordLength = 72

MaxPasswordLength is the maximum length bcrypt can hash. Go's bcrypt implementation rejects passwords over 72 bytes rather than silently truncating them.

View Source
const MinPasswordLength = 8

MinPasswordLength is the minimum required length for new passwords. This is only enforced when setting or changing passwords, not when validating existing passwords (to maintain backward compatibility).

View Source
const (
	NetIfName = "eth0"
)
View Source
const SerialCommandHistoryPath = "/userdata/serialCommandHistory.json"

Variables

This section is empty.

Functions

func ErrorfL

func ErrorfL(l *zerolog.Logger, format string, err error, args ...any) error

func GetBuiltAppVersion

func GetBuiltAppVersion() string

GetBuiltAppVersion returns the built-in app version

func GetDefaultHostname

func GetDefaultHostname() string

func GetDeviceID

func GetDeviceID() string

func GetLocalVersion

func GetLocalVersion() (systemVersion *semver.Version, appVersion *semver.Version, err error)

GetLocalVersion returns the local version of the system and app

func GetVersionData

func GetVersionData(isJson bool) ([]byte, error)

func LoadConfig

func LoadConfig()

func Main

func Main()

func RateLimitMiddleware

func RateLimitMiddleware() gin.HandlerFunc

RateLimitMiddleware creates a Gin middleware that applies rate limiting

func RunWebSecureServer

func RunWebSecureServer()

func RunWebServer

func RunWebServer()

func RunWebsocketClient

func RunWebsocketClient()

func SaveBackupConfig

func SaveBackupConfig() error

func SaveConfig

func SaveConfig() error

Types

type ATXState

type ATXState struct {
	Power bool `json:"power"`
	HDD   bool `json:"hdd"`
}

type BacklightSettings

type BacklightSettings struct {
	MaxBrightness int `json:"max_brightness"`
	DimAfter      int `json:"dim_after"`
	OffAfter      int `json:"off_after"`
}

type ChangePasswordRequest

type ChangePasswordRequest struct {
	OldPassword string `json:"oldPassword"`
	NewPassword string `json:"newPassword"`
}

type CloudConnectionState

type CloudConnectionState uint8
const (
	CloudConnectionStateNotConfigured CloudConnectionState = iota
	CloudConnectionStateDisconnected
	CloudConnectionStateConnecting
	CloudConnectionStateConnected
)

type CloudRegisterRequest

type CloudRegisterRequest struct {
	Token      string `json:"token"`
	CloudAPI   string `json:"cloudApi"`
	OidcGoogle string `json:"oidcGoogle"`
	ClientId   string `json:"clientId"`
}

type CloudState

type CloudState struct {
	Connected bool   `json:"connected"`
	URL       string `json:"url,omitempty"`
	AppURL    string `json:"appUrl,omitempty"`
}

type Config

type Config struct {
	CloudURL             string               `json:"cloud_url"`
	UpdateAPIURL         string               `json:"update_api_url"`
	CloudAppURL          string               `json:"cloud_app_url"`
	CloudToken           string               `json:"cloud_token"`
	TailscaleControlURL  string               `json:"tailscale_control_url,omitempty"`
	GoogleIdentity       string               `json:"google_identity"`
	JigglerEnabled       bool                 `json:"jiggler_enabled"`
	JigglerConfig        *JigglerConfig       `json:"jiggler_config"`
	AutoUpdateEnabled    bool                 `json:"auto_update_enabled"`
	IncludePreRelease    bool                 `json:"include_pre_release"`
	HashedPassword       string               `json:"hashed_password"`
	LocalAuthToken       string               `json:"local_auth_token"`
	LocalAuthMode        string               `json:"localAuthMode"` //TODO: fix it with migration
	LocalLoopbackOnly    bool                 `json:"local_loopback_only"`
	WakeOnLanDevices     []WakeOnLanDevice    `json:"wake_on_lan_devices"`
	KeyboardMacros       []KeyboardMacro      `json:"keyboard_macros"`
	KeyboardLayout       string               `json:"keyboard_layout"`
	EdidString           string               `json:"hdmi_edid_string"`
	ActiveExtension      string               `json:"active_extension"`
	DisplayRotation      string               `json:"display_rotation"`
	DisplayMaxBrightness int                  `json:"display_max_brightness"`
	DisplayDimAfterSec   int                  `json:"display_dim_after_sec"`
	DisplayOffAfterSec   int                  `json:"display_off_after_sec"`
	TLSMode              string               `json:"tls_mode"` // options: "self-signed", "user-defined", ""
	UsbConfig            *usbgadget.Config    `json:"usb_config"`
	UsbDevices           *usbgadget.Devices   `json:"usb_devices"`
	NetworkConfig        *types.NetworkConfig `json:"network_config"`
	DefaultLogLevel      string               `json:"default_log_level"`
	VideoSleepAfterSec   int                  `json:"video_sleep_after_sec"`
	VideoQualityFactor   float64              `json:"video_quality_factor"`
	VideoCodecPreference string               `json:"video_codec_preference"`
	NativeMaxRestart     uint                 `json:"native_max_restart_attempts"`
	MqttConfig           *MQTTConfig          `json:"mqtt_config"`
}

func (*Config) GetDisplayRotation

func (c *Config) GetDisplayRotation() uint16

GetDisplayRotation returns the display rotation

func (*Config) GetUpdateAPIURL

func (c *Config) GetUpdateAPIURL() string

GetUpdateAPIURL returns the update API URL

func (*Config) SetDisplayRotation

func (c *Config) SetDisplayRotation(rotation string) error

SetDisplayRotation sets the display rotation

type ConsoleBroker

type ConsoleBroker struct {
	// contains filtered or unexported fields
}

func NewConsoleBroker

func NewConsoleBroker(s Sink, norm NormalizationOptions) *ConsoleBroker

func (*ConsoleBroker) Close

func (b *ConsoleBroker) Close()

func (*ConsoleBroker) Enqueue

func (b *ConsoleBroker) Enqueue(ev consoleEvent)

func (*ConsoleBroker) SetNormOptions

func (b *ConsoleBroker) SetNormOptions(norm NormalizationOptions)

func (*ConsoleBroker) SetSink

func (b *ConsoleBroker) SetSink(s Sink)

func (*ConsoleBroker) SetTerminalPaused

func (b *ConsoleBroker) SetTerminalPaused(v bool)

func (*ConsoleBroker) Start

func (b *ConsoleBroker) Start()

type DCMsg

type DCMsg struct {
	Type string          `json:"type"`           // "serial" | "system"
	Name string          `json:"name,omitempty"` // e.g. "term.size"
	Data json.RawMessage `json:"data"`           // string for "serial", object for "system"
}

type DCPowerState

type DCPowerState struct {
	IsOn         bool    `json:"isOn"`
	Voltage      float64 `json:"voltage"`
	Current      float64 `json:"current"`
	Power        float64 `json:"power"`
	RestoreState int     `json:"restoreState"`
}

type DevModeState

type DevModeState struct {
	Enabled bool `json:"enabled"`
}

type DeviceStatus

type DeviceStatus struct {
	IsSetup bool `json:"isSetup"`
}

type DisplayRotationSettings

type DisplayRotationSettings struct {
	Rotation string `json:"rotation"`
}

type FailsafeModeNotification

type FailsafeModeNotification struct {
	Active bool   `json:"active"`
	Reason string `json:"reason"`
}

type JSONRPCEvent

type JSONRPCEvent struct {
	JSONRPC string `json:"jsonrpc"`
	Method  string `json:"method"`
	Params  any    `json:"params,omitempty"`
}

type JSONRPCRequest

type JSONRPCRequest struct {
	JSONRPC string         `json:"jsonrpc"`
	Method  string         `json:"method"`
	Params  map[string]any `json:"params,omitempty"`
	ID      any            `json:"id,omitempty"`
}

type JSONRPCResponse

type JSONRPCResponse struct {
	JSONRPC string `json:"jsonrpc"`
	Result  any    `json:"result,omitempty"`
	Error   any    `json:"error,omitempty"`
	ID      any    `json:"id"`
}

type JigglerConfig

type JigglerConfig struct {
	InactivityLimitSeconds int    `json:"inactivity_limit_seconds"`
	JitterPercentage       int    `json:"jitter_percentage"`
	ScheduleCronTab        string `json:"schedule_cron_tab"`
	Timezone               string `json:"timezone,omitempty"`
}

type KeyboardMacro

type KeyboardMacro struct {
	ID        string              `json:"id"`
	Name      string              `json:"name"`
	Steps     []KeyboardMacroStep `json:"steps"`
	SortOrder int                 `json:"sortOrder,omitempty"`
}

func (*KeyboardMacro) Validate

func (m *KeyboardMacro) Validate() error

type KeyboardMacroStep

type KeyboardMacroStep struct {
	Keys      []string `json:"keys"`
	Modifiers []string `json:"modifiers"`
	Delay     int      `json:"delay"`
}

func (*KeyboardMacroStep) Validate

func (s *KeyboardMacroStep) Validate() error

type KeyboardMacrosParams

type KeyboardMacrosParams struct {
	Macros []any `json:"macros"`
}

type LineEndingMode

type LineEndingMode int
const (
	LineEnding_AsIs LineEndingMode = iota
	LineEnding_LF
	LineEnding_CR
	LineEnding_CRLF
	LineEnding_LFCR
)

type LocalDevice

type LocalDevice struct {
	AuthMode     *string `json:"authMode"`
	DeviceID     string  `json:"deviceId"`
	LoopbackOnly bool    `json:"loopbackOnly"`
}

type LoginRequest

type LoginRequest struct {
	Password string `json:"password"`
}

type MQTTConfig

type MQTTConfig struct {
	Enabled           bool   `json:"enabled"`
	Broker            string `json:"broker"`
	Port              int    `json:"port"`
	Username          string `json:"username"`
	Password          string `json:"password"`
	BaseTopic         string `json:"base_topic"`
	UseTLS            bool   `json:"use_tls"`
	TLSInsecure       bool   `json:"tls_insecure"`
	EnableHADiscovery bool   `json:"enable_ha_discovery"`
	EnableActions     bool   `json:"enable_actions"`
	DebounceMs        int    `json:"debounce_ms"`
}

type MQTTManager

type MQTTManager struct {
	// contains filtered or unexported fields
}

func NewMQTTManager

func NewMQTTManager(cfg *MQTTConfig, deviceID string) (*MQTTManager, error)

func (*MQTTManager) Close

func (m *MQTTManager) Close()

Close disconnects from the MQTT broker gracefully and stops background goroutines.

func (*MQTTManager) IsConnected

func (m *MQTTManager) IsConnected() bool

IsConnected returns the current connection state.

func (*MQTTManager) LastError

func (m *MQTTManager) LastError() string

LastError returns the last connection error, or empty string if none.

type MQTTStatusResponse

type MQTTStatusResponse struct {
	Connected bool   `json:"connected"`
	Error     string `json:"error,omitempty"`
}

type MQTTTestResult

type MQTTTestResult struct {
	Success bool   `json:"success"`
	Error   string `json:"error,omitempty"`
}

type NBDDevice

type NBDDevice struct {
	// contains filtered or unexported fields
}

func NewNBDDevice

func NewNBDDevice() *NBDDevice

func (*NBDDevice) Close

func (d *NBDDevice) Close()

func (*NBDDevice) Start

func (d *NBDDevice) Start() error

type NormalizationOptions

type NormalizationOptions struct {
	Mode         NormalizeMode
	LineEnding   LineEndingMode
	TabRender    string // e.g. "    " or "" to keep '\t'
	PreserveANSI bool
	ShowNLTag    bool // print a visible tag for CR/LF like <CR>, <LF>, <CRLF>
}

type NormalizeMode

type NormalizeMode int
const (
	ModeCaret NormalizeMode = iota // ^C ^M ^?
	ModeNames                      // <CR>, <LF>, <ESC>, …
	ModeHex                        // \x1B
)

type PostRebootAction

type PostRebootAction struct {
	HealthCheck string `json:"healthCheck"`
	RedirectTo  string `json:"redirectTo"`
}

type QuickButton

type QuickButton struct {
	Id         string     `json:"id"`         // Unique identifier
	Label      string     `json:"label"`      // Button label
	Command    string     `json:"command"`    // Command to send, raw command to send (without auto-terminator)
	Terminator Terminator `json:"terminator"` // Terminator to use: None/CR/LF/CRLF/LFCR
	Sort       int        `json:"sort"`       // Sort order
}

type RPCHandler

type RPCHandler struct {
	Func           any
	Params         []string
	OptionalParams []string
}

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter provides IP-based rate limiting for password-related endpoints

func NewRateLimiter

func NewRateLimiter() *RateLimiter

NewRateLimiter creates a new rate limiter with automatic cleanup

func (*RateLimiter) IsAllowed

func (rl *RateLimiter) IsAllowed(ip string) (bool, int)

IsAllowed checks if the IP is allowed to make an attempt. Returns (allowed, retryAfterSeconds)

func (*RateLimiter) RecordFailure

func (rl *RateLimiter) RecordFailure(ip string)

RecordFailure records a failed authentication attempt for the IP

func (*RateLimiter) RecordSuccess

func (rl *RateLimiter) RecordSuccess(ip string)

RecordSuccess clears the rate limit entry for an IP after successful auth

func (*RateLimiter) Stop

func (rl *RateLimiter) Stop()

Stop stops the cleanup goroutine

type RpcNetworkSettings

type RpcNetworkSettings struct {
	types.NetworkConfig
}

func (*RpcNetworkSettings) ToNetworkConfig

func (s *RpcNetworkSettings) ToNetworkConfig() *types.NetworkConfig

type SSHKeyState

type SSHKeyState struct {
	SSHKey string `json:"sshKey"`
}

type SerialMux

type SerialMux struct {
	// contains filtered or unexported fields
}

func NewSerialMux

func NewSerialMux(p serial.Port, broker *ConsoleBroker) *SerialMux

func (*SerialMux) Close

func (m *SerialMux) Close()

func (*SerialMux) Enqueue

func (m *SerialMux) Enqueue(payload []byte, source string, requestEcho bool, origin TXOrigin)

func (*SerialMux) SetEchoEnabled

func (m *SerialMux) SetEchoEnabled(v bool)

func (*SerialMux) Start

func (m *SerialMux) Start()

type SerialSettings

type SerialSettings struct {
	BaudRate           int           `json:"baudRate"`           // The serial port bitrate (aka Baudrate)
	DataBits           int           `json:"dataBits"`           // Size of the character (must be 5, 6, 7 or 8)
	Parity             string        `json:"parity"`             // Parity (see Parity type for more info)
	StopBits           string        `json:"stopBits"`           // Stop bits (see StopBits type for more info)
	Terminator         Terminator    `json:"terminator"`         // Terminator to send after each command
	HideSerialSettings bool          `json:"hideSerialSettings"` // Whether to hide the serial settings in the UI
	EnableEcho         bool          `json:"enableEcho"`         // Whether to echo received characters back to the sender
	NormalizeMode      string        `json:"normalizeMode"`      // Normalization mode: "carret", "names", "hex"
	NormalizeLineEnd   string        `json:"normalizeLineEnd"`   // Line ending normalization: "keep", "lf", "cr", "crlf", "lfcr"
	TabRender          string        `json:"tabRender"`          // How to render tabs: "spaces", "arrow", "pipe"
	PreserveANSI       bool          `json:"preserveANSI"`       // Whether to preserve ANSI escape codes
	ShowNLTag          bool          `json:"showNLTag"`          // Whether to show a special tag for new lines
	Buttons            []QuickButton `json:"buttons"`            // Custom quick buttons
}

Mode describes a serial port configuration.

type Session

type Session struct {
	VideoTrack     *webrtc.TrackLocalStaticSample
	ControlChannel *webrtc.DataChannel
	RPCChannel     *webrtc.DataChannel
	HidChannel     *webrtc.DataChannel
	// contains filtered or unexported fields
}

func (*Session) ExchangeOffer

func (s *Session) ExchangeOffer(offerStr string) (string, error)

func (*Session) GetDiagnosticsInfo

func (s *Session) GetDiagnosticsInfo() diagnostics.SessionInfo

GetDiagnosticsInfo returns WebRTC diagnostic info for the diagnostics package.

type SessionConfig

type SessionConfig struct {
	ICEServers []string
	LocalIP    string
	IsCloud    bool

	Logger   *zerolog.Logger
	MDNSMode string
	// contains filtered or unexported fields
}

type SetPasswordRequest

type SetPasswordRequest struct {
	Password string `json:"password"`
}

type SetWakeOnLanDevicesParams

type SetWakeOnLanDevicesParams struct {
	Devices []WakeOnLanDevice `json:"devices"`
}

type SetupRequest

type SetupRequest struct {
	LocalAuthMode string `json:"localAuthMode"`
	Password      string `json:"password,omitempty"`
}

type Sink

type Sink interface {
	SendText(s string) error
}

type StorageFile

type StorageFile struct {
	Filename  string    `json:"filename"`
	Size      int64     `json:"size"`
	CreatedAt time.Time `json:"createdAt"`
}

type StorageFileUpload

type StorageFileUpload struct {
	AlreadyUploadedBytes int64  `json:"alreadyUploadedBytes"`
	DataChannel          string `json:"dataChannel"`
}

type StorageFiles

type StorageFiles struct {
	Files []StorageFile `json:"files"`
}

type StorageSpace

type StorageSpace struct {
	BytesUsed int64 `json:"bytesUsed"`
	BytesFree int64 `json:"bytesFree"`
}

type TLSState

type TLSState struct {
	Mode        string `json:"mode"`
	Certificate string `json:"certificate"`
	PrivateKey  string `json:"privateKey"`
}

type TXOrigin

type TXOrigin int
const (
	TXUser TXOrigin = iota
	TXSystem
)

type TerminalSize

type TerminalSize struct {
	Rows int `json:"rows"`
	Cols int `json:"cols"`
}

type Terminator

type Terminator struct {
	Label string `json:"label"` // Terminator label
	Value string `json:"value"` // Terminator value
}

type UploadProgress

type UploadProgress struct {
	Size                 int64
	AlreadyUploadedBytes int64
}

type VirtualMediaMode

type VirtualMediaMode string
const (
	CDROM VirtualMediaMode = "CDROM"
	Disk  VirtualMediaMode = "Disk"
)

type VirtualMediaSource

type VirtualMediaSource string
const (
	HTTP    VirtualMediaSource = "HTTP"
	Storage VirtualMediaSource = "Storage"
)

type VirtualMediaState

type VirtualMediaState struct {
	Source   VirtualMediaSource `json:"source"`
	Mode     VirtualMediaMode   `json:"mode"`
	Filename string             `json:"filename,omitempty"`
	URL      string             `json:"url,omitempty"`
	Size     int64              `json:"size"`
}

type VirtualMediaUrlInfo

type VirtualMediaUrlInfo struct {
	Usable bool
	Reason string //only populated if Usable is false
	Size   int64
}

type WakeOnLanDevice

type WakeOnLanDevice struct {
	Name        string `json:"name"`
	MacAddress  string `json:"macAddress"`
	BroadcastIP string `json:"broadcastIP,omitempty"`
}

type WebRTCSessionRequest

type WebRTCSessionRequest struct {
	Sd         string   `json:"sd"`
	OidcGoogle string   `json:"OidcGoogle,omitempty"`
	IP         string   `json:"ip,omitempty"`
	ICEServers []string `json:"iceServers,omitempty"`
}

Directories

Path Synopsis
e2e
remote-agent module
internal
diagnostics
Package diagnostics provides comprehensive system diagnostics logging for crash analysis, debugging, and troubleshooting.
Package diagnostics provides comprehensive system diagnostics logging for crash analysis, debugging, and troubleshooting.
ota
tzdata
Code generated by "go run gen.go".
Code generated by "go run gen.go".
usbgadget
Package usbgadget provides a high-level interface to manage USB gadgets THIS PACKAGE IS FOR INTERNAL USE ONLY AND ITS API MAY CHANGE WITHOUT NOTICE
Package usbgadget provides a high-level interface to manage USB gadgets THIS PACKAGE IS FOR INTERNAL USE ONLY AND ITS API MAY CHANGE WITHOUT NOTICE
pkg
nmlite
Package nmlite provides DHCP client functionality for the network manager.
Package nmlite provides DHCP client functionality for the network manager.
nmlite/link
Package link provides a wrapper around netlink.Link and provides a singleton netlink manager.
Package link provides a wrapper around netlink.Link and provides a singleton netlink manager.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL