sshprovision

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package sshprovision adopts a machine the operator already has (any VPS, home server, Raspberry Pi) as a node by dialing into it over SSH and installing the node agent there. This is a different feature from internal/provision (which creates a brand-new VM at a cloud provider's API and drives it through cloud-init on first boot): this package never imports that one, and duplicates the small agent systemd-unit/env-file shell snippet CloudInitParams.agentImage/RenderCloudInit render for a fresh VM, adapted to run as direct SSH commands against a machine that already exists instead of a cloud-init document a fresh VM processes on first boot.

Index

Constants

This section is empty.

Variables

View Source
var ErrHostKeyRequired = errors.New("sshprovision: a host key fingerprint is required, run the preflight and confirm the server's fingerprint")

ErrHostKeyRequired means a Provision call carried neither a pinned fingerprint nor an explicit opt out of host key verification.

Functions

func NormalizeFingerprint added in v0.2.2

func NormalizeFingerprint(fp string) (string, bool)

NormalizeFingerprint trims fp, adds a missing "SHA256:" prefix, and reports whether the result is a well-formed SHA256 fingerprint.

func PinnedHostKeyCallback added in v0.2.2

func PinnedHostKeyCallback(fp string) ssh.HostKeyCallback

PinnedHostKeyCallback accepts only a host key whose SHA256 fingerprint is fp.

Types

type AuthType

type AuthType string

AuthType selects how Credentials authenticates to the remote host.

const (
	AuthKey      AuthType = "key"
	AuthPassword AuthType = "password"
)

The two credential shapes Provision accepts, matching this feature's "SSH or VPS information" ask: a private key, or a password.

type Credentials

type Credentials struct {
	Host     string
	Port     int // 0 defaults to 22
	Username string
	Auth     AuthType
	// PrivateKey is a PEM-encoded private key, required when Auth is AuthKey.
	PrivateKey string
	// Passphrase decrypts PrivateKey when it's encrypted. Optional.
	Passphrase string
	// Password authenticates when Auth is AuthPassword.
	Password string
	// HostKeyFingerprint pins the server's host key (SHA256:...). Provision
	// refuses to send credentials to a server presenting any other key.
	HostKeyFingerprint string
	// InsecureSkipHostKeyCheck accepts any host key; the caller must warn loudly.
	InsecureSkipHostKeyCheck bool
}

Credentials dials and authenticates to one remote host for the duration of a single Provision call. The caller must discard it once Provision returns: nothing in this package persists it anywhere.

type DetectedHost

type DetectedHost struct {
	// OS is the lowercased `uname -s` output, e.g. "linux". Provision
	// fails before installing anything if this isn't "linux".
	OS string
	// Arch is "amd64" or "arm64", normalized from `uname -m`. Empty means
	// an unsupported architecture, and Provision fails before installing
	// anything.
	Arch string
	// Distro is /etc/os-release's PRETTY_NAME, best effort. "unknown" if
	// the file is missing or unreadable.
	Distro         string
	DockerPresent  bool
	SystemdPresent bool
}

DetectedHost is what Provision learns about the remote machine before it changes anything: shown to the operator so this doesn't feel like a black box.

type Event

type Event struct {
	Step    Step
	Message string
	// Err is set on the terminal event for a failed step; Provision
	// returns the same error.
	Err error
}

Event is one line of progress Provision reports through onEvent. Message is always safe to log and show to an operator: Provision never puts a credential or the join token in a Message.

type HostKey added in v0.2.2

type HostKey struct {
	// Type is the key algorithm, e.g. "ssh-ed25519" or "ssh-rsa".
	Type string
	// Fingerprint is "SHA256:" plus the unpadded base64 SHA-256 of the key.
	Fingerprint string
}

HostKey is one public host key a server presented, as ssh-keygen -l prints it.

type HostKeyMismatchError added in v0.2.2

type HostKeyMismatchError struct {
	Expected string
	Observed []HostKey
}

HostKeyMismatchError reports that no key the server presented matches the pinned fingerprint.

func (*HostKeyMismatchError) Error added in v0.2.2

func (e *HostKeyMismatchError) Error() string

type InstallParams

type InstallParams struct {
	ControlPlaneAddr string
	JoinToken        string
	CAFingerprint    string
	NodeName         string
	// AgentImage overrides defaultAgentImage (repo:tag). Empty uses the
	// default, the caller is expected to resolve a real release tag the
	// same way provision.CloudInitParams.agentImage does (internal/api
	// wires this from internal/version.Version).
	AgentImage string
	// MeshEnabled gives the agent container the TUN device and NET_ADMIN
	// its WireGuard device needs; off keeps the original unprivileged run.
	MeshEnabled bool
}

InstallParams is what the remote host needs to enroll as a node agent: the same information provision.CloudInitParams carries for a freshly created VM, minus the fields that only make sense for a cloud-init document (this package's own doc comment explains why the two aren't shared).

type Provisioner

type Provisioner struct {
	// DialTimeout bounds the initial TCP+SSH handshake. Zero uses
	// defaultDialTimeout.
	DialTimeout time.Duration
	// AgentName is the brand-derived stem for the unit, container and paths (brand.AgentName()).
	AgentName string
	// DisplayName is the brand's human name used in the unit description (brand.Name).
	DisplayName string
}

Provisioner adopts an existing machine over SSH: connects, detects its OS/arch, ensures Docker and systemd, then installs and starts the node agent as a systemd-managed container.

func New

func New(agentName, displayName string) *Provisioner

New returns a Provisioner that installs the agent under agentName, described as displayName.

func (*Provisioner) Provision

func (p *Provisioner) Provision(ctx context.Context, creds Credentials, params InstallParams, onEvent func(Event)) (DetectedHost, error)

Provision connects to creds, detects the remote host, and installs the node agent there so it enrolls with params.ControlPlaneAddr using params.JoinToken. It reports progress through onEvent (which may be nil) and returns what it detected about the host even on failure, where that's known before the failure occurred.

Provision returns once the agent's systemd unit reports active; it does not wait for the agent to actually dial the control plane and enroll; that is the caller's job to poll for separately (the same "server is up" vs. "node has enrolled" split internal/provision's own node-provision flow already draws between the provider API and the node registry).

func (*Provisioner) ScanHostKeys added in v0.2.2

func (p *Provisioner) ScanHostKeys(ctx context.Context, host string, port int) ([]HostKey, error)

ScanHostKeys connects to host:port and returns every host key the server presents, like ssh-keyscan. It never authenticates: each handshake is aborted inside the host key callback, so no username or credential is sent.

type Step

type Step string

Step is one stage of Provision, reported through onEvent as it starts, streams command output, and finishes.

const (
	StepConnect Step = "connect"
	StepDetect  Step = "detect"
	StepPrereqs Step = "prereqs"
	StepDocker  Step = "docker"
	StepAgent   Step = "agent"
	StepDone    Step = "done"
)

The stages Provision reports through onEvent, in order. Not every install reaches StepDocker's own install sub-events: DockerPresent already true skips straight past them.

Jump to

Keyboard shortcuts

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