Help us shape the future of Go! Take the 2026 Go Developer Survey

vm

package
v0.2.22 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package vm manages virtual machines for cross-OS job execution.

ephemerd uses VMs in two scenarios:

  1. Linux VM (long-running): On Windows and macOS hosts, a lightweight Linux VM runs containerd for Linux jobs. Same OCI images as native Linux. - Windows: Hyper-V Gen 2 VM with direct kernel boot via HCS API - macOS: Virtualization.framework Linux VM

  2. macOS VM (per-job): On macOS hosts, ephemeral macOS VMs run macOS-native jobs (Xcode, Swift, etc.). Each job gets a clone-on-write copy of a base image that is destroyed after the job completes.

Platform-specific implementations are in *_darwin.go, *_windows.go, and *_linux.go.

Index

Constants

View Source
const MacOSCloneGrace = 2 * time.Hour

MacOSCloneGrace is how long an unowned entry in jobs/ must have gone unwritten before the periodic sweep removes it. The live set is what protects running VMs; this is the second guard, for anything the live set cannot know about (a second daemon pointed at the same data dir, a clone in the instant between apfsCopy and registration). A guest writes to its .img continuously, so a live clone never looks two hours old.

Variables

This section is empty.

Functions

func GenerateEphemeralSSHKey

func GenerateEphemeralSSHKey() (ed25519.PrivateKey, string, error)

GenerateEphemeralSSHKey creates an in-memory ed25519 key pair for SSH access to macOS VMs. The private key is never written to disk — it lives only for the lifetime of this ephemerd process and rotates on restart. Returns the private key (as crypto.Signer) and the public key in authorized_keys format.

func LiveMacOSVMIDs added in v0.2.22

func LiveMacOSVMIDs() map[string]bool

LiveMacOSVMIDs returns the instance ids of every macOS VM this process still owns files for.

func ResolveMacOSDiskSize added in v0.2.22

func ResolveMacOSDiskSize(baseImage string, wantGB uint64, log *slog.Logger) uint64

ResolveMacOSDiskSize validates the configured macOS job disk size against the base image and returns the size to use, in GiB. 0 means "leave the clone exactly as big as the base image" — the default, and what is returned for any value that would not grow the disk. A shrink is never attempted: truncating below the base image would cut off the guest's filesystem.

func WindowsPathToWSL

func WindowsPathToWSL(winPath string) (string, error)

WindowsPathToWSL converts a Windows absolute path to a WSL /mnt/ path. Example: C:\Users\luthe\repo → /mnt/c/Users/luthe/repo

Types

type LinuxVM

type LinuxVM interface {
	// Client returns a containerd client connected to containerd inside the VM.
	Client() *client.Client

	// DispatchAddr returns the address of the dispatch gRPC server running
	// inside the VM (e.g. "localhost:10001"). Empty if dispatch is unavailable.
	DispatchAddr() string

	// Stop gracefully shuts down the VM.
	Stop()
}

LinuxVM is a long-running Linux VM that hosts containerd for Linux jobs. Implemented per-platform: Virtualization.framework on macOS, Hyper-V on Windows.

func StartLinuxVM

func StartLinuxVM(_ LinuxVMConfig) (LinuxVM, error)

StartLinuxVM is not needed on Linux — containerd runs directly on the host.

type LinuxVMConfig

type LinuxVMConfig struct {
	// DataDir is the ephemerd data directory. VM assets live under <DataDir>/vm/linux/.
	DataDir string

	// CPUs is the number of virtual CPUs. Defaults to 2.
	CPUs uint

	// MemoryMB is the VM memory in megabytes. Defaults to 2048.
	MemoryMB uint64

	// DiskSizeGB is the VM root disk size in gigabytes (sparse). Defaults to 50.
	DiskSizeGB uint64

	// ContainerdPort is the port containerd listens on inside the VM. Defaults to 10000.
	ContainerdPort uint32

	// DindEnabled passes --dind to the VM's ephemerd serve, mounting a fake
	// Docker socket into each container.
	DindEnabled bool

	// DindAllowPrivileged forwards the host's dind.allow_privileged setting
	// to the in-VM ephemerd via the kernel cmdline. Kept as a fallback for
	// environments where the Plan9 host-config share fails to mount (e.g.
	// stripped kernel without 9p modules); the share normally supersedes
	// this by carrying the same value through the shared config.toml.
	DindAllowPrivileged bool

	// HostDataDir is the host's ephemerd data directory. When set,
	// <HostDataDir>/config.toml is appended into the runtime-generated
	// boot-initrd tail (next to ephemerd-linux) and staged at
	// /etc/ephemerd/config.toml inside the VM, so any host-side setting
	// takes effect on the next VM boot without per-setting kernel cmdline
	// plumbing. A missing config.toml is non-fatal (fresh installs run on
	// defaults). See docs/arch/host-config-initrd.md.
	HostDataDir string

	Log *slog.Logger
}

LinuxVMConfig configures the long-running Linux VM for Linux jobs on non-Linux hosts.

func (*LinuxVMConfig) SetDefaults

func (c *LinuxVMConfig) SetDefaults()

SetDefaults applies default values for unconfigured fields.

type MacOSCloneSweep added in v0.2.22

type MacOSCloneSweep struct {
	Removed    int
	FreedBytes int64 // allocated bytes, not apparent size: a clone is sparse
	Failed     []string
}

MacOSCloneSweep is the result of one SweepStaleMacOSClones pass.

func SweepStaleMacOSClones added in v0.2.22

func SweepStaleMacOSClones(dataDir string, live map[string]bool, grace time.Duration, now time.Time, log *slog.Logger) MacOSCloneSweep

SweepStaleMacOSClones removes entries in <dataDir>/vm/macos/jobs that no VM in live owns and that have not been modified for grace. It never looks outside jobs/, so base.img, aux.bin and the rest of vm/macos are out of reach by construction. grace <= 0 with an empty live set removes everything — for `ephemerd doctor`, which only cleans with the daemon stopped.

type MacOSInstallOptions

type MacOSInstallOptions struct {
	CustomDiskImage string
	TartImage       string
}

MacOSInstallOptions is the non-darwin stub. See macos_install_darwin.go.

type MacOSVM

type MacOSVM interface {
	// WriteJITConfig writes the encoded JIT runner config to the job's shared
	// directory so the guest can pick it up on boot via virtio-fs.
	WriteJITConfig(encodedJIT string) error

	// Start boots the VM from a clone-on-write copy of the base image.
	Start(ctx context.Context) error

	// WaitForRunner blocks until the GitHub runner inside the VM is reachable.
	// Checks for a .ready sentinel file on the virtio-fs share first, then
	// falls back to SSH port 22. Returns the VM's discovered IP address.
	WaitForRunner(ctx context.Context) (string, error)

	// RunnerAddress returns the VM's discovered IP address, or empty if not yet known.
	RunnerAddress() string

	// Wait blocks until the VM exits. Returns the exit code.
	Wait(ctx context.Context) (int, error)

	// Stop forcefully stops the VM and deletes the clone.
	Stop()
}

MacOSVM is an ephemeral macOS VM for a single job. Only available on macOS hosts via Virtualization.framework.

func NewMacOSVM

func NewMacOSVM(_ MacOSVMConfig, _ string) (MacOSVM, error)

NewMacOSVM is only available on macOS hosts.

type MacOSVMConfig

type MacOSVMConfig struct {
	// DataDir is the ephemerd data directory. VM assets live under <DataDir>/vm/macos/.
	DataDir string

	// DiskImage is the path to the installed macOS disk (produced from
	// an Apple IPSW via EnsureMacOSBaseImage). Each job gets an APFS
	// clone of this file. Not to be confused with the OCI base image
	// that jobs overlay onto the VM at runtime.
	DiskImage string

	// SSHSigner is the ephemeral SSH private key for guest access.
	// Generated fresh on each ephemerd startup — never persisted to disk.
	SSHSigner interface{} // crypto.Signer (ed25519.PrivateKey)

	// SSHPubKey is the authorized_keys-format public key to inject into
	// each job's virtio-fs share. The guest picks it up on boot.
	SSHPubKey string

	// CPUs per macOS VM. Defaults to 4.
	CPUs uint

	// MemoryMB per macOS VM. Defaults to 8192.
	MemoryMB uint64

	// DiskSizeGB grows each job's disk clone to this many GiB before boot and
	// the guest's boot container with it (see macos_disk.go). 0 keeps the
	// base image's size. Pass it through ResolveMacOSDiskSize first.
	DiskSizeGB uint64

	// JobEnv is extra KEY=VALUE env for every job's runner: the cache-proxy
	// env, already rewritten to the host's address on the VM NAT. It is
	// verified reachable from inside each VM before use; see macos_proxyenv.go.
	JobEnv []string

	Log *slog.Logger
}

MacOSVMConfig configures per-job macOS VMs (macOS hosts only).

func (*MacOSVMConfig) SetDefaults

func (c *MacOSVMConfig) SetDefaults()

SetDefaults applies default values for unconfigured fields.

type MacOSVMDiskFiles

type MacOSVMDiskFiles struct {
	DataDir       string
	DiskImage     string
	AuxStorage    string
	MachineID     string
	HardwareModel string
}

MacOSVMDiskFiles is the non-darwin stub. See macos_install_darwin.go.

func EnsureMacOSVMDisk

func EnsureMacOSVMDisk(_ context.Context, _ string, _ MacOSInstallOptions, _ *slog.Logger) (*MacOSVMDiskFiles, error)

EnsureMacOSVMDisk is only implemented on darwin.

type RunDistro

type RunDistro struct {
	Name string
	// contains filtered or unexported fields
}

RunDistro tracks a single ephemerd-run WSL distro instance. Each concurrent "ephemerd run" gets its own distro with a unique name.

func NewRunDistro

func NewRunDistro(_ context.Context, _ RunDistroConfig) (*RunDistro, error)

NewRunDistro is only available on Windows.

func (*RunDistro) Destroy

func (d *RunDistro) Destroy()

Destroy is only available on Windows.

func (*RunDistro) Run

func (d *RunDistro) Run(_ context.Context, _ RunInWSLConfig) (int, error)

Run is only available on Windows.

type RunDistroConfig

type RunDistroConfig struct {
	DataDir string
	Log     *slog.Logger
}

RunDistroConfig configures the creation of a new RunDistro.

type RunInWSLConfig

type RunInWSLConfig struct {
	WorkflowPath string // absolute path to the workflow YAML
	JobFilter    string // optional --job filter
	RepoDir      string // absolute path to the repo root
}

RunInWSLConfig configures a single ephemerd run delegation to WSL.

Jump to

Keyboard shortcuts

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