deskconn

package module
v0.1.0-alpha.22153b7 Latest Latest
Warning

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

Go to latest
Published: Apr 29, 2026 License: MIT Imports: 40 Imported by: 0

README

Deskconn

Deskconn is a desktop management suite. It consists of two main tools: a desktop daemon and a command-line client.

Installation

curl -fsSL https://get.deskconn.com | sh

deskconnd

The desktop daemon responsible for registering and exposing desktop APIs to the Deskconn ecosystem. It runs in the background and enables remote management and control of the desktop.

Run
make run-deskconnd

deskconn

A command-line tool used to manage desktops. It can attach a desktop to the cloud, execute commands, transfer files, manage printers, and perform other administrative tasks.

Build
make build-deskconn
Run

Run the resulting binary to see available commands and help:

./deskconn
Supported commands

Command line interface looks like this:

usage: deskconn <command> [<args> ...]

Deskconn control CLI

Flags:
  --[no-]help  Show context-sensitive help (also try --help-long and
               --help-man).

Commands:
help [<command>...]
    Show help.


attach [<flags>]
    Attach a device

    -n, --name=NAME            Device name
    -u, --username=USERNAME    Username
    -p, --password=PASSWORD    Password
        --[no-]password-stdin  Read password from stdin

detach [<flags>]
    Detach device

    -u, --username=USERNAME    Username
    -p, --password=PASSWORD    Password
        --[no-]password-stdin  Read password from stdin

login [<flags>]
    Login and store credentials

    -u, --username=USERNAME    Username
    -p, --password=PASSWORD    Password
        --[no-]password-stdin  Read password from stdin

file pull [<flags>] <device> <remote-path> <local-path>
    Download a file or directory from a device

    -r, --[no-]recursive  Download directories recursively
        --[no-]p2p        Connect using WebRTC

file push [<flags>] <device> <local-path> <remote-path>
    Upload a file or directory to a device

    -r, --[no-]recursive  Upload directories recursively
        --[no-]p2p        Connect using WebRTC

shell [<flags>] <device>
    Start interactive shell

    --[no-]p2p  Connect using WebRTC

exec [<flags>] <device> <command>...
    Run a command

    --[no-]p2p  Connect using WebRTC

printer enable [<flags>]
    Enable receiving print jobs on this desktop

    --[no-]host-printers  Also allow remote clients to list this desktop's
                          printers

printer disable
    Disable receiving print jobs on this desktop


printer status
    Show whether this desktop accepts print jobs


printer list [<flags>] <device>
    List printers on a device

    --[no-]p2p  Connect using WebRTC

printer print --printer=PRINTER [<flags>] <device> <file_path>
    Print a local file on a device

    --printer=PRINTER  Printer name
    --[no-]p2p         Connect using WebRTC

port forward [<flags>] <device> [<ports>]
    Forward a local port to a port on the remote device

    -l, --local=LOCAL    Local port to listen on
    -r, --remote=REMOTE  Port on the remote device to connect to
        --[no-]p2p       Connect using WebRTC

ls [<flags>]
    List devices

    --[no-]refresh   Refresh device list from cloud
    --[no-]detailed  Show detailed output

whoami
    Show current user


logout
    Logout


config show
    Show config


config set <device> <key> <value>
    Set device alias


config unset <device> <key>
    Unset device alias


config edit
    Edit full config


self version
    Show the installed deskconn version


self update
    Check for updates and install the latest release

Documentation

Index

Constants

View Source
const (
	Realm                             = "io.xconn.deskconn"
	ProcedureDeskconnAttachDesktop    = "io.xconn.deskconn.desktop.attach"
	ProcedureDeskconnDetachDesktop    = "io.xconn.deskconn.desktop.detach"
	ProcedureDeskconnOrganizationList = "io.xconn.deskconn.organization.list"
	ProcedureOrganizationCreate       = "io.xconn.deskconn.organization.create"
	TopicDeskconnDesktopDetachFormat  = "io.xconn.deskconn.desktop.%s.detach"
	MachineIDPath                     = "/etc/machine-id"
)
View Source
const (
	ProcedureListKeys     = "io.xconn.deskconn.desktop.access.key.list"
	TopicKeyAddedFormat   = "io.xconn.deskconn.desktop.%s.key.add"
	TopicKeyRemovedFormat = "io.xconn.deskconn.desktop.%s.key.remove"
)
View Source
const (
	ProcedureKeyExchange         = "io.xconn.deskconn.deskconnd.key.exchange"
	ProcedureScreenBrightnessGet = "io.xconn.deskconn.deskconnd.screen.brightness.get"
	ProcedureScreenBrightnessSet = "io.xconn.deskconn.deskconnd.screen.brightness.set"
	ProcedureScreenLock          = "io.xconn.deskconn.deskconnd.screen.lock"
	ProcedureScreenIsLocked      = "io.xconn.deskconn.deskconnd.screen.islocked"
	ProcedureShell               = "io.xconn.deskconn.deskconnd.shell"
	ProcedureExec                = "io.xconn.deskconn.deskconnd.exec"
	ProcedureFileBrowse          = "io.xconn.deskconn.deskconnd.file.browse"
	ProcedurePrinterList         = "io.xconn.deskconn.deskconnd.printer.list"
	ProcedurePrinterPrint        = "io.xconn.deskconn.deskconnd.printer.print"
	ProcedureFileRename          = "io.xconn.deskconn.deskconnd.file.rename"
	ProcedureFileDelete          = "io.xconn.deskconn.deskconnd.file.delete"
	ProcedureFileCopy            = "io.xconn.deskconn.deskconnd.file.copy"

	ProcedureMPRISPlayers   = "io.xconn.deskconn.deskconnd.mpris.players"
	ProcedureMPRISPlayPause = "io.xconn.deskconn.deskconnd.mpris.playpause"
	ProcedureMPRISPlay      = "io.xconn.deskconn.deskconnd.mpris.play"
	ProcedureMPRISPause     = "io.xconn.deskconn.deskconnd.mpris.pause"
	ProcedureMPRISNext      = "io.xconn.deskconn.deskconnd.mpris.next"
	ProcedureMPRISPrevious  = "io.xconn.deskconn.deskconnd.mpris.previous"

	ErrInvalidArgument = "wamp.error.invalid_argument"
	ErrOperationFailed = "wamp.error.operation_failed"

	MetaTopicSessionLeave = "wamp.session.on_leave"
)
View Source
const (
	ProcedureWebRTCOffer     = "io.xconn.webrtc.offer"
	TopicAnswererOnCandidate = "io.xconn.webrtc.answerer.on_candidate"
	TopicOffererOnCandidate  = "io.xconn.webrtc.offerer.on_candidate"

	ProcedurePrincipalCreate = "io.xconn.deskconn.account.principal.create"
	ProcedurePrincipalDelete = "io.xconn.deskconn.account.principal.delete"
	ProcedureAccountGet      = "io.xconn.deskconn.account.get"

	ProcedureProxyShell       = "io.xconn.deskconn.deskconnd.proxy.shell"
	ProcedureProxyExec        = "io.xconn.deskconn.deskconnd.proxy.exec"
	ProcedureLogin            = "io.xconn.deskconn.login"
	ProcedureLogout           = "io.xconn.deskconn.logout"
	ProcedureConnectedDevices = "io.xconn.deskconn.connected_devices"

	ProcedureListDesktop = "io.xconn.deskconn.desktop.list"

	ProcedureAppUpdateCheck = "io.xconn.deskconn.app.update.check"

	ProcedureCoturnCreate = "io.xconn.deskconn.coturn.credentials.create"

	LocalRealm = "io.xconn.deskconn.local"
	CloudRealm = "io.xconn.deskconn"

	ErrAuthenticationFailed = "wamp.error.authentication_failed"
)
View Source
const (
	ProcedureFileDownload = "io.xconn.deskconn.deskconnd.file.download"
)
View Source
const (
	ProcedureFileUpload = "io.xconn.deskconn.deskconnd.file.upload"
)
View Source
const (
	ProcedurePortForward = "io.xconn.deskconn.deskconnd.port.forward"
)

Variables

View Source
var BacklightBasePath = "/sys/class/backlight" //nolint: gochecknoglobals

