Documentation
¶
Overview ¶
Package vm manages virtual machines for cross-OS job execution.
ephemerd uses VMs in two scenarios:
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
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 ¶
This section is empty.
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 WindowsPathToWSL ¶
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(cfg LinuxVMConfig) (LinuxVM, error)
StartLinuxVM boots a Linux VM on macOS and waits for containerd inside it.
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 MacOSInstallOptions ¶
type MacOSInstallOptions struct {
// CustomDiskImage skips the Tart image pull entirely and uses this
// pre-existing disk image. Set via vm.macos.disk_image in config.
CustomDiskImage string
// TartImage overrides the default Tart OCI image reference.
// Default is auto-detected from the host macOS version
// (e.g. ghcr.io/cirruslabs/macos-tahoe-base:latest).
TartImage string
}
MacOSInstallOptions configures how the base image is obtained.
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(cfg MacOSVMConfig, jobID string) (MacOSVM, error)
NewMacOSVM creates a new per-job macOS VM. Call Start() to boot it.
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
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 // e.g. /var/lib/ephemerd/vm/macos
DiskImage string // base.img — the bootable macOS VM disk
AuxStorage string // aux.bin — NVRAM / auxiliary storage
MachineID string // machine-id.bin
HardwareModel string // hardware-model.bin
}
MacOSVMDiskFiles are the on-disk artifacts needed to boot macOS VMs. Pulled from a Tart OCI image (ghcr.io/cirruslabs/macos-*-base).
func EnsureMacOSVMDisk ¶
func EnsureMacOSVMDisk(ctx context.Context, dataDir string, opts MacOSInstallOptions, log *slog.Logger) (*MacOSVMDiskFiles, error)
EnsureMacOSVMDisk makes sure a bootable macOS disk image exists. If a custom disk image is configured, uses that. Otherwise pulls a pre-built Tart base image from ghcr.io. Idempotent.
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.
type RunDistroConfig ¶
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.