diff --git a/.claude/rules/adding-options.md b/.claude/rules/adding-options.md
index 9021097..4198bca 100644
--- a/.claude/rules/adding-options.md
+++ b/.claude/rules/adding-options.md
@@ -1,9 +1,9 @@
---
paths:
- "options.go"
- - "propolis.go"
+ - "microvm.go"
- "runner/config.go"
- - "runner/cmd/propolis-runner/main.go"
+ - "runner/cmd/go-microvm-runner/main.go"
---
# Adding a New Option
@@ -11,5 +11,5 @@ paths:
1. Add the field to the `config` struct in `options.go`
2. Set the default in `defaultConfig()` if needed
3. Create a `With*` constructor following the existing pattern in `options.go`
-4. Use the field in `propolis.go` (in `Run()`) where appropriate
-5. If the option affects the runner, add the field to BOTH `runner.Config` in `runner/config.go` AND the runner's duplicate `Config` struct in `runner/cmd/propolis-runner/main.go` with the same JSON tag
+4. Use the field in `microvm.go` (in `Run()`) where appropriate
+5. If the option affects the runner, add the field to BOTH `runner.Config` in `runner/config.go` AND the runner's duplicate `Config` struct in `runner/cmd/go-microvm-runner/main.go` with the same JSON tag
diff --git a/.claude/rules/preflight-and-hooks.md b/.claude/rules/preflight-and-hooks.md
index ee69fe8..df28285 100644
--- a/.claude/rules/preflight-and-hooks.md
+++ b/.claude/rules/preflight-and-hooks.md
@@ -10,7 +10,7 @@ paths:
- Create a function returning `preflight.Check` with Name, Description, Run, and Required fields
- See existing checks in `preflight/kvm_linux.go` and `preflight/ports.go` for patterns
- Platform-specific checks go in build-tagged files (`//go:build linux` or `//go:build darwin`)
-- Register via `propolis.WithPreflightChecks()` or add to `registerPlatformChecks()` for defaults
+- Register via `microvm.WithPreflightChecks()` or add to `registerPlatformChecks()` for defaults
## Adding a Network Provider
- Implement the `net.Provider` interface (Start, SocketPath, Stop)
@@ -22,4 +22,4 @@ paths:
- Type: `func(rootfsPath string, cfg *image.OCIConfig) error`
- Run before `.krun_config.json` is written and before VM boot
- Multiple hooks run in registration order; any error aborts the pipeline
-- Register via `propolis.WithRootFSHook()`
+- Register via `microvm.WithRootFSHook()`
diff --git a/.github/workflows/builder.yaml b/.github/workflows/builder.yaml
index 5459331..d4b6d77 100644
--- a/.github/workflows/builder.yaml
+++ b/.github/workflows/builder.yaml
@@ -20,7 +20,7 @@ permissions:
env:
REGISTRY: ghcr.io
- IMAGE_NAME: stacklok/propolis-builder
+ IMAGE_NAME: stacklok/go-microvm-builder
jobs:
build:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index d5ff8f1..b5ce96f 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -52,14 +52,14 @@ jobs:
- name: Upload runtime artifact
uses: actions/upload-artifact@v7
with:
- name: propolis-runtime-linux-${{ matrix.arch }}
- path: dist/propolis-runtime-linux-${{ matrix.arch }}.tar.gz
+ name: go-microvm-runtime-linux-${{ matrix.arch }}
+ path: dist/go-microvm-runtime-linux-${{ matrix.arch }}.tar.gz
- name: Upload firmware artifact
uses: actions/upload-artifact@v7
with:
- name: propolis-firmware-linux-${{ matrix.arch }}
- path: dist/propolis-firmware-linux-${{ matrix.arch }}.tar.gz
+ name: go-microvm-firmware-linux-${{ matrix.arch }}
+ path: dist/go-microvm-firmware-linux-${{ matrix.arch }}.tar.gz
build-artifacts-darwin:
name: Build macOS (${{ matrix.arch }})
@@ -101,14 +101,14 @@ jobs:
- name: Upload runtime artifact
uses: actions/upload-artifact@v7
with:
- name: propolis-runtime-darwin-${{ matrix.arch }}
- path: dist/propolis-runtime-darwin-${{ matrix.arch }}.tar.gz
+ name: go-microvm-runtime-darwin-${{ matrix.arch }}
+ path: dist/go-microvm-runtime-darwin-${{ matrix.arch }}.tar.gz
- name: Upload firmware artifact
uses: actions/upload-artifact@v7
with:
- name: propolis-firmware-darwin-${{ matrix.arch }}
- path: dist/propolis-firmware-darwin-${{ matrix.arch }}.tar.gz
+ name: go-microvm-firmware-darwin-${{ matrix.arch }}
+ path: dist/go-microvm-firmware-darwin-${{ matrix.arch }}.tar.gz
create-release:
name: Create Release
@@ -126,7 +126,7 @@ jobs:
- name: Generate checksums
run: |
- sha256sum propolis-*.tar.gz > sha256sums.txt
+ sha256sum go-microvm-*.tar.gz > sha256sums.txt
- name: Create or update GitHub Release
env:
@@ -134,10 +134,10 @@ jobs:
run: |
if gh release view "${{ github.ref_name }}" >/dev/null 2>&1; then
gh release upload "${{ github.ref_name }}" --clobber \
- propolis-*.tar.gz sha256sums.txt
+ go-microvm-*.tar.gz sha256sums.txt
else
gh release create "${{ github.ref_name }}" --generate-notes \
- propolis-*.tar.gz sha256sums.txt
+ go-microvm-*.tar.gz sha256sums.txt
fi
push-oci:
@@ -153,12 +153,12 @@ jobs:
- name: Download runtime artifact
uses: actions/download-artifact@v8
with:
- name: propolis-runtime-linux-${{ matrix.arch }}
+ name: go-microvm-runtime-linux-${{ matrix.arch }}
- name: Download firmware artifact
uses: actions/download-artifact@v8
with:
- name: propolis-firmware-linux-${{ matrix.arch }}
+ name: go-microvm-firmware-linux-${{ matrix.arch }}
- name: Install oras
uses: oras-project/setup-oras@v1
@@ -169,15 +169,15 @@ jobs:
- name: Push runtime OCI artifact
run: |
- oras push ghcr.io/stacklok/propolis/runtime:${{ github.ref_name }}-linux-${{ matrix.arch }} \
- --artifact-type application/vnd.stacklok.propolis.runtime \
- propolis-runtime-linux-${{ matrix.arch }}.tar.gz:application/gzip
+ oras push ghcr.io/stacklok/go-microvm/runtime:${{ github.ref_name }}-linux-${{ matrix.arch }} \
+ --artifact-type application/vnd.stacklok.go-microvm.runtime \
+ go-microvm-runtime-linux-${{ matrix.arch }}.tar.gz:application/gzip
- name: Push firmware OCI artifact
run: |
- oras push ghcr.io/stacklok/propolis/firmware:${{ github.ref_name }}-linux-${{ matrix.arch }} \
- --artifact-type application/vnd.stacklok.propolis.firmware \
- propolis-firmware-linux-${{ matrix.arch }}.tar.gz:application/gzip
+ oras push ghcr.io/stacklok/go-microvm/firmware:${{ github.ref_name }}-linux-${{ matrix.arch }} \
+ --artifact-type application/vnd.stacklok.go-microvm.firmware \
+ go-microvm-firmware-linux-${{ matrix.arch }}.tar.gz:application/gzip
push-oci-darwin:
name: Push OCI macOS (${{ matrix.arch }})
@@ -191,12 +191,12 @@ jobs:
- name: Download runtime artifact
uses: actions/download-artifact@v8
with:
- name: propolis-runtime-darwin-${{ matrix.arch }}
+ name: go-microvm-runtime-darwin-${{ matrix.arch }}
- name: Download firmware artifact
uses: actions/download-artifact@v8
with:
- name: propolis-firmware-darwin-${{ matrix.arch }}
+ name: go-microvm-firmware-darwin-${{ matrix.arch }}
- name: Install oras
uses: oras-project/setup-oras@v1
@@ -207,12 +207,12 @@ jobs:
- name: Push runtime OCI artifact
run: |
- oras push ghcr.io/stacklok/propolis/runtime:${{ github.ref_name }}-darwin-${{ matrix.arch }} \
- --artifact-type application/vnd.stacklok.propolis.runtime \
- propolis-runtime-darwin-${{ matrix.arch }}.tar.gz:application/gzip
+ oras push ghcr.io/stacklok/go-microvm/runtime:${{ github.ref_name }}-darwin-${{ matrix.arch }} \
+ --artifact-type application/vnd.stacklok.go-microvm.runtime \
+ go-microvm-runtime-darwin-${{ matrix.arch }}.tar.gz:application/gzip
- name: Push firmware OCI artifact
run: |
- oras push ghcr.io/stacklok/propolis/firmware:${{ github.ref_name }}-darwin-${{ matrix.arch }} \
- --artifact-type application/vnd.stacklok.propolis.firmware \
- propolis-firmware-darwin-${{ matrix.arch }}.tar.gz:application/gzip
+ oras push ghcr.io/stacklok/go-microvm/firmware:${{ github.ref_name }}-darwin-${{ matrix.arch }} \
+ --artifact-type application/vnd.stacklok.go-microvm.firmware \
+ go-microvm-firmware-darwin-${{ matrix.arch }}.tar.gz:application/gzip
diff --git a/CLAUDE.md b/CLAUDE.md
index e6702ee..612eec7 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,7 +1,7 @@
-# propolis
+# go-microvm
Go library + runner binary for running OCI container images as microVMs via libkrun.
-Two-process model: pure-Go library spawns a CGO runner subprocess. Module: `github.com/stacklok/propolis`.
+Two-process model: pure-Go library spawns a CGO runner subprocess. Module: `github.com/stacklok/go-microvm`.
## Commands
@@ -31,23 +31,23 @@ macOS dev setup: `brew tap slp/krun && brew install libkrun libkrunfw` (see `doc
## Architecture
-Entry point: `propolis.go:Run()` orchestrates the full pipeline (preflight, pull, hooks, config, net, spawn, post-boot). Config via functional options in `options.go`. Returns a `*VM` handle (`vm.go`).
+Entry point: `microvm.go:Run()` orchestrates the full pipeline (preflight, pull, hooks, config, net, spawn, post-boot). Config via functional options in `options.go`. Returns a `*VM` handle (`vm.go`).
-**CGO boundary**: Only `krun/` and `runner/cmd/propolis-runner/` use CGO. Everything else is pure Go. The runner binary is sacrificial -- `krun_start_enter()` never returns, so it runs in a detached subprocess.
+**CGO boundary**: Only `krun/` and `runner/cmd/go-microvm-runner/` use CGO. Everything else is pure Go. The runner binary is sacrificial -- `krun_start_enter()` never returns, so it runs in a detached subprocess.
**Key subsystems**: `hypervisor/` (Backend abstraction + libkrun impl), `image/` (OCI pull + cache), `runner/` (subprocess spawning), `net/` (Provider interface + firewall + hosted mode + egress policy + topology constants), `guest/` (guest-side boot orchestration, hardening, SSH server), `hooks/` (RootFS hook factories for key injection, file injection), `extract/` (binary bundle caching), `preflight/` (platform checks via build tags), `ssh/` (keygen + client), `state/` (flock-based JSON persistence), `internal/` (pathutil, procutil).
## Things That Will Bite You
-- **CGO boundary is strict**: Only `krun/` and `runner/cmd/propolis-runner/` use CGO. Every other package MUST stay `CGO_ENABLED=0`. Never import `krun` from a non-CGO package.
-- **Runner config is duplicated**: `runner.Config` in `runner/config.go` and a duplicate `Config` struct in `runner/cmd/propolis-runner/main.go`. When adding a field, update BOTH structs with the same JSON tag, then handle it in `runVM()`.
+- **CGO boundary is strict**: Only `krun/` and `runner/cmd/go-microvm-runner/` use CGO. Every other package MUST stay `CGO_ENABLED=0`. Never import `krun` from a non-CGO package.
+- **Runner config is duplicated**: `runner.Config` in `runner/config.go` and a duplicate `Config` struct in `runner/cmd/go-microvm-runner/main.go`. When adding a field, update BOTH structs with the same JSON tag, then handle it in `runVM()`.
- **`krun_start_enter()` never returns**: It calls `exit()` when the guest shuts down. That's why we need the two-process model -- the runner process is sacrificial.
- **Platform build tags**: Preflight checks, resource checks, and some net code use `//go:build linux` or `//go:build darwin`. Each platform goes in a separate file. macOS preflight checks verify `kern.hv_support` sysctl and use `hw.memsize`/`syscall.Statfs` for resources.
- **Entitlements required on macOS**: `assets/entitlements.plist` has three entitlements: `com.apple.security.hypervisor`, `com.apple.security.cs.disable-library-validation`, and `com.apple.security.cs.allow-dyld-environment-variables` (needed because the hypervisor entitlement activates hardened runtime, which strips DYLD_* vars). The `task build-dev-darwin` command signs automatically.
- **CGO Homebrew paths**: `krun/context.go` CGO directives include `-L/opt/homebrew/lib` and `-L/usr/local/lib` for macOS. The linker ignores nonexistent paths.
-- **Tests excluding CGO packages**: When CGO isn't available, exclude krun: `CGO_ENABLED=0 go test $(go list ./... | grep -v krun | grep -v propolis-runner)`
+- **Tests excluding CGO packages**: When CGO isn't available, exclude krun: `CGO_ENABLED=0 go test $(go list ./... | grep -v krun | grep -v go-microvm-runner)`
- **Functional options pattern**: All public config uses `With*` constructors applying to unexported `config` struct via `optionFunc`. Follow the existing pattern in `options.go` exactly.
-- **Backend abstraction**: `WithRunnerPath`, `WithLibDir`, and `WithSpawner` are NOT on the top-level `propolis` package. They live in `hypervisor/libkrun` as backend-specific options. Use `propolis.WithBackend(libkrun.NewBackend(libkrun.WithRunnerPath(...)))`. Similarly, `VM.PID()` is gone; use `VM.ID()` (returns string).
+- **Backend abstraction**: `WithRunnerPath`, `WithLibDir`, and `WithSpawner` are NOT on the top-level `microvm` package. They live in `hypervisor/libkrun` as backend-specific options. Use `microvm.WithBackend(libkrun.NewBackend(libkrun.WithRunnerPath(...)))`. Similarly, `VM.PID()` is gone; use `VM.ID()` (returns string).
## Conventions
@@ -72,7 +72,7 @@ task test # Full test suite with race detector
After modifying CGO-free packages only:
```bash
-CGO_ENABLED=0 go vet $(go list ./... | grep -v krun | grep -v propolis-runner)
+CGO_ENABLED=0 go vet $(go list ./... | grep -v krun | grep -v go-microvm-runner)
```
When tests fail, fix the implementation, not the tests.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b864100..0e28fc1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-# Contributing to propolis
+# Contributing to go-microvm
## Prerequisites
@@ -60,7 +60,7 @@ Run `task --list` for the full list. Key tasks for development:
- **Error wrapping**: `fmt.Errorf("context: %w", err)`
- **Table-driven tests** with testify
- **Functional options**: follow the `With*` pattern in `options.go`
-- **CGO boundary**: only `krun/` and `runner/cmd/propolis-runner/` use CGO.
+- **CGO boundary**: only `krun/` and `runner/cmd/go-microvm-runner/` use CGO.
Never import `krun` from other packages.
## Commit Guidelines
diff --git a/README.md b/README.md
index 7f2361b..7ecd187 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,15 @@
-

+

-
propolis
+
go-microvm
Run OCI container images as microVMs with libkrun.
-
-
+
+
-
+
@@ -22,19 +22,19 @@
> [!WARNING]
-> **Experimental** -- propolis is under active development. APIs, configuration
+> **Experimental** -- go-microvm is under active development. APIs, configuration
> formats, and behavior may change without notice between releases. It is not
> yet recommended for production use.
---
-propolis is a Go library and runner binary that turns any OCI container image
+go-microvm is a Go library and runner binary that turns any OCI container image
into a lightweight virtual machine. It pulls the image, flattens its layers
into a rootfs, configures in-process networking, and boots the result using
[libkrun](https://github.com/containers/libkrun) -- all in a single function
call.
-You would use propolis when you need stronger isolation than containers provide
+You would use go-microvm when you need stronger isolation than containers provide
but want to keep the OCI image workflow you already have. The library handles
image caching, preflight validation, port forwarding, virtio-fs mounts, and
process lifecycle so you can focus on what runs inside the VM.
@@ -54,7 +54,7 @@ process lifecycle so you can focus on what runs inside the VM.
## Prerequisites
-propolis requires hardware virtualization support and a few system packages.
+go-microvm requires hardware virtualization support and a few system packages.
### Linux -- Fedora
@@ -122,8 +122,8 @@ sudo modprobe kvm kvm_amd # AMD CPUs
### Go Toolchain
-propolis requires **Go 1.26** or later. The library packages (everything
-except `krun` and `propolis-runner`) do not require CGO and compile with
+go-microvm requires **Go 1.26** or later. The library packages (everything
+except `krun` and `go-microvm-runner`) do not require CGO and compile with
`CGO_ENABLED=0`. The runner binary requires `CGO_ENABLED=1` and `libkrun-devel`.
## Quick Start
@@ -135,14 +135,14 @@ import (
"context"
"log"
- "github.com/stacklok/propolis"
+ "github.com/stacklok/go-microvm"
)
func main() {
ctx := context.Background()
- vm, err := propolis.Run(ctx, "alpine:latest",
- propolis.WithPorts(propolis.PortForward{Host: 8080, Guest: 80}),
+ vm, err := microvm.Run(ctx, "alpine:latest",
+ microvm.WithPorts(microvm.PortForward{Host: 8080, Guest: 80}),
)
if err != nil {
log.Fatal(err)
@@ -158,14 +158,14 @@ func main() {
}
```
-`propolis.Run` executes the full pipeline: preflight checks, OCI image pull,
+`microvm.Run` executes the full pipeline: preflight checks, OCI image pull,
layer extraction, rootfs caching, networking setup, subprocess spawn, and
post-boot hooks. It returns a `*VM` handle that you use to query status, stop,
or remove the VM.
## Advanced Usage
-For appliance-style deployments, propolis exposes hooks and overrides at every
+For appliance-style deployments, go-microvm exposes hooks and overrides at every
stage of the pipeline:
```go
@@ -176,41 +176,41 @@ import (
"os"
"path/filepath"
- "github.com/stacklok/propolis"
- "github.com/stacklok/propolis/hypervisor/libkrun"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/preflight"
- "github.com/stacklok/propolis/ssh"
+ "github.com/stacklok/go-microvm"
+ "github.com/stacklok/go-microvm/hypervisor/libkrun"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/preflight"
+ "github.com/stacklok/go-microvm/ssh"
)
func main() {
ctx := context.Background()
- vm, err := propolis.Run(ctx, "my-appliance:latest",
- // Name the VM (defaults to "propolis").
- propolis.WithName("my-appliance"),
+ vm, err := microvm.Run(ctx, "my-appliance:latest",
+ // Name the VM (defaults to "go-microvm").
+ microvm.WithName("my-appliance"),
// Configure VM resources.
// vCPUs default to 1, memory defaults to 512 MiB.
// Stock libkrunfw caps vCPUs at 8.
- propolis.WithCPUs(4),
- propolis.WithMemory(2048),
+ microvm.WithCPUs(4),
+ microvm.WithMemory(2048),
// Port forwards from host to guest.
- propolis.WithPorts(
- propolis.PortForward{Host: 443, Guest: 443},
- propolis.PortForward{Host: 2222, Guest: 22},
+ microvm.WithPorts(
+ microvm.PortForward{Host: 443, Guest: 443},
+ microvm.PortForward{Host: 2222, Guest: 22},
),
// Replace the OCI ENTRYPOINT/CMD with a custom init script.
// The command is written into /.krun_config.json and executed
// by libkrun's built-in init process (PID 1).
- propolis.WithInitOverride("/sbin/my-init"),
+ microvm.WithInitOverride("/sbin/my-init"),
// Inject files into the rootfs before boot.
// Hooks run after image extraction but before .krun_config.json
// is written, so they can modify anything in the filesystem.
- propolis.WithRootFSHook(func(rootfs string, cfg *image.OCIConfig) error {
+ microvm.WithRootFSHook(func(rootfs string, cfg *image.OCIConfig) error {
return os.WriteFile(
filepath.Join(rootfs, "etc", "my-app.conf"),
[]byte("key=value\n"), 0o644,
@@ -219,31 +219,31 @@ func main() {
// Run setup after the VM process is alive.
// Common use: wait for SSH, push configuration, run health checks.
- propolis.WithPostBoot(func(ctx context.Context, vm *propolis.VM) error {
+ microvm.WithPostBoot(func(ctx context.Context, vm *microvm.VM) error {
keyPath := filepath.Join(vm.DataDir(), "id_ecdsa")
sshClient := ssh.NewClient("127.0.0.1", 2222, "root", keyPath)
return sshClient.WaitForReady(ctx)
}),
// Mount a host directory into the guest via virtio-fs.
- propolis.WithVirtioFS(propolis.VirtioFSMount{
+ microvm.WithVirtioFS(microvm.VirtioFSMount{
Tag: "shared", HostPath: "/srv/data",
}),
// Use a custom data directory for state, caches, and logs.
- // Defaults to ~/.config/propolis or $PROPOLIS_DATA_DIR.
- propolis.WithDataDir("/var/lib/my-appliance"),
+ // Defaults to ~/.config/go-microvm or $GO_MICROVM_DATA_DIR.
+ microvm.WithDataDir("/var/lib/my-appliance"),
// Configure the libkrun backend with a specific runner binary
// and library search path. These options are backend-specific.
- propolis.WithBackend(libkrun.NewBackend(
- libkrun.WithRunnerPath("/usr/local/bin/propolis-runner"),
+ microvm.WithBackend(libkrun.NewBackend(
+ libkrun.WithRunnerPath("/usr/local/bin/go-microvm-runner"),
libkrun.WithLibDir("/opt/libs"),
)),
// Add custom preflight checks beyond the built-in defaults
// (KVM access, disk space, system resources, port availability).
- propolis.WithPreflightChecks(
+ microvm.WithPreflightChecks(
preflight.PortCheck(443, 2222),
preflight.Check{
Name: "connectivity",
@@ -257,7 +257,7 @@ func main() {
),
// Provide a custom image cache location.
- propolis.WithImageCache(image.NewCache("/var/cache/propolis")),
+ microvm.WithImageCache(image.NewCache("/var/cache/go-microvm")),
)
if err != nil {
panic(err)
@@ -280,7 +280,7 @@ func main() {
| Option | Description | Default |
|--------|-------------|---------|
-| `WithName(s)` | VM name for identification | `"propolis"` |
+| `WithName(s)` | VM name for identification | `"go-microvm"` |
| `WithCPUs(n)` | Virtual CPUs (max 8 with stock libkrunfw, max 255 hard limit) | `1` |
| `WithMemory(mib)` | RAM in MiB | `512` |
| `WithPorts(...)` | TCP port forwards from host to guest | none |
@@ -294,7 +294,7 @@ func main() {
| `WithPreflightChecker(c)` | Replace entire preflight checker | platform defaults |
| `WithPreflightChecks(...)` | Add custom pre-boot checks | KVM + resources |
| `WithVirtioFS(...)` | Host directory mounts via virtio-fs | none |
-| `WithDataDir(p)` | State, cache, and log directory | `~/.config/propolis` |
+| `WithDataDir(p)` | State, cache, and log directory | `~/.config/go-microvm` |
| `WithCleanDataDir()` | Remove existing data dir contents before boot | disabled |
| `WithEgressPolicy(p)` | Restrict outbound traffic to allowed DNS hostnames | none |
| `WithImageCache(c)` | Custom image cache instance | `$dataDir/cache/` |
@@ -306,9 +306,9 @@ func main() {
| Package | CGO? | Description |
|---------|------|-------------|
-| `propolis` (root) | No | Top-level API: `Run()`, `VM` type, functional options, hook types |
+| `microvm` (root) | No | Top-level API: `Run()`, `VM` type, functional options, hook types |
| `hypervisor` | No | `Backend` and `VMHandle` interfaces, `VMConfig`, `InitConfig` types |
-| `hypervisor/libkrun` | No | libkrun backend: spawns propolis-runner subprocess, `WithRunnerPath`/`WithLibDir`/`WithSpawner` |
+| `hypervisor/libkrun` | No | libkrun backend: spawns go-microvm-runner subprocess, `WithRunnerPath`/`WithLibDir`/`WithSpawner` |
| `image` | No | OCI image pull via `ImageFetcher`, layer flattening, rootfs extraction |
| `image/disk` | No | Disk image download with decompression (gzip/bzip2/xz) |
| `krun` | **Yes** | CGO bindings to libkrun C API (context, VM config, `StartEnter`) |
@@ -321,21 +321,21 @@ func main() {
| `net/hosted` | No | Hosted `net.Provider` running VirtualNetwork in caller's process with HTTP services |
| `net/topology` | No | Shared network topology constants (subnet, gateway, IPs, MTU) |
| `preflight` | No | `Checker` interface, `Check` struct, built-in KVM/HVF and port checks |
-| `runner` | No | `Spawner` / `ProcessHandle` interfaces for managing the propolis-runner subprocess |
-| `runner/cmd/propolis-runner` | **Yes** | The runner binary (calls `krun.StartEnter`, never returns) |
+| `runner` | No | `Spawner` / `ProcessHandle` interfaces for managing the go-microvm-runner subprocess |
+| `runner/cmd/go-microvm-runner` | **Yes** | The runner binary (calls `krun.StartEnter`, never returns) |
| `ssh` | No | ECDSA key generation and SSH client for guest communication |
| `state` | No | flock-based state persistence with atomic JSON writes |
| `rootfs` | No | Rootfs cloning with reflink (copy-on-write) support |
| `internal/pathutil` | No | Path traversal validation for safe file operations |
| `internal/xattr` | No | Extended attribute helpers for `override_stat` ownership mapping |
-Only `krun` and `runner/cmd/propolis-runner` require CGO and `libkrun-devel`.
+Only `krun` and `runner/cmd/go-microvm-runner` require CGO and `libkrun-devel`.
All other packages are pure Go and can be imported and tested with
`CGO_ENABLED=0`.
## Build
-propolis uses [Task](https://taskfile.dev/) as its build tool. Run
+go-microvm uses [Task](https://taskfile.dev/) as its build tool. Run
`task --list` for all available commands.
| Command | Description |
@@ -361,22 +361,22 @@ The library packages do not require CGO and can be validated separately:
```bash
# Test pure-Go packages only (no libkrun needed)
-CGO_ENABLED=0 go test $(go list ./... | grep -v krun | grep -v propolis-runner)
+CGO_ENABLED=0 go test $(go list ./... | grep -v krun | grep -v go-microvm-runner)
# Vet pure-Go packages
-CGO_ENABLED=0 go vet $(go list ./... | grep -v krun | grep -v propolis-runner)
+CGO_ENABLED=0 go vet $(go list ./... | grep -v krun | grep -v go-microvm-runner)
```
## Architecture
-propolis uses a **two-process model**:
+go-microvm uses a **two-process model**:
```
+---------------------------+ +---------------------------+
-| Your application | | propolis-runner |
-| (links propolis library) | spawn | (CGO binary, links |
+| Your application | | go-microvm-runner |
+| (links go-microvm lib) | spawn | (CGO binary, links |
| |-------->| libkrun) |
-| propolis.Run() | JSON | |
+| microvm.Run() | JSON | |
| | config | 1. Parse Config (argv[1])|
| Pure Go, no CGO | | 2. krun.CreateContext() |
| | | 3. SetVMConfig, SetRoot |
@@ -389,11 +389,11 @@ propolis uses a **two-process model**:
+------------------------------------->| this process
```
-1. **Your application** links the propolis library (pure Go, no CGO). It pulls
+1. **Your application** links the go-microvm library (pure Go, no CGO). It pulls
the OCI image, configures networking, runs preflight checks, and spawns a
subprocess.
-2. **propolis-runner** is a small CGO binary that receives the VM configuration
+2. **go-microvm-runner** is a small CGO binary that receives the VM configuration
as JSON in `argv[1]`. It calls libkrun's C API to configure the VM context,
then calls `krun_start_enter()` -- which **never returns** on success. The
calling process becomes the VM supervisor until the guest shuts down.
@@ -417,7 +417,7 @@ Go runtime.
|
Start networking (in-process vnet)
|
- Spawn propolis-runner subprocess
+ Spawn go-microvm-runner subprocess
|
Runner calls krun_start_enter()
|
@@ -475,7 +475,7 @@ sandboxed hypervisor like Firecracker.
### Tar Extraction Security
-When extracting OCI image layers, propolis applies multiple defenses against
+When extracting OCI image layers, go-microvm applies multiple defenses against
malicious tar archives:
- **Path traversal prevention**: `sanitizeTarPath` rejects absolute paths and
@@ -506,13 +506,13 @@ ls -la /dev/kvm
# If permission denied: sudo usermod -aG kvm $USER
# 2. Check console output for guest-side errors
-cat ~/.config/propolis/console.log
+cat ~/.config/go-microvm/console.log
# 3. Check runner stderr for host-side errors
-cat ~/.config/propolis/vm.log
+cat ~/.config/go-microvm/vm.log
# 4. Verify the runner binary is available
-which propolis-runner
+which go-microvm-runner
# Or check next to your binary
```
@@ -535,8 +535,8 @@ crane pull alpine:latest /tmp/test.tar
# Check which process is using a port
ss -tlnp | grep ':8080'
-# Or use the propolis preflight check directly:
-# propolis.WithPreflightChecks(preflight.PortCheck(8080))
+# Or use the go-microvm preflight check directly:
+# microvm.WithPreflightChecks(preflight.PortCheck(8080))
```
### macOS-Specific Issues
diff --git a/Taskfile.yaml b/Taskfile.yaml
index 8575634..9b7628f 100644
--- a/Taskfile.yaml
+++ b/Taskfile.yaml
@@ -4,7 +4,7 @@
version: '3'
vars:
- RUNNER_NAME: propolis-runner
+ RUNNER_NAME: go-microvm-runner
VERSION:
sh: git describe --tags --always --dirty 2>/dev/null || echo "dev"
COMMIT:
@@ -12,14 +12,14 @@ vars:
BUILD_DATE:
sh: date -u +"%Y-%m-%dT%H:%M:%SZ"
LDFLAGS: >-
- -X github.com/stacklok/propolis/internal/version.Version={{.VERSION}}
- -X github.com/stacklok/propolis/internal/version.Commit={{.COMMIT}}
- -X github.com/stacklok/propolis/internal/version.BuildDate={{.BUILD_DATE}}
+ -X github.com/stacklok/go-microvm/internal/version.Version={{.VERSION}}
+ -X github.com/stacklok/go-microvm/internal/version.Commit={{.COMMIT}}
+ -X github.com/stacklok/go-microvm/internal/version.BuildDate={{.BUILD_DATE}}
HOST_ARCH:
sh: uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/'
CONTAINER_RUNTIME:
sh: command -v podman >/dev/null 2>&1 && echo podman || echo docker
- BUILDER_IMAGE: ghcr.io/stacklok/propolis-builder
+ BUILDER_IMAGE: ghcr.io/stacklok/go-microvm-builder
LIBKRUN_VERSION:
sh: grep '^LIBKRUN_VERSION=' versions.env | cut -d= -f2
LIBKRUN_MAJOR:
@@ -61,7 +61,7 @@ tasks:
CGO_ENABLED: "1"
cmds:
- mkdir -p bin
- - go build -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/propolis-runner
+ - go build -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/go-microvm-runner
sources:
- ./**/*.go
- go.mod
@@ -74,7 +74,7 @@ tasks:
platforms: [darwin]
cmds:
- mkdir -p bin
- - CGO_ENABLED=1 go build -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/propolis-runner
+ - CGO_ENABLED=1 go build -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/go-microvm-runner
# Hypervisor.framework requires entitlements
- codesign --entitlements assets/entitlements.plist --force -s - bin/{{.RUNNER_NAME}}
@@ -95,7 +95,7 @@ tasks:
- install_name_tool -id @loader_path/libepoxy.0.dylib bin/libepoxy.0.dylib
- install_name_tool -id @loader_path/libvirglrenderer.1.dylib bin/libvirglrenderer.1.dylib
- install_name_tool -id @loader_path/libMoltenVK.dylib bin/libMoltenVK.dylib
- # Rewrite propolis-runner → libkrun reference
+ # Rewrite go-microvm-runner → libkrun reference
- >-
install_name_tool -change
/opt/homebrew/opt/libkrun/lib/libkrun.{{.LIBKRUN_MAJOR}}.dylib
@@ -159,7 +159,7 @@ tasks:
CGO_ENABLED: "1"
cmds:
- mkdir -p bin
- - go build -race -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/propolis-runner
+ - go build -race -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/go-microvm-runner
# =============================================================================
# Standard Tasks
@@ -173,7 +173,7 @@ tasks:
test-nocgo:
desc: Run unit tests excluding CGO packages
cmds:
- - go test -v -race $(go list ./... | grep -v krun | grep -v propolis-runner)
+ - go test -v -race $(go list ./... | grep -v krun | grep -v go-microvm-runner)
test-coverage:
desc: Run tests with coverage
@@ -208,7 +208,7 @@ tasks:
env:
CGO_ENABLED: "0"
cmds:
- - go build $(go list ./... | grep -v krun | grep -v propolis-runner)
+ - go build $(go list ./... | grep -v krun | grep -v go-microvm-runner)
verify:
desc: Verify code (fmt, lint, test)
@@ -277,7 +277,7 @@ tasks:
-e CGO_ENABLED=1
-e GOTOOLCHAIN=auto
{{.BUILDER_IMAGE}}:{{.BUILDER_IMAGE_TAG}}
- go build -buildvcs=false -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/propolis-runner
+ go build -buildvcs=false -ldflags "{{.LDFLAGS}}" -o bin/{{.RUNNER_NAME}} ./runner/cmd/go-microvm-runner
generates:
- bin/{{.RUNNER_NAME}}
- bin/libkrun.so.1
@@ -294,9 +294,9 @@ tasks:
cmds:
- mkdir -p dist
- |
- staging="propolis-runtime-linux-{{.HOST_ARCH}}"
+ staging="go-microvm-runtime-linux-{{.HOST_ARCH}}"
mkdir -p "${staging}"
- cp bin/propolis-runner bin/libkrun.so.1 "${staging}/"
+ cp bin/go-microvm-runner bin/libkrun.so.1 "${staging}/"
echo "{{.TAG}}" > "${staging}/VERSION"
tar czf "dist/${staging}.tar.gz" "${staging}"
rm -rf "${staging}"
@@ -308,7 +308,7 @@ tasks:
cmds:
- mkdir -p dist
- |
- staging="propolis-firmware-linux-{{.HOST_ARCH}}"
+ staging="go-microvm-firmware-linux-{{.HOST_ARCH}}"
mkdir -p "${staging}"
cp bin/libkrunfw.so.5 "${staging}/"
echo "{{.TAG}}" > "${staging}/VERSION"
@@ -327,9 +327,9 @@ tasks:
cmds:
- mkdir -p dist
- |
- staging="propolis-runtime-darwin-{{.HOST_ARCH}}"
+ staging="go-microvm-runtime-darwin-{{.HOST_ARCH}}"
mkdir -p "${staging}"
- cp bin/propolis-runner bin/libkrun.{{.LIBKRUN_MAJOR}}.dylib \
+ cp bin/go-microvm-runner bin/libkrun.{{.LIBKRUN_MAJOR}}.dylib \
bin/libepoxy.0.dylib bin/libvirglrenderer.1.dylib bin/libMoltenVK.dylib \
"${staging}/"
echo "{{.TAG}}" > "${staging}/VERSION"
@@ -344,7 +344,7 @@ tasks:
cmds:
- mkdir -p dist
- |
- staging="propolis-firmware-darwin-{{.HOST_ARCH}}"
+ staging="go-microvm-firmware-darwin-{{.HOST_ARCH}}"
mkdir -p "${staging}"
cp bin/libkrunfw.{{.LIBKRUNFW_MAJOR}}.dylib "${staging}/"
echo "{{.TAG}}" > "${staging}/VERSION"
@@ -367,11 +367,11 @@ tasks:
- mkdir -p bin
- >-
gh release download {{.RELEASE_TAG}}
- --repo stacklok/propolis
- --pattern "propolis-runtime-linux-{{.HOST_ARCH}}.tar.gz"
+ --repo stacklok/go-microvm
+ --pattern "go-microvm-runtime-linux-{{.HOST_ARCH}}.tar.gz"
--dir bin/ --clobber
- - tar -xzf bin/propolis-runtime-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
- - rm -f bin/propolis-runtime-linux-{{.HOST_ARCH}}.tar.gz
+ - tar -xzf bin/go-microvm-runtime-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
+ - rm -f bin/go-microvm-runtime-linux-{{.HOST_ARCH}}.tar.gz
fetch-firmware:
desc: Download pre-built firmware tarball from GitHub Release
@@ -381,11 +381,11 @@ tasks:
- mkdir -p bin
- >-
gh release download {{.RELEASE_TAG}}
- --repo stacklok/propolis
- --pattern "propolis-firmware-linux-{{.HOST_ARCH}}.tar.gz"
+ --repo stacklok/go-microvm
+ --pattern "go-microvm-firmware-linux-{{.HOST_ARCH}}.tar.gz"
--dir bin/ --clobber
- - tar -xzf bin/propolis-firmware-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
- - rm -f bin/propolis-firmware-linux-{{.HOST_ARCH}}.tar.gz
+ - tar -xzf bin/go-microvm-firmware-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
+ - rm -f bin/go-microvm-firmware-linux-{{.HOST_ARCH}}.tar.gz
fetch-runtime-darwin:
desc: Download pre-built macOS runtime tarball from GitHub Release
@@ -395,11 +395,11 @@ tasks:
- mkdir -p bin
- >-
gh release download {{.RELEASE_TAG}}
- --repo stacklok/propolis
- --pattern "propolis-runtime-darwin-{{.HOST_ARCH}}.tar.gz"
+ --repo stacklok/go-microvm
+ --pattern "go-microvm-runtime-darwin-{{.HOST_ARCH}}.tar.gz"
--dir bin/ --clobber
- - tar -xzf bin/propolis-runtime-darwin-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
- - rm -f bin/propolis-runtime-darwin-{{.HOST_ARCH}}.tar.gz
+ - tar -xzf bin/go-microvm-runtime-darwin-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
+ - rm -f bin/go-microvm-runtime-darwin-{{.HOST_ARCH}}.tar.gz
fetch-firmware-darwin:
desc: Download pre-built macOS firmware tarball from GitHub Release
@@ -409,11 +409,11 @@ tasks:
- mkdir -p bin
- >-
gh release download {{.RELEASE_TAG}}
- --repo stacklok/propolis
- --pattern "propolis-firmware-darwin-{{.HOST_ARCH}}.tar.gz"
+ --repo stacklok/go-microvm
+ --pattern "go-microvm-firmware-darwin-{{.HOST_ARCH}}.tar.gz"
--dir bin/ --clobber
- - tar -xzf bin/propolis-firmware-darwin-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
- - rm -f bin/propolis-firmware-darwin-{{.HOST_ARCH}}.tar.gz
+ - tar -xzf bin/go-microvm-firmware-darwin-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
+ - rm -f bin/go-microvm-firmware-darwin-{{.HOST_ARCH}}.tar.gz
fetch-runtime-oci:
desc: Pull pre-built runtime OCI artifact from ghcr.io
@@ -423,10 +423,10 @@ tasks:
- mkdir -p bin
- >-
oras pull
- ghcr.io/stacklok/propolis/runtime:{{.RELEASE_TAG}}-linux-{{.HOST_ARCH}}
+ ghcr.io/stacklok/go-microvm/runtime:{{.RELEASE_TAG}}-linux-{{.HOST_ARCH}}
-o bin/
- - tar -xzf bin/propolis-runtime-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
- - rm -f bin/propolis-runtime-linux-{{.HOST_ARCH}}.tar.gz
+ - tar -xzf bin/go-microvm-runtime-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
+ - rm -f bin/go-microvm-runtime-linux-{{.HOST_ARCH}}.tar.gz
fetch-firmware-oci:
desc: Pull pre-built firmware OCI artifact from ghcr.io
@@ -436,7 +436,7 @@ tasks:
- mkdir -p bin
- >-
oras pull
- ghcr.io/stacklok/propolis/firmware:{{.RELEASE_TAG}}-linux-{{.HOST_ARCH}}
+ ghcr.io/stacklok/go-microvm/firmware:{{.RELEASE_TAG}}-linux-{{.HOST_ARCH}}
-o bin/
- - tar -xzf bin/propolis-firmware-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
- - rm -f bin/propolis-firmware-linux-{{.HOST_ARCH}}.tar.gz
+ - tar -xzf bin/go-microvm-firmware-linux-{{.HOST_ARCH}}.tar.gz -C bin/ --strip-components=1
+ - rm -f bin/go-microvm-firmware-linux-{{.HOST_ARCH}}.tar.gz
diff --git a/assets/propolis.png b/assets/go-microvm.png
similarity index 100%
rename from assets/propolis.png
rename to assets/go-microvm.png
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index 341b773..3823ec3 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -1,6 +1,6 @@
-# propolis Architecture
+# go-microvm Architecture
-This document describes the internal architecture of propolis: how it turns an
+This document describes the internal architecture of go-microvm: how it turns an
OCI container image into a running microVM, the two-process model, networking,
state management, security measures, and extension points.
@@ -26,12 +26,12 @@ success it never returns -- the process becomes the VM supervisor and
eventually calls `exit()` when the guest shuts down. This means we cannot call
it from a normal Go application without losing the Go runtime entirely.
-propolis solves this with two processes:
+go-microvm solves this with two processes:
```
+----------------------------------+ +----------------------------------+
-| Your application | | propolis-runner |
-| (links propolis library) | | (CGO binary, links libkrun) |
+| Your application | | go-microvm-runner |
+| (links go-microvm library) | | (CGO binary, links libkrun) |
| | | |
| 1. Preflight checks | spawn | 1. Parse Config from argv[1] |
| 2. Pull & cache OCI image |------>| 2. Validate (rootfs, vCPUs>0) |
@@ -39,7 +39,7 @@ propolis solves this with two processes:
| 4. Run rootfs hooks | config| 4. SetVMConfig(vCPUs, RAM) |
| 5. Write .krun_config.json | | 5. SetRoot(rootfsPath) |
| 6. Start networking (if custom)| | 6. Setup networking |
-| 7. Spawn propolis-runner | | 7. AddVirtioFS (for each mount) |
+| 7. Spawn go-microvm-runner | | 7. AddVirtioFS (for each mount) |
| 8. Run post-boot hooks | | 8. SetConsoleOutput(logPath) |
| 9. Return *VM handle | | 9. krun_start_enter() |
| | | (NEVER RETURNS ON SUCCESS) |
@@ -54,7 +54,7 @@ propolis solves this with two processes:
### Library Side (your application)
The library is pure Go with no CGO dependency. It performs the following steps
-in `propolis.Run()`:
+in `microvm.Run()`:
1. **Preflight checks** -- Runs all registered `preflight.Checker` validations.
Built-in checks verify KVM/HVF access, disk space, and system resources.
@@ -92,7 +92,7 @@ in `propolis.Run()`:
6. **Start VM via backend** -- The `hypervisor.Backend` handles rootfs
preparation and VM launch. The default libkrun backend serializes
- `runner.Config` as JSON and spawns `propolis-runner` as a detached
+ `runner.Config` as JSON and spawns `go-microvm-runner` as a detached
subprocess (`setsid` for new session). The runner is located by
searching: explicit path, system PATH, then next to the calling
executable. Custom backends can be provided via `WithBackend()`.
@@ -100,9 +100,9 @@ in `propolis.Run()`:
7. **Post-boot hooks** -- Runs caller-provided `PostBootHook` functions. If
any hook fails, the VM is stopped and the error is returned.
-### Runner Side (propolis-runner)
+### Runner Side (go-microvm-runner)
-The runner binary (`runner/cmd/propolis-runner/main.go`) is intentionally
+The runner binary (`runner/cmd/go-microvm-runner/main.go`) is intentionally
minimal. It is a thin translation layer between JSON config and the libkrun
C API:
@@ -147,7 +147,7 @@ testing or to customize how the runner subprocess is launched.
## Hypervisor Backend Abstraction
-The `hypervisor` package defines the `Backend` interface that decouples propolis
+The `hypervisor` package defines the `Backend` interface that decouples go-microvm
from any specific hypervisor implementation:
```go
@@ -169,7 +169,7 @@ type VMHandle interface {
The default backend (`hypervisor/libkrun`) implements `Backend` by:
1. **PrepareRootFS**: Writes `/.krun_config.json` to the rootfs from `InitConfig`
-2. **Start**: Converts `VMConfig` to `runner.Config`, spawns `propolis-runner`
+2. **Start**: Converts `VMConfig` to `runner.Config`, spawns `go-microvm-runner`
via the `runner.Spawner` interface, and returns a `processHandle` wrapping
the subprocess
@@ -177,15 +177,15 @@ The libkrun backend accepts its own options via `libkrun.NewBackend(opts...)`:
| Option | Description |
|--------|-------------|
-| `libkrun.WithRunnerPath(p)` | Path to propolis-runner binary |
+| `libkrun.WithRunnerPath(p)` | Path to go-microvm-runner binary |
| `libkrun.WithLibDir(d)` | Directory for libkrun/libkrunfw shared libraries |
| `libkrun.WithSpawner(s)` | Custom runner subprocess spawner (for testing) |
### Custom Backends
To support a different hypervisor, implement `hypervisor.Backend` and pass it
-via `propolis.WithBackend()`. The backend handles all hypervisor-specific logic
-while propolis handles OCI image management, networking, hooks, and lifecycle.
+via `microvm.WithBackend()`. The backend handles all hypervisor-specific logic
+while go-microvm handles OCI image management, networking, hooks, and lifecycle.
For migration details from the older top-level `WithRunnerPath`/`WithLibDir`/
`WithSpawner` options, see [MIGRATION-BACKEND-ABSTRACTION.md](MIGRATION-BACKEND-ABSTRACTION.md).
@@ -268,7 +268,7 @@ Step 9: NETWORKING
Custom provider: net.Provider.Start() in caller's process, socket path to runner
|
Step 10: SPAWN
- runner.Spawner.Spawn() --> propolis-runner subprocess
+ runner.Spawner.Spawn() --> go-microvm-runner subprocess
Detached (setsid), stdout/stderr redirected to vm.log
|
Step 11: POST-BOOT
@@ -281,7 +281,7 @@ Step 11: POST-BOOT
Images are cached by manifest digest under the data directory:
```
-~/.config/propolis/cache/
+~/.config/go-microvm/cache/
sha256-abc123def456.../ <-- extracted rootfs for this digest
sha256-789012345678.../ <-- another cached image
```
@@ -309,14 +309,14 @@ This ensures no partial writes and no corruption from concurrent access.
### Cache Directory
-The cache directory defaults to `~/.config/propolis/cache/`. It can be
+The cache directory defaults to `~/.config/go-microvm/cache/`. It can be
customized via `WithDataDir()` (which sets the cache under `$dataDir/cache/`)
or directly via `WithImageCache(image.NewCache("/custom/path"))`.
## .krun_config.json
libkrun's built-in init process reads `/.krun_config.json` from the root of
-the guest filesystem to determine what program to execute. propolis constructs
+the guest filesystem to determine what program to execute. go-microvm constructs
this file from the OCI image config with optional overrides.
### Format
@@ -352,7 +352,7 @@ This is the same mechanism used by krunvm and podman machine.
## Networking
-propolis uses a userspace network stack powered by
+go-microvm uses a userspace network stack powered by
[gvisor-tap-vsock](https://github.com/containers/gvisor-tap-vsock). All VM
traffic flows as Ethernet frames with no kernel networking between host and
guest.
@@ -443,7 +443,7 @@ type Provider interface {
To replace the default runner-side networking with a different backend
(e.g., passt, slirp4netns, a custom bridge, or the built-in hosted
provider), implement this interface and pass it via
-`propolis.WithNetProvider()`. The `SocketPath()` return value is passed to
+`microvm.WithNetProvider()`. The `SocketPath()` return value is passed to
the runner as the Unix socket path for `krun_add_net_unixstream`.
### Network Topology Constants
@@ -464,16 +464,16 @@ these values to ensure a consistent topology.
### Hosted Network Provider
The `net/hosted` package implements a `net.Provider` that runs the
-VirtualNetwork in the caller's process rather than inside propolis-runner.
+VirtualNetwork in the caller's process rather than inside go-microvm-runner.
This enables callers to access the VirtualNetwork directly -- for example,
to create in-process TCP listeners via gonet that are reachable from the
guest VM without opening real host sockets.
```go
p := hosted.NewProvider()
-vm, err := propolis.Run(ctx, image,
- propolis.WithNetProvider(p),
- propolis.WithPorts(propolis.PortForward{Host: sshPort, Guest: 22}),
+vm, err := microvm.Run(ctx, image,
+ microvm.WithNetProvider(p),
+ microvm.WithPorts(microvm.PortForward{Host: sshPort, Guest: 22}),
)
// p.VirtualNetwork() is now available for gonet listeners.
```
@@ -487,12 +487,12 @@ before the guest boots and are reachable from inside the VM:
```go
p := hosted.NewProvider()
p.AddService(hosted.Service{Port: 4483, Handler: myHandler})
-vm, err := propolis.Run(ctx, image, propolis.WithNetProvider(p))
+vm, err := microvm.Run(ctx, image, microvm.WithNetProvider(p))
// Guest can reach http://192.168.127.1:4483/
```
The hosted provider exposes a Unix socket (`hosted-net.sock` in the data
-directory) that propolis-runner connects to. When firewall rules are
+directory) that go-microvm-runner connects to. When firewall rules are
configured, a `firewall.Relay` is inserted between the runner connection
and the VirtualNetwork to filter traffic. The relay is accessible via
`Provider.Relay()` for metrics.
@@ -500,7 +500,7 @@ and the VirtualNetwork to filter traffic. The relay is accessible via
## Extension Points
```
- propolis.Run()
+ microvm.Run()
|
+------------+------------+
| |
@@ -540,14 +540,14 @@ and the VirtualNetwork to filter traffic. The relay is accessible via
Inject validation before any work begins:
```go
-propolis.WithPreflightChecks(check1, check2)
+microvm.WithPreflightChecks(check1, check2)
```
### Rootfs Hooks
Modify the extracted filesystem before boot:
```go
-propolis.WithRootFSHook(func(rootfs string, cfg *image.OCIConfig) error {
+microvm.WithRootFSHook(func(rootfs string, cfg *image.OCIConfig) error {
// Write files, install keys, modify configs
return nil
})
@@ -557,14 +557,14 @@ propolis.WithRootFSHook(func(rootfs string, cfg *image.OCIConfig) error {
Replace the OCI ENTRYPOINT/CMD:
```go
-propolis.WithInitOverride("/sbin/my-init", "--flag")
+microvm.WithInitOverride("/sbin/my-init", "--flag")
```
### Network Provider
Replace the default runner-side networking with a custom provider:
```go
-propolis.WithNetProvider(myProvider)
+microvm.WithNetProvider(myProvider)
```
The `net/hosted` package provides a built-in hosted provider that runs the
@@ -572,7 +572,7 @@ VirtualNetwork in the caller's process:
```go
p := hosted.NewProvider()
p.AddService(hosted.Service{Port: 4483, Handler: myHandler})
-propolis.WithNetProvider(p)
+microvm.WithNetProvider(p)
// After Run(), p.VirtualNetwork() is available for gonet listeners.
```
@@ -580,7 +580,7 @@ propolis.WithNetProvider(p)
Run logic after the VM process is confirmed alive:
```go
-propolis.WithPostBoot(func(ctx context.Context, vm *propolis.VM) error {
+microvm.WithPostBoot(func(ctx context.Context, vm *microvm.VM) error {
// Wait for SSH, push config, verify health
return nil
})
@@ -633,8 +633,8 @@ via `slog.Warn` but do not prevent the pipeline from proceeding.
Pass checks via `WithPreflightChecks()`:
```go
-propolis.Run(ctx, ref,
- propolis.WithPreflightChecks(
+microvm.Run(ctx, ref,
+ microvm.WithPreflightChecks(
preflight.PortCheck(8080, 2222),
preflight.Check{
Name: "my-check",
@@ -650,7 +650,7 @@ Custom checks are appended to (not replacing) the built-in platform defaults.
To replace the entire preflight checker (e.g., when the caller manages its own):
```go
-propolis.WithPreflightChecker(preflight.NewEmpty())
+microvm.WithPreflightChecker(preflight.NewEmpty())
```
## Guest-Side Packages
@@ -663,7 +663,7 @@ processes to orchestrate guest boot.
|---------|---------|
| `guest/boot` | Orchestrates the guest boot sequence: mounts, networking, workspace, hardening, environment, SSH, capabilities. Functional options pattern for configuration. |
| `guest/mount` | Handles essential filesystem mounts (devtmpfs, sysfs, procfs) and workspace mounts |
-| `guest/env` | Loads environment variables from `/.propolis/env.sh` |
+| `guest/env` | Loads environment variables from `/.go-microvm/env.sh` |
| `guest/netcfg` | Guest-side network configuration (DHCP, routes) |
| `guest/harden` | VM kernel hardening: capability dropping (CAP_NET_ADMIN, etc.), CIS benchmark sysctls, `PR_SET_NO_NEW_PRIVS` |
| `guest/reaper` | Zombie process reaping (init process duties) |
@@ -674,7 +674,7 @@ processes to orchestrate guest boot.
| Package | Purpose |
|---------|---------|
| `hooks` | RootFS hook factories: `InjectAuthorizedKeys`, `InjectFile`, `InjectBinary`, `InjectEnvFile`. Uses `internal/pathutil` for path traversal validation. |
-| `extract` | Binary bundle caching with SHA-256 versioning, atomic extraction, and cross-process file locking. Used to cache and extract the propolis-runner binary and libraries. |
+| `extract` | Binary bundle caching with SHA-256 versioning, atomic extraction, and cross-process file locking. Used to cache and extract the go-microvm-runner binary and libraries. |
| `image/disk` | Streaming disk image download with retry support and decompression (gzip, bzip2, xz). |
## State Management
@@ -684,14 +684,14 @@ The `state` package provides persistent VM state with file-based locking.
### Directory Layout
```
-~/.config/propolis/ (or $PROPOLIS_DATA_DIR, or WithDataDir path)
- propolis-state.json <-- VM state (atomic JSON)
- propolis-state.lock <-- flock for exclusive access
+~/.config/go-microvm/ (or $GO_MICROVM_DATA_DIR, or WithDataDir path)
+ go-microvm-state.json <-- VM state (atomic JSON)
+ go-microvm-state.lock <-- flock for exclusive access
cache/
sha256-abc123.../ <-- cached rootfs by digest
sha256-def456.../
console.log <-- guest console output (kernel, init)
- vm.log <-- propolis-runner stdout/stderr
+ vm.log <-- go-microvm-runner stdout/stderr
hosted-net.sock <-- networking Unix socket (only with hosted provider)
```
@@ -725,8 +725,8 @@ The `state` package provides persistent VM state with file-based locking.
The `state.Manager` provides atomic load-and-lock semantics:
-1. `LoadAndLock(ctx)` acquires an exclusive `flock` on `propolis-state.lock`
-2. Reads and parses `propolis-state.json` (or returns a default State if the file
+1. `LoadAndLock(ctx)` acquires an exclusive `flock` on `go-microvm-state.lock`
+2. Reads and parses `go-microvm-state.json` (or returns a default State if the file
does not exist)
3. Returns a `LockedState` that holds the lock
@@ -757,7 +757,7 @@ for cases where another process may hold the lock temporarily.
1. Marshals the state to JSON with indentation
2. Writes to a temporary file in the same directory (`state-*.json.tmp`)
-3. Calls `os.Rename()` to atomically replace `propolis-state.json`
+3. Calls `os.Rename()` to atomically replace `go-microvm-state.json`
If a crash occurs during write, either the old state remains intact or the
new state is fully written -- never a partial file. The `flock` ensures only
@@ -807,7 +807,7 @@ safe use in shell commands.
The standard post-boot hook pattern uses `WaitForReady`:
```go
-propolis.WithPostBoot(func(ctx context.Context, vm *propolis.VM) error {
+microvm.WithPostBoot(func(ctx context.Context, vm *microvm.VM) error {
client := ssh.NewClient("127.0.0.1", 2222, "root", keyPath)
return client.WaitForReady(ctx)
})
diff --git a/docs/CI.md b/docs/CI.md
index 399b3ae..39f6014 100644
--- a/docs/CI.md
+++ b/docs/CI.md
@@ -1,6 +1,6 @@
# CI & Release Pipelines
-propolis uses three GitHub Actions workflows. They form a dependency chain:
+go-microvm uses three GitHub Actions workflows. They form a dependency chain:
the **Builder** produces a container image that **CI** and **Release** consume.
## Workflows
@@ -34,7 +34,7 @@ setup tools, call task).
### Builder (`builder.yaml`)
-Builds the `ghcr.io/stacklok/propolis-builder` container image, which
+Builds the `ghcr.io/stacklok/go-microvm-builder` container image, which
compiles libkrun and libkrunfw from source. This image provides the CGO
toolchain that CI and Release need.
@@ -66,7 +66,7 @@ Both architectures (amd64, arm64) build on native runners.
**Where artifacts go:**
- GitHub Release with checksums
-- OCI artifacts pushed to `ghcr.io/stacklok/propolis/{runtime,firmware}`
+- OCI artifacts pushed to `ghcr.io/stacklok/go-microvm/{runtime,firmware}`
The runtime and firmware are split into separate tarballs because they
have different licenses.
diff --git a/docs/MACOS.md b/docs/MACOS.md
index a758fc6..c6d9dd2 100644
--- a/docs/MACOS.md
+++ b/docs/MACOS.md
@@ -1,6 +1,6 @@
# macOS Support
-propolis supports macOS on Apple Silicon (arm64) using Hypervisor.framework.
+go-microvm supports macOS on Apple Silicon (arm64) using Hypervisor.framework.
## Requirements
@@ -18,7 +18,7 @@ brew install libkrun libkrunfw
```
This installs the libraries and headers into Homebrew's prefix (`/opt/homebrew`
-on Apple Silicon, `/usr/local` on Intel). The CGO directives in propolis
+on Apple Silicon, `/usr/local` on Intel). The CGO directives in go-microvm
automatically search both paths.
## Key Platform Differences
@@ -47,10 +47,10 @@ Three entitlements are required (see `assets/entitlements.plist`):
entitlement activates hardened runtime, which silently strips `DYLD_*`
variables without this entitlement)
-The propolis-runner binary must be signed:
+The go-microvm-runner binary must be signed:
```bash
-codesign --entitlements assets/entitlements.plist --force -s - bin/propolis-runner
+codesign --entitlements assets/entitlements.plist --force -s - bin/go-microvm-runner
```
The `task build-dev-darwin` command handles signing automatically.
@@ -58,7 +58,7 @@ The `task build-dev-darwin` command handles signing automatically.
## DYLD_LIBRARY_PATH
When using bundled (non-system) libraries, the runner subprocess needs
-`DYLD_LIBRARY_PATH` set. propolis handles this automatically via
+`DYLD_LIBRARY_PATH` set. go-microvm handles this automatically via
`libkrun.WithLibDir()` (passed to `libkrun.NewBackend()`).
The hypervisor entitlement activates macOS **hardened runtime**, which silently
@@ -69,12 +69,12 @@ to find libkrun, verify the binary is signed with all three entitlements.
## Filesystem Permissions (virtiofs)
-On macOS, non-root users cannot `chown` files to arbitrary UIDs. When propolis
+On macOS, non-root users cannot `chown` files to arbitrary UIDs. When go-microvm
extracts an OCI image, all files end up owned by the host user. libkrun's
virtiofs FUSE server performs access checks using host-side ownership, so guest
processes running as different UIDs (e.g., root) would get `EACCES` errors.
-propolis works around this using the `user.containers.override_stat` extended
+go-microvm works around this using the `user.containers.override_stat` extended
attribute, which libkrun's virtiofs server reads to report overridden
uid/gid/mode to the guest. This is the same mechanism used by podman on macOS.
The xattr is set automatically during OCI layer extraction and rootfs cloning
@@ -83,7 +83,7 @@ The xattr is set automatically during OCI layer extraction and rootfs cloning
## Guest Networking
On macOS, libkrun's Hypervisor.framework backend pre-configures the guest
-network interface via DHCP before the custom init process runs. propolis
+network interface via DHCP before the custom init process runs. go-microvm
handles this transparently by using idempotent network configuration
(`AddrReplace`/`RouteReplace` instead of `AddrAdd`/`RouteAdd`), so the init
works correctly regardless of whether the interface is already configured.
@@ -106,11 +106,11 @@ nested virtualization).
EXC_BAD_ACCESS (code=1, address=0x0)
```
-The propolis-runner binary is not signed with the hypervisor entitlement.
+The go-microvm-runner binary is not signed with the hypervisor entitlement.
Re-sign it:
```bash
-codesign --entitlements assets/entitlements.plist --force -s - bin/propolis-runner
+codesign --entitlements assets/entitlements.plist --force -s - bin/go-microvm-runner
```
### DYLD_LIBRARY_PATH issues
diff --git a/docs/MIGRATION-BACKEND-ABSTRACTION.md b/docs/MIGRATION-BACKEND-ABSTRACTION.md
index 17e9917..ac0513c 100644
--- a/docs/MIGRATION-BACKEND-ABSTRACTION.md
+++ b/docs/MIGRATION-BACKEND-ABSTRACTION.md
@@ -8,35 +8,35 @@ consumers.
| Removed API | Replacement | Affected projects |
|---|---|---|
-| `propolis.WithRunnerPath(p)` | `libkrun.WithRunnerPath(p)` passed to `libkrun.NewBackend()` | waggle, apiary, toolhive-appliance |
-| `propolis.WithLibDir(d)` | `libkrun.WithLibDir(d)` passed to `libkrun.NewBackend()` | waggle, toolhive-appliance |
-| `propolis.WithSpawner(s)` | `libkrun.WithSpawner(s)` passed to `libkrun.NewBackend()` | tests only |
-| `propolis.VM.PID() int` | `propolis.VM.ID() string` | waggle, toolhive-appliance |
+| `microvm.WithRunnerPath(p)` | `libkrun.WithRunnerPath(p)` passed to `libkrun.NewBackend()` | waggle, apiary, toolhive-appliance |
+| `microvm.WithLibDir(d)` | `libkrun.WithLibDir(d)` passed to `libkrun.NewBackend()` | waggle, toolhive-appliance |
+| `microvm.WithSpawner(s)` | `libkrun.WithSpawner(s)` passed to `libkrun.NewBackend()` | tests only |
+| `microvm.VM.PID() int` | `microvm.VM.ID() string` | waggle, toolhive-appliance |
## New Imports
```go
-import "github.com/stacklok/propolis/hypervisor/libkrun"
+import "github.com/stacklok/go-microvm/hypervisor/libkrun"
```
## Migration Examples
-### waggle (`pkg/infra/vm/propolis.go`)
+### waggle (`pkg/infra/vm/microvm.go`)
**Before:**
```go
if opts.RunnerPath != "" {
- propolisOpts = append(propolisOpts, propolis.WithRunnerPath(opts.RunnerPath))
+ microvmOpts = append(microvmOpts, microvm.WithRunnerPath(opts.RunnerPath))
}
if opts.LibDir != "" {
- propolisOpts = append(propolisOpts, propolis.WithLibDir(opts.LibDir))
+ microvmOpts = append(microvmOpts, microvm.WithLibDir(opts.LibDir))
}
slog.Info("microVM created", "pid", vm.PID())
```
**After:**
```go
-import "github.com/stacklok/propolis/hypervisor/libkrun"
+import "github.com/stacklok/go-microvm/hypervisor/libkrun"
var backendOpts []libkrun.Option
if opts.RunnerPath != "" {
@@ -45,7 +45,7 @@ if opts.RunnerPath != "" {
if opts.LibDir != "" {
backendOpts = append(backendOpts, libkrun.WithLibDir(opts.LibDir))
}
-propolisOpts = append(propolisOpts, propolis.WithBackend(libkrun.NewBackend(backendOpts...)))
+microvmOpts = append(microvmOpts, microvm.WithBackend(libkrun.NewBackend(backendOpts...)))
slog.Info("microVM created", "id", vm.ID())
```
@@ -54,16 +54,16 @@ slog.Info("microVM created", "id", vm.ID())
**Before:**
```go
if r.runnerPath != "" {
- opts = append(opts, propolis.WithRunnerPath(r.runnerPath))
+ opts = append(opts, microvm.WithRunnerPath(r.runnerPath))
}
```
**After:**
```go
-import "github.com/stacklok/propolis/hypervisor/libkrun"
+import "github.com/stacklok/go-microvm/hypervisor/libkrun"
if r.runnerPath != "" {
- opts = append(opts, propolis.WithBackend(libkrun.NewBackend(
+ opts = append(opts, microvm.WithBackend(libkrun.NewBackend(
libkrun.WithRunnerPath(r.runnerPath),
)))
}
@@ -74,10 +74,10 @@ if r.runnerPath != "" {
**Before:**
```go
if runnerPath != "" {
- propolisOpts = append(propolisOpts, propolis.WithRunnerPath(runnerPath))
+ microvmOpts = append(microvmOpts, microvm.WithRunnerPath(runnerPath))
}
if libDir != "" {
- propolisOpts = append(propolisOpts, propolis.WithLibDir(libDir))
+ microvmOpts = append(microvmOpts, microvm.WithLibDir(libDir))
}
PID: vmInstance.PID(),
go m.reaperLoop(vmInstance.PID())
@@ -87,7 +87,7 @@ go m.reaperLoop(vmInstance.PID())
```go
import (
"strconv"
- "github.com/stacklok/propolis/hypervisor/libkrun"
+ "github.com/stacklok/go-microvm/hypervisor/libkrun"
)
var backendOpts []libkrun.Option
@@ -97,7 +97,7 @@ if runnerPath != "" {
if libDir != "" {
backendOpts = append(backendOpts, libkrun.WithLibDir(libDir))
}
-propolisOpts = append(propolisOpts, propolis.WithBackend(libkrun.NewBackend(backendOpts...)))
+microvmOpts = append(microvmOpts, microvm.WithBackend(libkrun.NewBackend(backendOpts...)))
// For PID — parse ID string:
id := vmInstance.ID()
@@ -110,8 +110,8 @@ pid, _ := strconv.Atoi(id)
**Before:**
```go
spawner := &mockSpawner{proc: mockProc, err: nil}
-opts := []propolis.Option{
- propolis.WithSpawner(spawner),
+opts := []microvm.Option{
+ microvm.WithSpawner(spawner),
}
```
@@ -131,7 +131,7 @@ func (m *mockBackend) Start(_ context.Context, _ hypervisor.VMConfig) (hyperviso
return m.handle, m.err
}
-opts := []propolis.Option{
- propolis.WithBackend(&mockBackend{handle: mockHandle}),
+opts := []microvm.Option{
+ microvm.WithBackend(&mockBackend{handle: mockHandle}),
}
```
diff --git a/docs/NETWORKING.md b/docs/NETWORKING.md
index 7a0a4b7..bbb1f8f 100644
--- a/docs/NETWORKING.md
+++ b/docs/NETWORKING.md
@@ -1,6 +1,6 @@
# Networking and Firewall
-This document provides a deep dive into the propolis networking subsystem,
+This document provides a deep dive into the go-microvm networking subsystem,
including the in-process userspace network stack, wire protocol, firewall
architecture, and extension points.
@@ -18,7 +18,7 @@ architecture, and extension points.
## Overview
-propolis uses a userspace network stack powered by
+go-microvm uses a userspace network stack powered by
[gvisor-tap-vsock](https://github.com/containers/gvisor-tap-vsock). All VM
traffic flows as Ethernet frames with no kernel networking between host and
guest, and no separate gvproxy binary is needed.
@@ -59,7 +59,7 @@ When no `WithNetProvider()` is set, the runner creates a VirtualNetwork
in-process and connects it to libkrun via a socketpair:
```
-+----------------------------------propolis-runner process---------+
++----------------------------------go-microvm-runner process------+
| |
| +----------+ socketpair +-------------------+ Go net |
| | libkrun | (fd pair) | VirtualNetwork |----------+ |
@@ -375,15 +375,15 @@ Return traffic for allowed connections is automatically permitted via
connection tracking.
```go
-import "github.com/stacklok/propolis/net/firewall"
+import "github.com/stacklok/go-microvm/net/firewall"
-vm, err := propolis.Run(ctx, "my-app:latest",
- propolis.WithPorts(
- propolis.PortForward{Host: 8080, Guest: 80},
- propolis.PortForward{Host: 2222, Guest: 22},
+vm, err := microvm.Run(ctx, "my-app:latest",
+ microvm.WithPorts(
+ microvm.PortForward{Host: 8080, Guest: 80},
+ microvm.PortForward{Host: 2222, Guest: 22},
),
- propolis.WithFirewallDefaultAction(firewall.Deny),
- propolis.WithFirewallRules(
+ microvm.WithFirewallDefaultAction(firewall.Deny),
+ microvm.WithFirewallRules(
// Egress: allow DNS and HTTPS
firewall.Rule{
Direction: firewall.Egress,
@@ -417,13 +417,13 @@ vm, err := propolis.Run(ctx, "my-app:latest",
### Allow Specific Ingress Ports Only
```go
-vm, err := propolis.Run(ctx, "my-server:latest",
- propolis.WithPorts(
- propolis.PortForward{Host: 8443, Guest: 443},
- propolis.PortForward{Host: 6443, Guest: 6443},
+vm, err := microvm.Run(ctx, "my-server:latest",
+ microvm.WithPorts(
+ microvm.PortForward{Host: 8443, Guest: 443},
+ microvm.PortForward{Host: 6443, Guest: 6443},
),
- propolis.WithFirewallDefaultAction(firewall.Deny),
- propolis.WithFirewallRules(
+ microvm.WithFirewallDefaultAction(firewall.Deny),
+ microvm.WithFirewallRules(
// Allow all egress (VM can reach the internet)
firewall.Rule{
Direction: firewall.Egress,
@@ -458,8 +458,8 @@ When no firewall rules are configured, all traffic passes through
unrestricted. This is the default behavior:
```go
-vm, err := propolis.Run(ctx, "alpine:latest",
- propolis.WithPorts(propolis.PortForward{Host: 8080, Guest: 80}),
+vm, err := microvm.Run(ctx, "alpine:latest",
+ microvm.WithPorts(microvm.PortForward{Host: 8080, Guest: 80}),
)
```
@@ -467,13 +467,13 @@ vm, err := propolis.Run(ctx, "alpine:latest",
`WithEgressPolicy()` restricts VM outbound traffic to a set of allowed DNS
hostnames. Instead of writing firewall rules for specific IPs (which change
-often), you specify hostnames and let propolis handle the rest.
+often), you specify hostnames and let go-microvm handle the rest.
```go
-vm, err := propolis.Run(ctx, "my-app:latest",
- propolis.WithPorts(propolis.PortForward{Host: 8080, Guest: 80}),
- propolis.WithEgressPolicy(propolis.EgressPolicy{
- AllowedHosts: []propolis.EgressHost{
+vm, err := microvm.Run(ctx, "my-app:latest",
+ microvm.WithPorts(microvm.PortForward{Host: 8080, Guest: 80}),
+ microvm.WithEgressPolicy(microvm.EgressPolicy{
+ AllowedHosts: []microvm.EgressHost{
{Name: "api.github.com", Ports: []uint16{443}},
{Name: "*.docker.io"},
{Name: "ntp.ubuntu.com", Ports: []uint16{123}, Protocol: 17},
@@ -555,7 +555,7 @@ To replace the default runner-side networking with an alternative backend
2. `Start()` must block until the Unix socket is ready for connections.
3. The socket must use `SOCK_STREAM` with 4-byte big-endian length-prefixed
Ethernet frames (the QEMU transport protocol).
-4. Pass your provider via `propolis.WithNetProvider(myProvider)`.
+4. Pass your provider via `microvm.WithNetProvider(myProvider)`.
The `SocketPath()` return value is passed to the runner as the Unix socket
path for `krun_add_net_unixstream`. See `net/hosted/provider.go` for the
diff --git a/docs/SECURITY.md b/docs/SECURITY.md
index 5a58e70..2dd373f 100644
--- a/docs/SECURITY.md
+++ b/docs/SECURITY.md
@@ -1,7 +1,7 @@
# Security Model
This document describes the security properties, trust boundaries, and
-hardening recommendations for propolis.
+hardening recommendations for go-microvm.
## Table of Contents
@@ -19,14 +19,14 @@ hardening recommendations for propolis.
## Trust Boundaries
-propolis has two trust boundaries:
+go-microvm has two trust boundaries:
```
Trust boundary 1: KVM/HVF
(hardware isolation)
|
+-------------------------+|+------------------------------------------+
-| Guest VM ||| propolis-runner |
+| Guest VM ||| go-microvm-runner |
| (untrusted code) ||| +------------------+ +------------------+|
| ||| | libkrun VMM | | VirtualNetwork ||
| Runs user workload ||| | (virtio devices, | | (gvisor-tap-vsock||
@@ -136,9 +136,9 @@ security-sensitive deployments.
The collapsed trust boundary (default mode) would matter more if:
- **Multiple VMs shared a VirtualNetwork** (multi-tenant): one VM could
- sniff or poison another's traffic. propolis does not support this.
+ sniff or poison another's traffic. go-microvm does not support this.
- **The network stack held secrets** (TLS termination, auth tokens):
- a guest escape would expose them. propolis port forwards are plain TCP.
+ a guest escape would expose them. go-microvm port forwards are plain TCP.
- **The network stack ran with higher privileges** than the VMM: not the
case here, both share the same process and UID.
@@ -199,7 +199,7 @@ network stack out of the runner process. This achieves process-level
separation without a custom helper binary:
```
-propolis-runner (VMM only)
+go-microvm-runner (VMM only)
└── Unix socket → hosted provider in caller's process
caller's process (network stack)
└── hosted.Provider → VirtualNetwork + HTTP services
@@ -387,7 +387,7 @@ The egress policy prevents a compromised or untrusted VM from:
## Tar Extraction Defenses
-When extracting OCI image layers, propolis applies multiple layers of
+When extracting OCI image layers, go-microvm applies multiple layers of
defense against malicious tar archives:
**Path traversal prevention.** Every tar entry name is cleaned via
@@ -418,7 +418,7 @@ are silently skipped.
## Process Identity Verification
-When managing VM lifecycle, propolis verifies process identity before
+When managing VM lifecycle, go-microvm verifies process identity before
sending signals:
- `IsAlive()` sends signal 0 to the PID (no-op that verifies the
@@ -432,7 +432,7 @@ been reused.
## Host Capabilities (Linux)
-When running as a non-root user on Linux, propolis requires `CAP_CHOWN` on the
+When running as a non-root user on Linux, go-microvm requires `CAP_CHOWN` on the
process to set correct file ownership during OCI image extraction. Without it,
all extracted rootfs files are owned by the host user, and the guest sees
incorrect ownership — which can cause permission errors for processes running
@@ -451,7 +451,7 @@ capsh --addamb=cap_chown -- -c '/path/to/your-binary'
### override_stat xattr (macOS and Linux)
-propolis also sets the `user.containers.override_stat` extended attribute on
+go-microvm also sets the `user.containers.override_stat` extended attribute on
extracted files so that libkrun's virtiofs server reports correct ownership to
the guest. This is the same mechanism that podman uses on macOS.
@@ -478,11 +478,11 @@ See the `internal/xattr` package for details.
## SSH Client Security
The SSH client uses `InsecureIgnoreHostKey()` for host key verification.
-This is acceptable because the client only connects to VMs that propolis
+This is acceptable because the client only connects to VMs that go-microvm
just created -- the guest was booted from an image we pulled and configured,
and the connection is over a localhost port forward that is not exposed to
the network.
-If propolis is used in a scenario where the SSH connection traverses an
+If go-microvm is used in a scenario where the SSH connection traverses an
untrusted network, host key verification should be implemented by the
caller using a custom SSH client rather than the built-in one.
diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md
index cf72268..b0fc351 100644
--- a/docs/TROUBLESHOOTING.md
+++ b/docs/TROUBLESHOOTING.md
@@ -1,6 +1,6 @@
# Troubleshooting
-Common issues when using propolis and how to resolve them.
+Common issues when using go-microvm and how to resolve them.
## VM Fails to Start
@@ -28,28 +28,28 @@ sysctl kern.hv_support
### Code signing required (macOS)
-If propolis-runner crashes immediately with `EXC_BAD_ACCESS`, it needs the
+If go-microvm-runner crashes immediately with `EXC_BAD_ACCESS`, it needs the
hypervisor entitlement. See [docs/MACOS.md](MACOS.md).
## Log Files
-propolis writes log files to the data directory
-(`~/.config/propolis/` by default, or the path set via `WithDataDir()`):
+go-microvm writes log files to the data directory
+(`~/.config/go-microvm/` by default, or the path set via `WithDataDir()`):
| File | Contents |
|------|----------|
| `console.log` | Guest console output (kernel messages, init script) |
-| `vm.log` | propolis-runner stdout/stderr (libkrun errors) |
+| `vm.log` | go-microvm-runner stdout/stderr (libkrun errors) |
Networking logs are emitted via `log/slog` and appear in the application's
structured logging output rather than a separate file.
```bash
# Check for guest-side errors (kernel, init script)
-cat ~/.config/propolis/console.log
+cat ~/.config/go-microvm/console.log
# Check for host-side runner errors
-cat ~/.config/propolis/vm.log
+cat ~/.config/go-microvm/vm.log
```
## Port Conflicts
@@ -77,17 +77,17 @@ successfully by checking the application's log output for errors from
## Runner Binary Not Found
-propolis searches for `propolis-runner` in this order:
+go-microvm searches for `go-microvm-runner` in this order:
1. Explicit path via `libkrun.WithRunnerPath()` (passed to `libkrun.NewBackend()`)
2. System `$PATH`
3. Next to the calling executable
```bash
# Check if it's in PATH
-which propolis-runner
+which go-microvm-runner
# Build it (requires system libkrun-devel)
-cd propolis && task build-dev
+cd go-microvm && task build-dev
```
## Resource Limits
@@ -100,7 +100,7 @@ guests to 8 vCPUs. Requesting more will fail at `SetVMConfig()`.
### Memory
There is no hard memory limit from libkrun. The practical limit is
-available host RAM. propolis defaults to 512 MiB.
+available host RAM. go-microvm defaults to 512 MiB.
## Licensing
diff --git a/extract/source.go b/extract/source.go
index 259d23c..95a4015 100644
--- a/extract/source.go
+++ b/extract/source.go
@@ -9,9 +9,9 @@ import (
"os"
)
-// RunnerBinaryName is the expected filename for the propolis-runner binary
+// RunnerBinaryName is the expected filename for the go-microvm-runner binary
// within a runtime source directory.
-const RunnerBinaryName = "propolis-runner"
+const RunnerBinaryName = "go-microvm-runner"
// Source resolves a set of files into a directory, using cacheDir for
// extraction-based implementations. The context allows caller-implemented
@@ -58,7 +58,7 @@ func (s *dirSource) Ensure(_ context.Context, _ string) (string, error) {
return s.path, nil
}
-// RuntimeBundle creates a Source that extracts propolis-runner and libkrun
+// RuntimeBundle creates a Source that extracts go-microvm-runner and libkrun
// into a versioned cache directory. The runner and libkrun byte slices are
// the file contents to extract. The libkrun major soname version is always 1
// because the runner binary is built against a specific libkrun ABI.
diff --git a/extract/source_test.go b/extract/source_test.go
index 458ffd5..1f5d9a1 100644
--- a/extract/source_test.go
+++ b/extract/source_test.go
@@ -26,7 +26,7 @@ func TestRuntimeBundle_ExtractsFiles(t *testing.T) {
dir, err := src.Ensure(context.Background(), cacheDir)
require.NoError(t, err)
- // Verify propolis-runner.
+ // Verify go-microvm-runner.
got, err := os.ReadFile(filepath.Join(dir, RunnerBinaryName))
require.NoError(t, err)
assert.Equal(t, runnerData, got)
diff --git a/go.mod b/go.mod
index 1ebb289..ca0d598 100644
--- a/go.mod
+++ b/go.mod
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-module github.com/stacklok/propolis
+module github.com/stacklok/go-microvm
go 1.26.0
diff --git a/guest/boot/boot.go b/guest/boot/boot.go
index afa480d..217a4de 100644
--- a/guest/boot/boot.go
+++ b/guest/boot/boot.go
@@ -14,11 +14,11 @@ import (
"golang.org/x/crypto/ssh"
- "github.com/stacklok/propolis/guest/env"
- "github.com/stacklok/propolis/guest/harden"
- "github.com/stacklok/propolis/guest/mount"
- "github.com/stacklok/propolis/guest/netcfg"
- "github.com/stacklok/propolis/guest/sshd"
+ "github.com/stacklok/go-microvm/guest/env"
+ "github.com/stacklok/go-microvm/guest/harden"
+ "github.com/stacklok/go-microvm/guest/mount"
+ "github.com/stacklok/go-microvm/guest/netcfg"
+ "github.com/stacklok/go-microvm/guest/sshd"
)
// Run executes the full guest boot sequence and returns a shutdown function
diff --git a/guest/boot/options.go b/guest/boot/options.go
index 5c83df3..e6c3555 100644
--- a/guest/boot/options.go
+++ b/guest/boot/options.go
@@ -118,8 +118,8 @@ func WithSSHAgentForwarding(enabled bool) Option {
}
// WithTmpSize sets the size of the /tmp tmpfs in MiB. Defaults to 256 MiB when
-// 0 or not set. The value is read from /etc/propolis-vm.json when provided by
-// the host via [github.com/stacklok/propolis.WithTmpSize].
+// 0 or not set. The value is read from /etc/go-microvm.json when provided by
+// the host via [github.com/stacklok/go-microvm.WithTmpSize].
func WithTmpSize(mib uint32) Option {
return optionFunc(func(c *config) {
if mib > 0 {
diff --git a/guest/harden/seccomp_test.go b/guest/harden/seccomp_test.go
index 5ea6f95..f7e45f3 100644
--- a/guest/harden/seccomp_test.go
+++ b/guest/harden/seccomp_test.go
@@ -133,7 +133,7 @@ func TestBlockedSyscallsReturnsFourGroups(t *testing.T) {
func TestApplySeccompBlocksSyscalls(t *testing.T) {
t.Parallel()
- if os.Getenv("PROPOLIS_SECCOMP_CHILD") == "1" {
+ if os.Getenv("GO_MICROVM_SECCOMP_CHILD") == "1" {
// Child process: apply filter, probe blocked syscalls, print results.
runSeccompChild()
return
@@ -142,7 +142,7 @@ func TestApplySeccompBlocksSyscalls(t *testing.T) {
// Parent process: re-exec ourselves running only this test.
//nolint:gosec // Test helper — arguments are not user-controlled.
cmd := exec.Command(os.Args[0], "-test.run=^TestApplySeccompBlocksSyscalls$", "-test.v")
- cmd.Env = append(os.Environ(), "PROPOLIS_SECCOMP_CHILD=1")
+ cmd.Env = append(os.Environ(), "GO_MICROVM_SECCOMP_CHILD=1")
out, err := cmd.CombinedOutput()
output := string(out)
diff --git a/guest/netcfg/doc.go b/guest/netcfg/doc.go
index ad21e6e..1919981 100644
--- a/guest/netcfg/doc.go
+++ b/guest/netcfg/doc.go
@@ -4,7 +4,7 @@
//go:build linux
// Package netcfg configures guest networking inside a microVM. It brings up
-// eth0 with the guest IP from the propolis network topology, adds a default
+// eth0 with the guest IP from the go-microvm network topology, adds a default
// route via the gateway, and writes /etc/resolv.conf to point at the
// gateway's DNS service.
package netcfg
diff --git a/guest/netcfg/netcfg.go b/guest/netcfg/netcfg.go
index cb80990..abe6682 100644
--- a/guest/netcfg/netcfg.go
+++ b/guest/netcfg/netcfg.go
@@ -13,10 +13,10 @@ import (
"github.com/vishvananda/netlink"
- "github.com/stacklok/propolis/net/topology"
+ "github.com/stacklok/go-microvm/net/topology"
)
-// Configure brings up the guest network interface with the standard propolis
+// Configure brings up the guest network interface with the standard go-microvm
// topology: eth0 gets the guest IP (192.168.127.2/24), a default route via
// the gateway (192.168.127.1), and /etc/resolv.conf pointing at the gateway.
func Configure(logger *slog.Logger) error {
diff --git a/guest/netcfg/netcfg_test.go b/guest/netcfg/netcfg_test.go
index a232078..1b5f21d 100644
--- a/guest/netcfg/netcfg_test.go
+++ b/guest/netcfg/netcfg_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
- "github.com/stacklok/propolis/net/topology"
+ "github.com/stacklok/go-microvm/net/topology"
)
func TestConfigureRequiresRoot(t *testing.T) {
diff --git a/guest/sshd/doc.go b/guest/sshd/doc.go
index d66ffa4..c09d4e7 100644
--- a/guest/sshd/doc.go
+++ b/guest/sshd/doc.go
@@ -7,5 +7,5 @@
// public-key authentication, command execution with PTY support, environment
// variable injection, signal forwarding, and window-change handling. The
// server is designed to run inside a microVM as the primary remote access
-// mechanism, paired with the host-side ssh.Client from the propolis/ssh package.
+// mechanism, paired with the host-side ssh.Client from the go-microvm/ssh package.
package sshd
diff --git a/guest/vmconfig/vmconfig.go b/guest/vmconfig/vmconfig.go
index 436d452..644e123 100644
--- a/guest/vmconfig/vmconfig.go
+++ b/guest/vmconfig/vmconfig.go
@@ -11,7 +11,7 @@ import (
)
// GuestPath is the guest path where the host writes the VM config.
-const GuestPath = "/etc/propolis-vm.json"
+const GuestPath = "/etc/go-microvm.json"
// Config holds settings written by the host and read by the guest init.
// Zero values mean "use the built-in default" for each field.
@@ -21,7 +21,7 @@ type Config struct {
TmpSizeMiB uint32 `json:"tmp_size_mib,omitempty"`
}
-// Read loads the VM config from /etc/propolis-vm.json.
+// Read loads the VM config from /etc/go-microvm.json.
// Returns a zero-value Config (all defaults) if the file does not exist,
// ensuring backward compatibility with hosts that do not write the file.
func Read() (Config, error) {
diff --git a/hooks/doc.go b/hooks/doc.go
index 95b3963..6e109b5 100644
--- a/hooks/doc.go
+++ b/hooks/doc.go
@@ -6,5 +6,5 @@
// before VM boot.
//
// Functions return func(string, *image.OCIConfig) error which is structurally
-// identical to propolis.RootFSHook.
+// identical to microvm.RootFSHook.
package hooks
diff --git a/hooks/hooks.go b/hooks/hooks.go
index c9ece59..0b85bed 100644
--- a/hooks/hooks.go
+++ b/hooks/hooks.go
@@ -13,14 +13,14 @@ import (
"sort"
"strings"
- "github.com/stacklok/propolis/guest/vmconfig"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/internal/pathutil"
- "github.com/stacklok/propolis/internal/xattr"
+ "github.com/stacklok/go-microvm/guest/vmconfig"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/internal/pathutil"
+ "github.com/stacklok/go-microvm/internal/xattr"
)
// InjectVMConfig returns a RootFSHook that writes the given VM config as JSON
-// to /etc/propolis-vm.json inside the rootfs. The guest init reads this file
+// to /etc/go-microvm.json inside the rootfs. The guest init reads this file
// to configure mounts before the SSH server starts.
func InjectVMConfig(cfg vmconfig.Config) func(string, *image.OCIConfig) error {
return func(rootfsPath string, _ *image.OCIConfig) error {
diff --git a/hooks/hooks_test.go b/hooks/hooks_test.go
index 5bf2fac..7e25e69 100644
--- a/hooks/hooks_test.go
+++ b/hooks/hooks_test.go
@@ -14,7 +14,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/guest/vmconfig"
+ "github.com/stacklok/go-microvm/guest/vmconfig"
)
// chownCall records a single chown invocation.
@@ -71,14 +71,14 @@ func TestInjectVMConfig(t *testing.T) {
err := hook(rootfs, nil)
require.NoError(t, err)
- data, err := os.ReadFile(filepath.Join(rootfs, "etc", "propolis-vm.json"))
+ data, err := os.ReadFile(filepath.Join(rootfs, "etc", "go-microvm.json"))
require.NoError(t, err)
var got vmconfig.Config
require.NoError(t, json.Unmarshal(data, &got))
assert.Equal(t, tt.cfg, got)
- info, err := os.Stat(filepath.Join(rootfs, "etc", "propolis-vm.json"))
+ info, err := os.Stat(filepath.Join(rootfs, "etc", "go-microvm.json"))
require.NoError(t, err)
assert.Equal(t, os.FileMode(0o644), info.Mode().Perm())
})
diff --git a/hypervisor/libkrun/backend.go b/hypervisor/libkrun/backend.go
index 9751d0c..69f3f7b 100644
--- a/hypervisor/libkrun/backend.go
+++ b/hypervisor/libkrun/backend.go
@@ -9,16 +9,16 @@ import (
"os"
"path/filepath"
- "github.com/stacklok/propolis/extract"
- "github.com/stacklok/propolis/hypervisor"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/runner"
+ "github.com/stacklok/go-microvm/extract"
+ "github.com/stacklok/go-microvm/hypervisor"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/runner"
)
// Option configures a libkrun Backend.
type Option func(*Backend)
-// WithRunnerPath sets the path to the propolis-runner binary.
+// WithRunnerPath sets the path to the go-microvm-runner binary.
// When empty, the runner is found via $PATH or alongside the calling binary.
func WithRunnerPath(p string) Option { return func(b *Backend) { b.runnerPath = p } }
@@ -30,7 +30,7 @@ func WithLibDir(d string) Option { return func(b *Backend) { b.libDir = d } }
// When nil (default), the standard runner.DefaultSpawner is used.
func WithSpawner(s runner.Spawner) Option { return func(b *Backend) { b.spawner = s } }
-// WithRuntime sets a Source that provides propolis-runner and libkrun.
+// WithRuntime sets a Source that provides go-microvm-runner and libkrun.
// Mutually exclusive with WithRunnerPath and WithLibDir.
// When using bundle-based sources, WithCacheDir must also be set.
func WithRuntime(src extract.Source) Option { return func(b *Backend) { b.runtime = src } }
@@ -109,7 +109,7 @@ func (b *Backend) validate() error {
return nil
}
-// Start launches the VM via the propolis-runner subprocess.
+// Start launches the VM via the go-microvm-runner subprocess.
func (b *Backend) Start(ctx context.Context, cfg hypervisor.VMConfig) (hypervisor.VMHandle, error) {
if err := b.validate(); err != nil {
return nil, err
diff --git a/hypervisor/libkrun/backend_test.go b/hypervisor/libkrun/backend_test.go
index c9a3005..aa48e65 100644
--- a/hypervisor/libkrun/backend_test.go
+++ b/hypervisor/libkrun/backend_test.go
@@ -13,9 +13,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/extract"
- "github.com/stacklok/propolis/hypervisor"
- "github.com/stacklok/propolis/runner"
+ "github.com/stacklok/go-microvm/extract"
+ "github.com/stacklok/go-microvm/hypervisor"
+ "github.com/stacklok/go-microvm/runner"
)
func TestBackend_Name(t *testing.T) {
@@ -205,7 +205,7 @@ func (m *mockSource) Ensure(_ context.Context, cacheDir string) (string, error)
return m.dir, m.err
}
-// makeRuntimeDir creates a temp directory with a dummy propolis-runner binary.
+// makeRuntimeDir creates a temp directory with a dummy go-microvm-runner binary.
func makeRuntimeDir(t *testing.T) string {
t.Helper()
dir := t.TempDir()
@@ -387,7 +387,7 @@ func TestBackend_Start_FirmwareEnsureError(t *testing.T) {
func TestBackend_Start_RuntimeMissingRunner(t *testing.T) {
t.Parallel()
- // Dir exists but has no propolis-runner binary.
+ // Dir exists but has no go-microvm-runner binary.
emptyDir := t.TempDir()
b := NewBackend(
@@ -402,7 +402,7 @@ func TestBackend_Start_RuntimeMissingRunner(t *testing.T) {
_, err := b.Start(context.Background(), cfg)
require.Error(t, err)
- assert.Contains(t, err.Error(), "propolis-runner not found")
+ assert.Contains(t, err.Error(), "go-microvm-runner not found")
}
func TestBackend_Options_Sources(t *testing.T) {
diff --git a/hypervisor/libkrun/doc.go b/hypervisor/libkrun/doc.go
index d97cfca..dca3736 100644
--- a/hypervisor/libkrun/doc.go
+++ b/hypervisor/libkrun/doc.go
@@ -2,5 +2,5 @@
// SPDX-License-Identifier: Apache-2.0
// Package libkrun implements the hypervisor.Backend interface using
-// libkrun via the propolis-runner subprocess.
+// libkrun via the go-microvm-runner subprocess.
package libkrun
diff --git a/hypervisor/libkrun/handle.go b/hypervisor/libkrun/handle.go
index 65b83d7..7bc35ee 100644
--- a/hypervisor/libkrun/handle.go
+++ b/hypervisor/libkrun/handle.go
@@ -7,7 +7,7 @@ import (
"context"
"strconv"
- "github.com/stacklok/propolis/runner"
+ "github.com/stacklok/go-microvm/runner"
)
// processHandle wraps a runner.ProcessHandle as a hypervisor.VMHandle.
diff --git a/image/disk/decompress.go b/image/disk/decompress.go
index cadd5fa..6e2304e 100644
--- a/image/disk/decompress.go
+++ b/image/disk/decompress.go
@@ -16,7 +16,7 @@ import (
"github.com/klauspost/compress/zstd"
- "github.com/stacklok/propolis/image"
+ "github.com/stacklok/go-microvm/image"
)
// MaxDecompressedSize is the safety limit for decompression (30 GiB).
diff --git a/image/pull.go b/image/pull.go
index 7f914dd..572ca66 100644
--- a/image/pull.go
+++ b/image/pull.go
@@ -20,7 +20,7 @@ import (
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/mutate"
- "github.com/stacklok/propolis/internal/xattr"
+ "github.com/stacklok/go-microvm/internal/xattr"
"golang.org/x/sync/errgroup"
)
@@ -100,7 +100,7 @@ func PullWithFetcher(ctx context.Context, imageRef string, cache *Cache, fetcher
if cache != nil {
tmpDir, err = cache.TempDir()
} else {
- tmpDir, err = os.MkdirTemp("", "propolis-rootfs-*")
+ tmpDir, err = os.MkdirTemp("", "go-microvm-rootfs-*")
}
if err != nil {
return nil, fmt.Errorf("create temp dir for rootfs: %w", err)
diff --git a/image/tar_security.go b/image/tar_security.go
index e6d78c4..8019e0f 100644
--- a/image/tar_security.go
+++ b/image/tar_security.go
@@ -6,7 +6,7 @@ package image
import (
"os"
- "github.com/stacklok/propolis/internal/pathutil"
+ "github.com/stacklok/go-microvm/internal/pathutil"
)
// SanitizeTarPath validates and resolves a tar entry path to prevent path
diff --git a/internal/pathutil/doc.go b/internal/pathutil/doc.go
index 0560ca9..9f54aed 100644
--- a/internal/pathutil/doc.go
+++ b/internal/pathutil/doc.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-// Package pathutil provides path validation helpers shared across propolis
+// Package pathutil provides path validation helpers shared across go-microvm
// packages. The primary use case is verifying that a guest-relative path
// resolves within a root directory, preventing path traversal attacks via
// ".." components or absolute paths.
diff --git a/internal/procutil/doc.go b/internal/procutil/doc.go
index 625646f..36dfb75 100644
--- a/internal/procutil/doc.go
+++ b/internal/procutil/doc.go
@@ -2,5 +2,5 @@
// SPDX-License-Identifier: Apache-2.0
// Package procutil provides platform-specific process identity verification
-// utilities shared by the propolis library and runner packages.
+// utilities shared by the go-microvm library and runner packages.
package procutil
diff --git a/internal/version/doc.go b/internal/version/doc.go
index c106c5e..baa3f16 100644
--- a/internal/version/doc.go
+++ b/internal/version/doc.go
@@ -4,5 +4,5 @@
// Package version holds build-time version information injected via ldflags.
// The variables in this package are set by the linker during build:
//
-// go build -ldflags "-X github.com/stacklok/propolis/internal/version.Version=..."
+// go build -ldflags "-X github.com/stacklok/go-microvm/internal/version.Version=..."
package version
diff --git a/internal/xattr/doc.go b/internal/xattr/doc.go
index 82666de..9d1c27f 100644
--- a/internal/xattr/doc.go
+++ b/internal/xattr/doc.go
@@ -5,7 +5,7 @@
// attribute on macOS and Linux so that the virtiofs server reports correct
// guest-visible ownership and permissions for rootfs files.
//
-// When propolis extracts an OCI image, the host user ends up owning all
+// When go-microvm extracts an OCI image, the host user ends up owning all
// files because non-root cannot chown. libkrun's virtiofs server
// performs access checks against these host-side attributes, causing
// permission denied errors for guest processes running as UIDs that
diff --git a/krun/doc.go b/krun/doc.go
index 2edf42d..ab9d735 100644
--- a/krun/doc.go
+++ b/krun/doc.go
@@ -10,8 +10,8 @@
// The bindings are only available when CGO is enabled on Linux or macOS.
// Use [IsAvailable] to check at runtime whether libkrun is functional.
//
-// The primary consumer of this package is the propolis-runner binary
-// (runner/cmd/propolis-runner), which is spawned as a subprocess to run VMs.
-// The main propolis library does not link against libkrun directly; it
+// The primary consumer of this package is the go-microvm-runner binary
+// (runner/cmd/go-microvm-runner), which is spawned as a subprocess to run VMs.
+// The main go-microvm library does not link against libkrun directly; it
// communicates with libkrun through the runner subprocess.
package krun
diff --git a/propolis.go b/microvm.go
similarity index 95%
rename from propolis.go
rename to microvm.go
index a6e26e1..164e19e 100644
--- a/propolis.go
+++ b/microvm.go
@@ -1,19 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-// Package propolis provides a simple framework for running OCI container images
+// Package microvm provides a simple framework for running OCI container images
// as microVMs using libkrun.
//
// The happy path is a single function call:
//
-// vm, err := propolis.Run(ctx, "alpine:latest",
-// propolis.WithPorts(propolis.PortForward{Host: 8080, Guest: 80}),
+// vm, err := microvm.Run(ctx, "alpine:latest",
+// microvm.WithPorts(microvm.PortForward{Host: 8080, Guest: 80}),
// )
// defer vm.Stop(ctx)
//
// For advanced use cases, every layer is pluggable: custom init scripts,
// rootfs hooks, network providers, preflight checks, and post-boot hooks.
-package propolis
+package microvm
import (
"context"
@@ -27,15 +27,15 @@ import (
"syscall"
"time"
- "github.com/stacklok/propolis/guest/vmconfig"
- "github.com/stacklok/propolis/hooks"
- "github.com/stacklok/propolis/hypervisor"
- "github.com/stacklok/propolis/hypervisor/libkrun"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/net/firewall"
- "github.com/stacklok/propolis/net/hosted"
- rootfspkg "github.com/stacklok/propolis/rootfs"
- "github.com/stacklok/propolis/state"
+ "github.com/stacklok/go-microvm/guest/vmconfig"
+ "github.com/stacklok/go-microvm/hooks"
+ "github.com/stacklok/go-microvm/hypervisor"
+ "github.com/stacklok/go-microvm/hypervisor/libkrun"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/net/firewall"
+ "github.com/stacklok/go-microvm/net/hosted"
+ rootfspkg "github.com/stacklok/go-microvm/rootfs"
+ "github.com/stacklok/go-microvm/state"
)
// Run pulls an OCI image and boots it as a microVM. It is the primary entry
diff --git a/propolis_test.go b/microvm_test.go
similarity index 98%
rename from propolis_test.go
rename to microvm_test.go
index 6fa019d..d472060 100644
--- a/propolis_test.go
+++ b/microvm_test.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-package propolis
+package microvm
import (
"context"
@@ -17,12 +17,12 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/hypervisor"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/internal/testutil"
- "github.com/stacklok/propolis/net/firewall"
- "github.com/stacklok/propolis/preflight"
- "github.com/stacklok/propolis/state"
+ "github.com/stacklok/go-microvm/hypervisor"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/internal/testutil"
+ "github.com/stacklok/go-microvm/net/firewall"
+ "github.com/stacklok/go-microvm/preflight"
+ "github.com/stacklok/go-microvm/state"
)
// --- Pure function tests ---
@@ -304,7 +304,7 @@ func TestForceRemoveAll(t *testing.T) {
t.Run("no error on nonexistent path", func(t *testing.T) {
t.Parallel()
- require.NoError(t, forceRemoveAll("/tmp/does-not-exist-propolis-test"))
+ require.NoError(t, forceRemoveAll("/tmp/does-not-exist-go-microvm-test"))
})
}
diff --git a/net/doc.go b/net/doc.go
index 8e04465..e49189b 100644
--- a/net/doc.go
+++ b/net/doc.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-// Package net defines the networking abstraction for propolis microVMs.
+// Package net defines the networking abstraction for go-microvm microVMs.
//
// A [Provider] manages the lifecycle of a network backend that connects the
// host to the guest VM. The default implementation uses an in-process
diff --git a/net/egress/frame.go b/net/egress/frame.go
index 53d2c12..47ee014 100644
--- a/net/egress/frame.go
+++ b/net/egress/frame.go
@@ -7,7 +7,7 @@ import (
"encoding/binary"
"fmt"
- "github.com/stacklok/propolis/net/firewall"
+ "github.com/stacklok/go-microvm/net/firewall"
)
const (
diff --git a/net/egress/frame_test.go b/net/egress/frame_test.go
index 370a103..f5dbdd0 100644
--- a/net/egress/frame_test.go
+++ b/net/egress/frame_test.go
@@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/net/firewall"
+ "github.com/stacklok/go-microvm/net/firewall"
)
// buildTestUDPFrame constructs a minimal Ethernet + IPv4 + UDP frame with
diff --git a/net/egress/interceptor.go b/net/egress/interceptor.go
index 438fe98..0dcef13 100644
--- a/net/egress/interceptor.go
+++ b/net/egress/interceptor.go
@@ -8,7 +8,7 @@ import (
"net"
"time"
- "github.com/stacklok/propolis/net/firewall"
+ "github.com/stacklok/go-microvm/net/firewall"
)
const (
diff --git a/net/egress/interceptor_test.go b/net/egress/interceptor_test.go
index 41c368d..47b0a2d 100644
--- a/net/egress/interceptor_test.go
+++ b/net/egress/interceptor_test.go
@@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/net/firewall"
+ "github.com/stacklok/go-microvm/net/firewall"
)
// buildDNSQueryFrame builds a complete Ethernet frame containing a DNS query.
diff --git a/net/hosted/doc.go b/net/hosted/doc.go
index e266654..dca703c 100644
--- a/net/hosted/doc.go
+++ b/net/hosted/doc.go
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// Package hosted implements a [net.Provider] that runs the gvisor-tap-vsock
-// VirtualNetwork in the caller's process rather than inside propolis-runner.
+// VirtualNetwork in the caller's process rather than inside go-microvm-runner.
//
// This enables callers to access the VirtualNetwork directly — for example,
// to create in-process TCP listeners via gonet that are reachable from the
@@ -11,9 +11,9 @@
// # Usage
//
// p := hosted.NewProvider()
-// vm, err := propolis.Run(ctx, image,
-// propolis.WithNetProvider(p),
-// propolis.WithPorts(propolis.PortForward{Host: sshPort, Guest: 22}),
+// vm, err := microvm.Run(ctx, image,
+// microvm.WithNetProvider(p),
+// microvm.WithPorts(microvm.PortForward{Host: sshPort, Guest: 22}),
// )
// // p.VirtualNetwork() is now available for gonet listeners.
//
@@ -25,10 +25,10 @@
//
// p := hosted.NewProvider()
// p.AddService(hosted.Service{Port: 4483, Handler: myHandler})
-// vm, err := propolis.Run(ctx, image, propolis.WithNetProvider(p))
+// vm, err := microvm.Run(ctx, image, microvm.WithNetProvider(p))
// // Guest can reach http://192.168.127.1:4483/
//
-// The provider exposes a Unix socket that propolis-runner connects to. Frames
+// The provider exposes a Unix socket that go-microvm-runner connects to. Frames
// are bridged between the runner connection and the VirtualNetwork's QEMU
// transport. When firewall rules are configured, a [firewall.Relay] is
// inserted to filter traffic.
diff --git a/net/hosted/provider.go b/net/hosted/provider.go
index dbaa74c..21430c0 100644
--- a/net/hosted/provider.go
+++ b/net/hosted/provider.go
@@ -15,17 +15,17 @@ import (
"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/containers/gvisor-tap-vsock/pkg/virtualnetwork"
- "github.com/stacklok/propolis/internal/logbridge"
- propnet "github.com/stacklok/propolis/net"
- "github.com/stacklok/propolis/net/egress"
- "github.com/stacklok/propolis/net/firewall"
- "github.com/stacklok/propolis/net/topology"
+ "github.com/stacklok/go-microvm/internal/logbridge"
+ propnet "github.com/stacklok/go-microvm/net"
+ "github.com/stacklok/go-microvm/net/egress"
+ "github.com/stacklok/go-microvm/net/firewall"
+ "github.com/stacklok/go-microvm/net/topology"
)
const socketName = "hosted-net.sock"
// Provider runs a gvisor-tap-vsock VirtualNetwork in the caller's process
-// and exposes a Unix socket for propolis-runner to connect to.
+// and exposes a Unix socket for go-microvm-runner to connect to.
type Provider struct {
mu sync.Mutex
vn *virtualnetwork.VirtualNetwork
@@ -119,7 +119,7 @@ func (p *Provider) Start(ctx context.Context, cfg propnet.Config) error {
return nil
}
-// SocketPath returns the path to the Unix socket for propolis-runner.
+// SocketPath returns the path to the Unix socket for go-microvm-runner.
func (p *Provider) SocketPath() string {
p.mu.Lock()
defer p.mu.Unlock()
@@ -250,7 +250,7 @@ func (p *Provider) buildEgressRelay(ctx context.Context, cfg propnet.Config) *fi
return firewall.NewRelayWithDNSHook(filter, interceptor)
}
-// acceptLoop accepts connections from propolis-runner and bridges them
+// acceptLoop accepts connections from go-microvm-runner and bridges them
// to the VirtualNetwork.
func (p *Provider) acceptLoop() {
defer p.wg.Done()
diff --git a/net/hosted/provider_test.go b/net/hosted/provider_test.go
index 597c1d8..10382bb 100644
--- a/net/hosted/provider_test.go
+++ b/net/hosted/provider_test.go
@@ -14,9 +14,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/internal/testutil"
- propnet "github.com/stacklok/propolis/net"
- "github.com/stacklok/propolis/net/firewall"
+ "github.com/stacklok/go-microvm/internal/testutil"
+ propnet "github.com/stacklok/go-microvm/net"
+ "github.com/stacklok/go-microvm/net/firewall"
)
// freePort returns a TCP port that is currently available on localhost.
diff --git a/net/hosted/service.go b/net/hosted/service.go
index 7192158..9127efd 100644
--- a/net/hosted/service.go
+++ b/net/hosted/service.go
@@ -11,7 +11,7 @@ import (
"net/http"
"time"
- "github.com/stacklok/propolis/net/topology"
+ "github.com/stacklok/go-microvm/net/topology"
)
// Service describes an HTTP service to expose inside the virtual network.
diff --git a/net/hosted/service_test.go b/net/hosted/service_test.go
index 497848d..bcbf1ce 100644
--- a/net/hosted/service_test.go
+++ b/net/hosted/service_test.go
@@ -11,8 +11,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/internal/testutil"
- propnet "github.com/stacklok/propolis/net"
+ "github.com/stacklok/go-microvm/internal/testutil"
+ propnet "github.com/stacklok/go-microvm/net"
)
func TestAddServiceBeforeStart(t *testing.T) {
diff --git a/net/provider.go b/net/provider.go
index 10abcf4..f2b70e7 100644
--- a/net/provider.go
+++ b/net/provider.go
@@ -6,7 +6,7 @@ package net
import (
"context"
- "github.com/stacklok/propolis/net/firewall"
+ "github.com/stacklok/go-microvm/net/firewall"
)
// PortForward describes a TCP port forwarding rule from host to guest.
diff --git a/net/topology/doc.go b/net/topology/doc.go
index 3c3f625..e646940 100644
--- a/net/topology/doc.go
+++ b/net/topology/doc.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-// Package topology defines shared network topology constants for propolis
+// Package topology defines shared network topology constants for go-microvm
// microVMs. These constants describe the virtual network layout used by
// gvisor-tap-vsock: subnet, gateway, guest IP, MAC address, and MTU.
//
diff --git a/net/topology/topology.go b/net/topology/topology.go
index e9da13e..07ad405 100644
--- a/net/topology/topology.go
+++ b/net/topology/topology.go
@@ -3,7 +3,7 @@
package topology
-// Network topology constants for the propolis virtual network.
+// Network topology constants for the go-microvm virtual network.
// These match the gvisor-tap-vsock defaults used by libkrun/krunvm.
const (
// Subnet is the CIDR notation for the virtual network subnet.
diff --git a/options.go b/options.go
index f4c9c8f..e262ec2 100644
--- a/options.go
+++ b/options.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-package propolis
+package microvm
import (
"context"
@@ -9,11 +9,11 @@ import (
"path/filepath"
"syscall"
- "github.com/stacklok/propolis/hypervisor"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/net"
- "github.com/stacklok/propolis/net/firewall"
- "github.com/stacklok/propolis/preflight"
+ "github.com/stacklok/go-microvm/hypervisor"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/net"
+ "github.com/stacklok/go-microvm/net/firewall"
+ "github.com/stacklok/go-microvm/preflight"
)
// Option configures a VM. Use the With* functions to create options.
@@ -91,7 +91,7 @@ type config struct {
func defaultConfig() *config {
dataDir := defaultDataDir()
return &config{
- name: "propolis",
+ name: "microvm",
cpus: 1,
memory: 512,
ports: nil,
@@ -113,14 +113,14 @@ func defaultConfig() *config {
}
func defaultDataDir() string {
- if dir := os.Getenv("PROPOLIS_DATA_DIR"); dir != "" {
+ if dir := os.Getenv("GO_MICROVM_DATA_DIR"); dir != "" {
return dir
}
home, err := os.UserHomeDir()
if err != nil {
home = "/tmp"
}
- return filepath.Join(home, ".config", "propolis")
+ return filepath.Join(home, ".config", "go-microvm")
}
func (c *config) buildNetConfig() net.Config {
@@ -150,7 +150,7 @@ func (c *config) buildNetConfig() net.Config {
// --- Option constructors ---
-// WithName sets the VM name. Defaults to "propolis".
+// WithName sets the VM name. Defaults to "microvm".
func WithName(name string) Option {
return optionFunc(func(c *config) { c.name = name })
}
@@ -215,7 +215,7 @@ func WithFirewallDefaultAction(action firewall.Action) Option {
// WithPreflightChecker replaces the entire preflight checker. Use this when
// the caller manages its own preflight logic and wants to skip the built-in
// defaults (KVM, port availability, disk space). Pass [preflight.NewEmpty]()
-// to disable all propolis preflight checks.
+// to disable all microvm preflight checks.
func WithPreflightChecker(checker preflight.Checker) Option {
return optionFunc(func(c *config) { c.preflight = checker })
}
@@ -242,7 +242,7 @@ func WithBackend(b hypervisor.Backend) Option {
}
// WithDataDir sets the base directory for VM state, caches, and logs.
-// Defaults to ~/.config/propolis or $PROPOLIS_DATA_DIR.
+// Defaults to ~/.config/go-microvm or $GO_MICROVM_DATA_DIR.
func WithDataDir(path string) Option {
return optionFunc(func(c *config) {
c.dataDir = path
@@ -303,7 +303,7 @@ func WithLogLevel(level uint32) Option {
// Defaults to 256 MiB when 0 or not set. The kernel enforces available
// memory as the upper bound; unreasonable values will cause a mount failure
// inside the guest.
-// The value is written to /etc/propolis-vm.json in the rootfs and read by
+// The value is written to /etc/go-microvm.json in the rootfs and read by
// the guest init before mounting filesystems.
func WithTmpSize(mib uint32) Option {
return optionFunc(func(c *config) { c.tmpSizeMiB = mib })
diff --git a/options_test.go b/options_test.go
index 5ec00ec..914ac96 100644
--- a/options_test.go
+++ b/options_test.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-package propolis
+package microvm
import (
"context"
@@ -10,9 +10,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/image"
- "github.com/stacklok/propolis/net/firewall"
- "github.com/stacklok/propolis/preflight"
+ "github.com/stacklok/go-microvm/image"
+ "github.com/stacklok/go-microvm/net/firewall"
+ "github.com/stacklok/go-microvm/preflight"
)
func TestDefaultConfig(t *testing.T) {
@@ -23,7 +23,7 @@ func TestDefaultConfig(t *testing.T) {
assert.Equal(t, uint32(1), cfg.cpus)
assert.Equal(t, uint32(512), cfg.memory)
- assert.Equal(t, "propolis", cfg.name)
+ assert.Equal(t, "microvm", cfg.name)
assert.NotNil(t, cfg.preflight)
assert.Nil(t, cfg.netProvider) // lazy-initialized in Run() when not set by WithNetProvider
assert.NotNil(t, cfg.imageCache)
diff --git a/preflight/chown_linux.go b/preflight/chown_linux.go
index 57af90b..a32f799 100644
--- a/preflight/chown_linux.go
+++ b/preflight/chown_linux.go
@@ -45,7 +45,7 @@ func (c *chownChecker) check(_ context.Context) error {
return fmt.Errorf("process lacks CAP_CHOWN: extracted rootfs files will have incorrect ownership, " +
"which may cause permission errors inside the guest; " +
- "grant CAP_CHOWN to the propolis process or run as root")
+ "grant CAP_CHOWN to the go-microvm process or run as root")
}
// getEffectiveCaps returns the low 32 bits of the effective capability set
diff --git a/rootfs/clone.go b/rootfs/clone.go
index 348601b..3f801a9 100644
--- a/rootfs/clone.go
+++ b/rootfs/clone.go
@@ -12,7 +12,7 @@ import (
"path/filepath"
"strings"
- "github.com/stacklok/propolis/internal/xattr"
+ "github.com/stacklok/go-microvm/internal/xattr"
)
// CloneDir recursively clones srcDir into dstDir using platform-native COW
diff --git a/rootfs/clone_test.go b/rootfs/clone_test.go
index b2f8aa1..ca9f550 100644
--- a/rootfs/clone_test.go
+++ b/rootfs/clone_test.go
@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/rootfs"
+ "github.com/stacklok/go-microvm/rootfs"
)
func TestCloneDir(t *testing.T) {
diff --git a/runner/cmd/propolis-runner/main.go b/runner/cmd/go-microvm-runner/main.go
similarity index 96%
rename from runner/cmd/propolis-runner/main.go
rename to runner/cmd/go-microvm-runner/main.go
index 4617c1b..3a41d6b 100644
--- a/runner/cmd/propolis-runner/main.go
+++ b/runner/cmd/go-microvm-runner/main.go
@@ -3,8 +3,8 @@
//go:build (linux || darwin) && cgo
-// Package main provides the propolis-runner helper binary.
-// This binary is spawned as a subprocess by the propolis framework
+// Package main provides the go-microvm-runner helper binary.
+// This binary is spawned as a subprocess by the go-microvm framework
// to run VMs using libkrun's CGO bindings.
//
// IMPORTANT: libkrun's krun_start_enter() takes over the calling process
@@ -25,9 +25,9 @@ import (
"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/containers/gvisor-tap-vsock/pkg/virtualnetwork"
- "github.com/stacklok/propolis/internal/logbridge"
- "github.com/stacklok/propolis/krun"
- "github.com/stacklok/propolis/net/topology"
+ "github.com/stacklok/go-microvm/internal/logbridge"
+ "github.com/stacklok/go-microvm/krun"
+ "github.com/stacklok/go-microvm/net/topology"
)
// sentinel errors for classifying exit codes.
@@ -86,7 +86,7 @@ const (
func main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "Usage: %s \n", filepath.Base(os.Args[0]))
- fmt.Fprintf(os.Stderr, "\nThis is a helper binary for propolis.\n")
+ fmt.Fprintf(os.Stderr, "\nThis is a helper binary for go-microvm.\n")
fmt.Fprintf(os.Stderr, "It should not be run directly.\n")
os.Exit(exitConfigError)
}
diff --git a/runner/config.go b/runner/config.go
index ea63c6d..7aa2b86 100644
--- a/runner/config.go
+++ b/runner/config.go
@@ -11,7 +11,7 @@ type PortForward struct {
Guest uint16 `json:"guest"`
}
-// Config contains the configuration for running a VM via the propolis-runner subprocess.
+// Config contains the configuration for running a VM via the go-microvm-runner subprocess.
type Config struct {
// RootPath is the path to the root filesystem directory (virtiofs).
RootPath string `json:"root_path"`
@@ -38,7 +38,7 @@ type Config struct {
// libraries. The runner subprocess uses this via LD_LIBRARY_PATH.
// Not serialized to JSON; set by the caller before spawning.
LibDir string `json:"-"`
- // RunnerPath is the explicit path to the propolis-runner binary.
+ // RunnerPath is the explicit path to the go-microvm-runner binary.
// Not serialized to JSON; used by Spawn to locate the binary.
RunnerPath string `json:"-"`
// VMLogPath is the path to the file where runner stdout/stderr is written.
diff --git a/runner/config_test.go b/runner/config_test.go
index 0e41e05..b164ba9 100644
--- a/runner/config_test.go
+++ b/runner/config_test.go
@@ -15,7 +15,7 @@ func TestConfig_MarshalUnmarshal_RoundTrip(t *testing.T) {
t.Parallel()
original := Config{
- RootPath: "/var/lib/propolis/rootfs",
+ RootPath: "/var/lib/go-microvm/rootfs",
NumVCPUs: 4,
RAMMiB: 1024,
NetSocket: "/tmp/net.sock",
@@ -24,7 +24,7 @@ func TestConfig_MarshalUnmarshal_RoundTrip(t *testing.T) {
LogLevel: 3,
// These should NOT appear in JSON.
LibDir: "/usr/local/lib/krun",
- RunnerPath: "/usr/bin/propolis-runner",
+ RunnerPath: "/usr/bin/go-microvm-runner",
VMLogPath: "/var/log/vm.log",
}
diff --git a/runner/process_darwin.go b/runner/process_darwin.go
index 4455c70..97d4d92 100644
--- a/runner/process_darwin.go
+++ b/runner/process_darwin.go
@@ -5,7 +5,7 @@
package runner
-import "github.com/stacklok/propolis/internal/procutil"
+import "github.com/stacklok/go-microvm/internal/procutil"
// isExpectedProcess checks if the process at pid is running the expected binary.
// Delegates to the shared implementation in internal/procutil.
diff --git a/runner/process_linux.go b/runner/process_linux.go
index 52a6400..6cf3d34 100644
--- a/runner/process_linux.go
+++ b/runner/process_linux.go
@@ -5,7 +5,7 @@
package runner
-import "github.com/stacklok/propolis/internal/procutil"
+import "github.com/stacklok/go-microvm/internal/procutil"
// isExpectedProcess checks if the process at pid is running the expected binary.
// Delegates to the shared implementation in internal/procutil.
diff --git a/runner/spawn.go b/runner/spawn.go
index adba6e8..960e894 100644
--- a/runner/spawn.go
+++ b/runner/spawn.go
@@ -24,8 +24,8 @@ var (
)
const (
- // runnerBinaryName is the name of the propolis-runner binary.
- runnerBinaryName = "propolis-runner"
+ // runnerBinaryName is the name of the go-microvm-runner binary.
+ runnerBinaryName = "go-microvm-runner"
// stopTimeout is the maximum time to wait for the process to exit after SIGTERM.
stopTimeout = 30 * time.Second
// stopPollInterval is the interval between process liveness checks during stop.
@@ -46,7 +46,7 @@ func newProcessDeps() processDeps {
}
}
-// runnerFinder locates the propolis-runner binary with injectable lookups.
+// runnerFinder locates the go-microvm-runner binary with injectable lookups.
type runnerFinder struct {
stat func(string) (os.FileInfo, error)
lookPath func(string) (string, error)
@@ -86,13 +86,13 @@ func (p *Process) killTarget() int {
return -p.pid
}
-// Spawn starts the propolis-runner binary as a detached subprocess.
+// Spawn starts the go-microvm-runner binary as a detached subprocess.
// Deprecated: Use SpawnProcess or DefaultSpawner instead.
func Spawn(ctx context.Context, cfg Config) (*Process, error) {
return SpawnProcess(ctx, cfg)
}
-// SpawnProcess starts the propolis-runner binary as a detached subprocess.
+// SpawnProcess starts the go-microvm-runner binary as a detached subprocess.
// The runner binary receives the VM configuration as a JSON string in argv[1].
// On success, the returned Process can be used to monitor and stop the VM.
func SpawnProcess(ctx context.Context, cfg Config) (*Process, error) {
@@ -244,7 +244,7 @@ func (p *Process) IsAlive() bool {
return true
}
-// find locates the propolis-runner binary. It checks, in order:
+// find locates the go-microvm-runner binary. It checks, in order:
// 1. The explicit path provided in cfg.RunnerPath
// 2. The system PATH
// 3. Next to the current executable
diff --git a/state/state.go b/state/state.go
index 04ffc7d..3553595 100644
--- a/state/state.go
+++ b/state/state.go
@@ -26,13 +26,13 @@ const (
stateVersion = 1
// stateFileName is the name of the state JSON file within the data directory.
- // Named "propolis-state.json" to avoid collision with the caller's own
+ // Named "go-microvm-state.json" to avoid collision with the caller's own
// state file (e.g. toolhive-appliance's "state.json") when both share
// the same dataDir.
- stateFileName = "propolis-state.json"
+ stateFileName = "go-microvm-state.json"
// lockFileName is the name of the lock file within the data directory.
- lockFileName = "propolis-state.lock"
+ lockFileName = "go-microvm-state.lock"
// retryInterval is the interval between lock acquisition retries.
retryInterval = 500 * time.Millisecond
diff --git a/vm.go b/vm.go
index e4972a5..774a04e 100644
--- a/vm.go
+++ b/vm.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-package propolis
+package microvm
import (
"context"
@@ -12,9 +12,9 @@ import (
"strings"
"time"
- "github.com/stacklok/propolis/hypervisor"
- "github.com/stacklok/propolis/net"
- "github.com/stacklok/propolis/state"
+ "github.com/stacklok/go-microvm/hypervisor"
+ "github.com/stacklok/go-microvm/net"
+ "github.com/stacklok/go-microvm/state"
)
// VM represents a running microVM.
diff --git a/vm_test.go b/vm_test.go
index 968deec..9c0a346 100644
--- a/vm_test.go
+++ b/vm_test.go
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
// SPDX-License-Identifier: Apache-2.0
-package propolis
+package microvm
import (
"context"
@@ -13,8 +13,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "github.com/stacklok/propolis/net"
- "github.com/stacklok/propolis/state"
+ "github.com/stacklok/go-microvm/net"
+ "github.com/stacklok/go-microvm/state"
)
// mockVMHandle is a test double for hypervisor.VMHandle.