Skip to content

verity volumes: attach verified read-only data disks to CVMs#752

Open
h4x3rotab wants to merge 23 commits into
masterfrom
verity-volumes
Open

verity volumes: attach verified read-only data disks to CVMs#752
h4x3rotab wants to merge 23 commits into
masterfrom
verity-volumes

Conversation

@h4x3rotab

@h4x3rotab h4x3rotab commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What this does

Adds generic read-only verity data volumes to CVMs. An operator builds or wraps a filesystem image, places it in the VMM's configured volumes_dir, and attaches it by name at deploy time. The guest discovers the disk, verifies it against the root measured in app-compose.json, and mounts it read-only at the requested absolute path.

How it fits together

  • dstack verity --dir <path> packs a directory into a reproducible squashfs volume.
  • dstack verity --fs-image <path> wraps an existing filesystem image.
  • Each disk uses a generic DSTACK_VOLUME envelope in partition 1, filesystem data in partition 2, and the dm-verity superblock/hash tree in partition 3.
  • The VMM resolves bare volume names under cvm.volumes_dir and attaches the raw disks read-only.
  • The guest dstack-volume helper scans /sys/class/block, matches the full root, opens the disk with veritysetup using the measured root, and mounts it before the application starts.
  • Attestation binds verity_root and target through app-compose.json and therefore the measured app_id.

Example:

dstack verity --dir ./models -o models.img
dstack deploy -c docker-compose.yaml \
  --volume models.img:<verity-root>:/run/models

See docs/verity-volumes.md.

Why Docker image seeding is not included

An earlier version injected pre-extracted layers directly into Docker's private overlay2 state. That couples the feature to Docker internals (imagedb, layerdb, overlay2, and repository metadata) and creates unsafe lifecycle edge cases: bind mounts disappear on reboot while Docker metadata persists, pulled images may share layers with verity-seeded images, and removing or changing a volume can leave existing images or containers with dangling layer references.

Safely reconciling that state would require ownership tracking and Docker-specific graph cleanup, while a custom containerd snapshotter would be a substantially larger and less mature integration. This PR therefore keeps the trust and lifecycle boundary simple: it only exposes verified, read-only data filesystems and does not modify Docker image state.

Validation

  • cargo clippy -p dstack-volume --all-targets -- -D warnings
  • cargo clippy -p dstack-cli --all-targets -- -D warnings
  • cargo test -p dstack-volume -p dstack-cli -p dstack-types
  • cargo test -p dstack-vmm --no-fail-fast
  • End-to-end local volume build with dstack verity --dir

@h4x3rotab h4x3rotab changed the title verity volumes: reproducible dm-verity image/data pre-seeding for CVMs verity volumes: pre-load docker images and data into CVMs Jul 4, 2026
@h4x3rotab
h4x3rotab force-pushed the verity-volumes branch 12 times, most recently from b0a463a to 109c584 Compare July 4, 2026 23:16
Comment thread dstack/vmm/src/app/qemu.rs Fixed
Comment thread dstack/vmm/src/app/qemu.rs Fixed
Comment thread dstack/vmm/src/app/qemu.rs Fixed
Comment thread dstack/vmm/src/app/qemu.rs Fixed
Comment thread dstack/vmm/src/app/qemu.rs Fixed
Comment thread dstack/vmm/src/app/qemu.rs Fixed
@kvinwang kvinwang changed the title verity volumes: pre-load docker images and data into CVMs verity volumes: attach verified read-only data disks to CVMs Jul 21, 2026
h4x3rotab and others added 12 commits July 21, 2026 02:19
Add read-only verity volumes -- extra virtio-blk disks a CVM can mount
instead of pulling and unpacking their contents. A volume is declared in
app-compose.json as `{ verity_root, target }`, and attached at deploy time
with `--volume <name>`: the vmm looks the name up under cvm.volumes_dir and
attaches it read-only. Because verity_root is part of the measured compose,
the guest can check the bytes it's handed against it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Just before dockerd starts, dstack-prepare.sh runs the seeding helper. For
each volume declared in the compose it finds the matching disk by opening it
with veritysetup against the measured verity_root, then either seeds docker's
overlay2 store (target "docker") so the images are already present, or mounts
the volume at a path (a data volume). It's fail-safe throughout: a volume
that's missing or doesn't verify is skipped, and its images just pull.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`dstack verity <image>...` builds a squashfs + dm-verity volume that
pre-extracts docker images (or, with `--dir`, a plain directory) so a CVM can
start without pulling or unpacking them. It fetches images itself through
oci-client -- no docker daemon -- and lays out the overlay2 store
deterministically (each layer's directory id is its chain-id, with a fixed
timestamp and salt). The same inputs always produce the same verity_root, so
anyone can recompute it from the pinned image digests and confirm what's in
the volume without trusting the builder. `dstack deploy --volume` attaches
the result.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants