Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- os: the Yocto guest-OS backend (`os/yocto/`) is deprecated in favor of mkosi (`os/mkosi/`), which is now the default and recommended backend. `os/build.sh` defaults to `--backend mkosi`, and `make os-image` / `make os-repro-check` build with mkosi. The Yocto builds move to `make os-image-yocto` / `make os-repro-check-yocto`; `make os-image-mkosi` / `make os-repro-check-mkosi` remain as aliases. Every Yocto entrypoint prints a deprecation warning, and the backend is kept only to rebuild existing Yocto images. The mkosi build still reads patches, units and scripts from `os/yocto/`, so the directory stays until those files move

### Removed
- vmm: pulling guest images from an OCI registry, together with the `[image] registry` setting, the `ListRegistryImages` and `PullRegistryImage` RPCs, the registry section of the Images panel, and `os/image/dstack-image-oci.sh`. Guest images are not published to a registry, so the feature had no users. A leftover `registry` line in `vmm.toml` is ignored; install images into the local image directory instead
- verifier: the `debug` request field and the `acpi_tables` / `rtmr_debug` response fields. The per-event RTMR diff never had the events it diffed, so it reported every expected digest as missing. Requests that still send `debug` are accepted and the field is ignored.
- sdk: `TlsKeyOptions.path` in the JavaScript SDK. `GetTlsKeyArgs` has no such field and `getTlsKey` never read it, so a caller who set it was silently ignored. Breaking at the type level only, and only for code whose value was already being discarded. `deriveKey`'s `path` is a real, deprecated Tappd-era parameter and stays; the Python, Rust and Go v0 TLS-key options never carried one
- guest-agent: the `EmitEvent` RPC no longer records anything -- runtime RTMR3 events are system-owned in 0.6.0, so an app can no longer extend the measurement chain. The method itself stays on the unversioned path and always fails with an error naming the removal, rather than being deleted outright: a deleted method answers HTTP 404 `Service not found: EmitEvent`, which tells a 0.5.x caller nothing about why its events stopped being recorded, while the kept stub fails with a message naming the removal and pointing at `report_data`. **Breaking:** any app extending RTMR3 at runtime must stop; bind app data through `report_data` instead, which is what most callers wanted anyway
Expand Down
53 changes: 0 additions & 53 deletions docs/tutorials/guest-image-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,59 +241,6 @@ The `image_path` should point to `/var/lib/dstack/images`.

If VMM isn't finding the images, verify the path in the configuration matches where you installed them.

## OCI Registry Setup

Guest images can be stored in any OCI-compatible container registry (Docker Hub, GHCR, Harbor, etc.), allowing VMM to discover and pull images directly from the web UI.

### Pushing Images to a Registry

Use the `dstack-image-oci.sh` script to package and push a guest image directory:

```bash
# Push a standard image (auto-tags: version + sha256-hash)
./os/image/dstack-image-oci.sh push /var/lib/dstack/images/dstack-0.6.0 ghcr.io/your-org/guest-image

# Current unified image is also used on NVIDIA hosts
./os/image/dstack-image-oci.sh push /var/lib/dstack/images/dstack-0.6.0 ghcr.io/your-org/guest-image --tag 0.6.0

# Push with a custom tag
./os/image/dstack-image-oci.sh push /var/lib/dstack/images/dstack-0.6.0 ghcr.io/your-org/guest-image --tag latest

# List tags in the registry
./os/image/dstack-image-oci.sh list ghcr.io/your-org/guest-image
```

The script reads `metadata.json` and `digest.txt` from the image directory and auto-generates tags:

| Image directory | Generated tags |
|---|---|
| `dstack-0.5.8` | `0.5.8`, `sha256-<hash>` |
| `dstack-dev-0.5.8` | `dev-0.5.8`, `sha256-<hash>` |
| `dstack-nvidia-0.5.8` | `nvidia-0.5.8`, `sha256-<hash>` |

Prerequisites: `docker` CLI (for building), `python3`, registry login (`docker login`).

### Configuring VMM to Use a Registry

Add the `[image]` section to `vmm.toml`:

```toml
[image]
# Local image directory (default: ~/.dstack-vmm/image)
# path = "/var/lib/dstack/images"

# OCI registry for discovering and pulling images
registry = "ghcr.io/your-org/guest-image"
```

After restarting VMM, click **Images** in the web UI to browse the registry. Click **Pull** to download an image — it will be extracted to the local image directory automatically.

### How It Works

- **Push**: The script builds a `FROM scratch` Docker image containing the guest image files (kernel, initrd, rootfs, firmware, metadata) and pushes it to the registry.
- **Pull**: VMM fetches the OCI manifest via the Registry HTTP API v2, downloads each layer blob, and extracts the tar contents into the local image directory. No Docker daemon required on the VMM host.
- **Discovery**: VMM queries the registry's tag list API to show available versions alongside locally installed images.

## Managing Multiple Image Versions

You can have multiple image versions installed simultaneously:
Expand Down
3 changes: 0 additions & 3 deletions dstack/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions dstack/vmm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,7 @@ fatfs.workspace = true
fscommon.workspace = true
or-panic.workspace = true
url.workspace = true
reqwest.workspace = true
rand.workspace = true
flate2.workspace = true
tar.workspace = true
tempfile.workspace = true
wait-timeout.workspace = true
listenfd.workspace = true
Expand Down
27 changes: 0 additions & 27 deletions dstack/vmm/rpc/proto/vmm_rpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -437,10 +437,6 @@ service Vmm {
// Remove a stopped supervisor process by ID.
rpc SvRemove(Id) returns (google.protobuf.Empty);

// List images available in the configured OCI registry.
rpc ListRegistryImages(google.protobuf.Empty) returns (RegistryImageListResponse);
// Pull an image from the OCI registry to local storage.
rpc PullRegistryImage(PullRegistryImageRequest) returns (google.protobuf.Empty);
// Delete a local guest image by name.
rpc DeleteImage(Id) returns (google.protobuf.Empty);
}
Expand All @@ -450,29 +446,6 @@ message SvListResponse {
repeated SvProcessInfo processes = 1;
}

// Available images discovered from the OCI registry.
message RegistryImageListResponse {
repeated RegistryImageInfo images = 1;
}

// Metadata for an image tag in the OCI registry.
message RegistryImageInfo {
// Tag name (e.g., "0.5.8", "nvidia-0.5.8")
string tag = 1;
// Whether this image is already downloaded locally
bool local = 2;
// Whether this image is currently being pulled
bool pulling = 3;
// Error message from the last failed pull attempt (empty if no error)
string error = 4;
}

// Request to pull an image from the OCI registry.
message PullRegistryImageRequest {
// Tag to pull (e.g., "0.5.8")
string tag = 1;
}

// Information about a single supervisor process.
message SvProcessInfo {
string id = 1;
Expand Down
10 changes: 0 additions & 10 deletions dstack/vmm/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ mod image;
mod mr_config;
pub(crate) mod network;
mod qemu;
pub(crate) mod registry;
mod vm_info;
mod workdir;

Expand Down Expand Up @@ -302,12 +301,6 @@ pub struct GpuSpec {
pub slot: String,
}

#[derive(Clone, Debug)]
pub(crate) enum PullStatus {
Pulling,
Failed(String),
}

/// First delay before a removal asks netd again to release a VM's interfaces.
#[cfg(not(test))]
const RELEASE_RETRY_INITIAL: Duration = Duration::from_secs(2);
Expand All @@ -321,8 +314,6 @@ pub struct App {
pub config: Arc<Config>,
pub supervisor: SupervisorClient,
state: Arc<Mutex<AppState>>,
/// Pull status for registry images: tag → status.
pub(crate) pull_status: Arc<Mutex<std::collections::HashMap<String, PullStatus>>>,
/// One lock per VM, held across a launch or a teardown. See
/// [`App::launch_lock`].
launch_locks: Arc<Mutex<HashMap<String, Arc<tokio::sync::Mutex<()>>>>>,
Expand Down Expand Up @@ -356,7 +347,6 @@ impl App {
removing: HashSet::new(),
})),
config: Arc::new(config),
pull_status: Arc::new(Mutex::new(std::collections::HashMap::new())),
launch_locks: Arc::new(Mutex::new(HashMap::new())),
}
}
Expand Down
Loading
Loading