Functions

func AdvertiseService

func AdvertiseService(hostname string, port int, realm, orgID string) (*zeroconf.Server, error)

func AllZeros

func AllZeros(b []byte) bool

func Attach

func Attach(session *xconn.Session, desktopName, orgID string) error

func CfgDirectory

func CfgDirectory() (string, error)

func CloudURI

func CloudURI() string

func ConnectCloudRealm

func ConnectCloudRealm(cfgDirectory string) (*xconn.Session, error)

func ConnectDeviceRealm

func ConnectDeviceRealm(ctx context.Context, realm, cfgDirectory string, useP2P bool) (*xconn.Session, error)

func CreateX25519KeyPair

func CreateX25519KeyPair() (publicKey []byte, privateKey []byte, err error)

func CredentialsFilePath

func CredentialsFilePath() (string, error)

func DecryptChaCha20Poly1305

func DecryptChaCha20Poly1305(ciphertext, nonce, key []byte) ([]byte, error)

func DecryptPayload

func DecryptPayload(data, key []byte) ([]byte, error)

DecryptPayload decrypts a payload produced by EncryptPayload (nonce+ciphertext).

func DeriveKeyHKDF

func DeriveKeyHKDF(sharedSecret, info []byte) ([]byte, error)

func Detach

func Detach(session *xconn.Session, authID string) error

func DisablePrinting

func DisablePrinting() error

func EnablePrinterHosting

func EnablePrinterHosting() error

func EnablePrinting

func EnablePrinting() error

func EncryptChaCha20Poly1305

func EncryptChaCha20Poly1305(plaintext, key []byte) ([]byte, []byte, error)

func EncryptPayload

func EncryptPayload(plaintext, key []byte) ([]byte, error)

EncryptPayload encrypts plaintext and returns nonce+ciphertext concatenated.

func FetchTURNServers

func FetchTURNServers(session *xconn.Session) ([]xconnwebrtc.ICEServer, int64, error)

func ForwardLocalPort

func ForwardLocalPort(ctx context.Context, session *xconn.Session, remotePort, localPort string) error

func GetOrRefreshTURNServers

func GetOrRefreshTURNServers(ctx context.Context, authid, privKey, cfgDirectory string) ([]xconnwebrtc.ICEServer,
	error)

func Login

func Login(session *xconn.Session, username string) error

func PerformKeyExchange

func PerformKeyExchange(privateKey, peerPublicKey []byte) ([]byte, error)

func PrintEnableFilePath

func PrintEnableFilePath() (string, error)

func PrintingEnabled

func PrintingEnabled() (bool, error)

func ProxyProgressiveInvocationHandler

func ProxyProgressiveInvocationHandler(proxyCalls *ProxyCalls, clientSessions *ClientSessions,
	cfgDirectory, procedure string) xconn.InvocationHandler

func PullFiles

func PullFiles(session *xconn.Session, remotePath, localPath string, recursive bool) error

func PushFiles

func PushFiles(session *xconn.Session, localPath, remotePath string, recursive bool) error

func ReadCredentials

func ReadCredentials(cfgDirectory string) (string, string, error)

func RemoveCredentialsFiles

func RemoveCredentialsFiles(cfgDirectory string) error

func SetPrintMode

func SetPrintMode(mode PrintMode) error

func StartInteractiveCommand

func StartInteractiveCommand(session *xconn.Session, procedureName string, args ...string) error

func WritePrincipalsToFile

func WritePrincipalsToFile(principals []*CryptosignPrincipal) error

Types

type Authenticator

type Authenticator struct {
	sync.Mutex
	// contains filtered or unexported fields
}

func NewAuthenticator

func NewAuthenticator(principals []*CryptosignPrincipal) *Authenticator

func (*Authenticator) Authenticate

func (a *Authenticator) Authenticate(request auth.Request) (auth.Response, error)

func (*Authenticator) Methods

func (a *Authenticator) Methods() []auth.Method

func (*Authenticator) RetrievePrincipal

func (a *Authenticator) RetrievePrincipal(authid string) (*CryptosignPrincipal, bool)

func (*Authenticator) SetPrincipal

func (a *Authenticator) SetPrincipal(authid string, principal *CryptosignPrincipal)

func (*Authenticator) SetPrincipals

func (a *Authenticator) SetPrincipals(principals []*CryptosignPrincipal)

func (*Authenticator) SubscribeEvents

func (a *Authenticator) SubscribeEvents(session *xconn.Session, machineID string) error

type ClientSessions

type ClientSessions struct {
	sync.Mutex
	// contains filtered or unexported fields
}

func NewClientSessions

func NewClientSessions() *ClientSessions

func (*ClientSessions) DeleteDeviceSession

func (c *ClientSessions) DeleteDeviceSession(realm string)

func (*ClientSessions) DeviceSessions

func (c *ClientSessions) DeviceSessions() map[string]*xconn.Session

func (*ClientSessions) EnsureDeviceSession

func (c *ClientSessions) EnsureDeviceSession(ctx context.Context, realm, cfgDirectory string) (*xconn.Session, error)

func (*ClientSessions) LoggedIn

func (c *ClientSessions) LoggedIn() bool

func (*ClientSessions) Login

func (c *ClientSessions) Login()

func (*ClientSessions) Logout

func (c *ClientSessions) Logout()

func (*ClientSessions) SessionByRealm

func (c *ClientSessions) SessionByRealm(authid string) (*xconn.Session, bool)

func (*ClientSessions) StoreDeviceSession

func (c *ClientSessions) StoreDeviceSession(realm string, session *xconn.Session)

type Config

type Config struct {
	Devices []Device `yaml:"devices"`
}

type Credentials

type Credentials struct {
	Realm          string `json:"realm"`
	AuthID         string `json:"authid"`
	PublicKey      string `json:"public_key"`
	PrivateKey     string `json:"private_key"` // #nosec
	OrganizationID string `json:"organization_id"`
}

func EnsureCredentials

func EnsureCredentials() (*Credentials, error)

type CryptosignPrincipal

type CryptosignPrincipal struct {
	AuthID         string   `json:"authid"`
	AuthorizedKeys []string `json:"authorized_keys"`
	AuthRole       string   `json:"authrole"`
}

func ReadPrincipalsFromFile

func ReadPrincipalsFromFile() ([]*CryptosignPrincipal, error)

type Deskconn

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

func NewDeskconn

func NewDeskconn(screen *Screen, mpris *MPRIS) *Deskconn

func (*Deskconn) Register

func (d *Deskconn) Register(session *xconn.Session) error

type Device

type Device struct {
	Authid       string       `json:"authid" yaml:"authid"`
	ID           string       `json:"id" yaml:"id"`
	Name         string       `json:"name" yaml:"name"`
	Organization Organization `json:"organization" yaml:"organization"`
	Realm        string       `json:"realm" yaml:"realm"`
	Alias        string       `yaml:"alias"`
	Connected    bool         `yaml:"-" json:"-"`
}

func DevicesFromCfg

func DevicesFromCfg(cfgDirectory string) ([]Device, error)

func FetchDevicesFromCloud

func FetchDevicesFromCloud(cfgDirectory string) ([]Device, error)

type FileBrowseResult

type FileBrowseResult struct {
	Path       string      `json:"path"`
	HomePath   string      `json:"home_path"`
	ParentPath string      `json:"parent_path,omitempty"`
	Type       string      `json:"type"`
	Mode       string      `json:"mode"`
	Size       int64       `json:"size"`
	ModTime    time.Time   `json:"mod_time"`
	IsDir      bool        `json:"is_dir"`
	IsSymlink  bool        `json:"is_symlink"`
	LinkTarget string      `json:"link_target,omitempty"`
	Entries    []FileEntry `json:"entries,omitempty"`
}

type FileBrowser

type FileBrowser struct{}

func NewFileBrowser

func NewFileBrowser() *FileBrowser

func (*FileBrowser) Browse

func (f *FileBrowser) Browse(pathArg string) (*FileBrowseResult, error)

func (*FileBrowser) Copy

func (f *FileBrowser) Copy(srcPath, dstPath string) error

func (*FileBrowser) Delete

func (f *FileBrowser) Delete(path string) error

func (*FileBrowser) Rename

func (f *FileBrowser) Rename(oldPath, newPath string) error

type FileEntry

type FileEntry struct {
	Name       string    `json:"name"`
	Path       string    `json:"path"`
	Type       string    `json:"type"`
	Mode       string    `json:"mode"`
	Size       int64     `json:"size"`
	Hidden     bool      `json:"hidden"`
	ModTime    time.Time `json:"mod_time"`
	IsDir      bool      `json:"is_dir"`
	IsSymlink  bool      `json:"is_symlink"`
	LinkTarget string    `json:"link_target,omitempty"`
}

type MPRIS

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

func NewMPRIS

func NewMPRIS(conn *dbus.Conn) *MPRIS

func (*MPRIS) ListPlayers

func (m *MPRIS) ListPlayers() (map[string]string, error)

func (*MPRIS) Next

func (m *MPRIS) Next() error

func (*MPRIS) NextPlayer

func (m *MPRIS) NextPlayer(name string) error

func (*MPRIS) Pause

func (m *MPRIS) Pause() error

func (*MPRIS) PausePlayer

func (m *MPRIS) PausePlayer(name string) error

func (*MPRIS) Play

func (m *MPRIS) Play() error

func (*MPRIS) PlayPause

func (m *MPRIS) PlayPause() error

func (*MPRIS) PlayPausePlayer

func (m *MPRIS) PlayPausePlayer(name string) error

func (*MPRIS) PlayPlayer

func (m *MPRIS) PlayPlayer(name string) error

func (*MPRIS) Previous

func (m *MPRIS) Previous() error

func (*MPRIS) PreviousPlayer

func (m *MPRIS) PreviousPlayer(name string) error

type Organization

type Organization struct {
	ID   string `json:"id" yaml:"id"`
	Name string `json:"name" yaml:"name"`
}

type PrintJobStatus

type PrintJobStatus struct {
	JobID     string `json:"job_id"`
	Printer   string `json:"printer"`
	State     string `json:"state"`
	Message   string `json:"message,omitempty"`
	CreatedAt int64  `json:"created_at"`
}

type PrintMode

type PrintMode string
const (
	PrintModeDisabled PrintMode = "disabled"
	PrintModeAccept   PrintMode = "accept"
	PrintModeHost     PrintMode = "host"
)

func CurrentPrintMode

func CurrentPrintMode() (PrintMode, error)

type Printer

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

func NewPrinter

func NewPrinter() *Printer

func (*Printer) ExecutePrint

func (p *Printer) ExecutePrint(ctx context.Context, printer string, filename string, data []byte) error

type PrinterInfo

type PrinterInfo struct {
	Name     string `json:"name"`
	PPDModel string `json:"ppd"`
}

type ProxyCall

type ProxyCall struct {
	ProgressChan chan *xconn.Progress
}

type ProxyCalls

type ProxyCalls struct {
	sync.Mutex
	// contains filtered or unexported fields
}

func NewProxyCalls

func NewProxyCalls() *ProxyCalls

func (*ProxyCalls) Delete

func (p *ProxyCalls) Delete(id uint64)

func (*ProxyCalls) Get

func (p *ProxyCalls) Get(id uint64) (*ProxyCall, bool)

func (*ProxyCalls) Store

func (p *ProxyCalls) Store(id uint64, c *ProxyCall)

type Screen

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

func NewScreen

func NewScreen(sessionBus, systemBus *dbus.Conn) *Screen

func (*Screen) GetBrightness

func (s *Screen) GetBrightness() (int, error)

func (*Screen) IsLocked

func (s *Screen) IsLocked() (bool, error)

func (*Screen) Lock

func (s *Screen) Lock() error

func (*Screen) SetBrightness

func (s *Screen) SetBrightness(percent int) error

type TURNCredentials

type TURNCredentials struct {
	ExpiresAt  int64    `json:"expires_at"`
	Username   string   `json:"username"`
	Credential string   `json:"credential"`
	URLs       []string `json:"urls"`
}

Directories

Path Synopsis
cmd
deskconn command
deskconnd command

Jump to

Keyboard shortcuts

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