@@ -108,38 +108,24 @@ enum Command {
108108 } ,
109109 /// Scaffold a new app project in the current directory.
110110 Init ,
111- /// Build a verity volume that pre-loads docker images (or a directory) into
112- /// a CVM.
111+ /// Build a read-only verity data volume from a directory or filesystem image.
113112 ///
114- /// The CVM mounts the volume instead of pulling and unpacking the images, so
115- /// it starts in seconds. The build runs anywhere — no docker daemon, no TEE —
116- /// but needs root, `mksquashfs`, and `veritysetup`. It prints a verity_root
117- /// to paste into your compose. See docs/verity-volumes.md.
113+ /// The build needs no daemon or TEE. It prints a verity_root to paste into
114+ /// the deploy command. See docs/verity-volumes.md.
118115 Verity {
119- /// images to bake in, ideally pinned by digest (e.g. `repo@sha256:...`).
120- #[ arg( value_name = "IMAGE" ) ]
121- images : Vec < String > ,
122- /// pack this directory into a data volume instead of images (mounted at a
123- /// path you choose in the compose).
124- #[ arg( long, value_name = "PATH" , conflicts_with = "images" ) ]
116+ /// Pack this directory into a read-only data volume.
117+ #[ arg( long, value_name = "PATH" ) ]
125118 dir : Option < String > ,
126119 /// wrap an existing filesystem image instead of building squashfs. The
127120 /// guest mounts it read-only after dm-verity verification.
128- #[ arg( long = "fs-image" , value_name = "PATH" , conflicts_with_all = [ "images" , " dir"] ) ]
121+ #[ arg( long = "fs-image" , value_name = "PATH" , conflicts_with = " dir") ]
129122 fs_image : Option < String > ,
130123 /// where to write the volume.
131124 #[ arg( long, short = 'o' , default_value = "verity.img" ) ]
132125 output : String ,
133126 /// squashfs compression: `none` (the default), `zstd`, or `gzip`.
134127 #[ arg( long, default_value = "none" ) ]
135128 compress : String ,
136- /// image platform to fetch; must match the guest. `linux/amd64` today,
137- /// `linux/arm64` for arm64 hosts.
138- #[ arg( long, default_value = "linux/amd64" ) ]
139- platform : String ,
140- /// allow plain-HTTP registries (loopback registries already use HTTP).
141- #[ arg( long) ]
142- plain_http : bool ,
143129 } ,
144130}
145131
@@ -233,38 +219,28 @@ async fn main() -> Result<()> {
233219 Command :: Info { .. } => stub ( "info" ) ,
234220 Command :: Init => stub ( "init" ) ,
235221 Command :: Verity {
236- images,
237222 dir,
238223 fs_image,
239224 output,
240225 compress,
241- platform,
242- plain_http,
243226 } => {
244227 cmd_verity (
245- & images,
246228 dir. as_deref ( ) ,
247229 fs_image. as_deref ( ) ,
248230 & output,
249231 & compress,
250- & platform,
251- plain_http,
252232 json,
253233 )
254234 . await
255235 }
256236 }
257237}
258238
259- #[ allow( clippy:: too_many_arguments) ]
260239async fn cmd_verity (
261- images : & [ String ] ,
262240 dir : Option < & str > ,
263241 fs_image : Option < & str > ,
264242 output : & str ,
265243 compress : & str ,
266- platform : & str ,
267- plain_http : bool ,
268244 json : bool ,
269245) -> Result < ( ) > {
270246 let compress = match compress {
@@ -274,13 +250,10 @@ async fn cmd_verity(
274250 other => bail ! ( "unknown --compress '{other}' (use none|zstd|gzip)" ) ,
275251 } ;
276252 let result = dstack_volume:: verity ( dstack_volume:: VerityOptions {
277- images : images. to_vec ( ) ,
278253 dir : dir. map ( std:: path:: PathBuf :: from) ,
279254 fs_image : fs_image. map ( std:: path:: PathBuf :: from) ,
280255 output : output. into ( ) ,
281256 compress,
282- platform : platform. to_string ( ) ,
283- plain_http,
284257 } )
285258 . await ?;
286259
@@ -289,58 +262,31 @@ async fn cmd_verity(
289262 . len ( ) ;
290263
291264 if json {
292- let imgs: Vec < _ > = result
293- . images
294- . iter ( )
295- . map ( |i| {
296- serde_json:: json!( {
297- "reference" : i. reference,
298- "manifestDigest" : i. manifest_digest,
299- "configDigest" : i. config_digest,
300- "topChainId" : i. top_chain_id,
301- } )
302- } )
303- . collect ( ) ;
304265 print_json ( & serde_json:: json!( {
305266 "verityRoot" : result. verity_root,
306267 "output" : result. output. display( ) . to_string( ) ,
307268 "dataSize" : result. data_size,
308269 "volumeSize" : volume_size,
309- "images" : imgs,
310270 } ) ) ;
311271 return Ok ( ( ) ) ;
312272 }
313273
314274 let mib = volume_size as f64 / 1_048_576.0 ;
315275 println ! ( "wrote {} ({mib:.1} MiB)" , result. output. display( ) ) ;
316- if !result. images . is_empty ( ) {
317- // the manifest digest is what `image: repo@sha256:...` pins — not the
318- // config digest (the image id), which can't be pulled by digest.
319- println ! ( "\n baked images — pin each by digest in your compose:" ) ;
320- for i in & result. images {
321- println ! ( " {} @ {}" , i. reference, i. manifest_digest) ;
322- }
323- }
324276 let file = result
325277 . output
326278 . file_name ( )
327279 . map ( |s| s. to_string_lossy ( ) . into_owned ( ) )
328280 . unwrap_or_else ( || result. output . display ( ) . to_string ( ) ) ;
329281 // a data volume mounts at a path you choose; it must be writable (the guest
330282 // rootfs is read-only), e.g. under /run.
331- let target = if result. images . is_empty ( ) {
332- "/run/models"
333- } else {
334- "docker"
335- } ;
283+ let target = "/run/models" ;
336284 println ! ( "\n copy {file} into the vmm's volumes_dir, then deploy with:" ) ;
337285 println ! (
338286 " dstack deploy -c docker-compose.yaml --volume {file}:{}:{target}" ,
339287 result. verity_root
340288 ) ;
341- if result. images . is_empty ( ) {
342- println ! ( " (change {target} to your mount path)" ) ;
343- }
289+ println ! ( " (change {target} to your mount path)" ) ;
344290 Ok ( ( ) )
345291}
346292
@@ -358,7 +304,7 @@ struct VolumeSpec {
358304/// seeds content matching the attested root. `dstack verity` prints the exact
359305/// spec to paste.
360306///
361- /// `TARGET` is `docker` (seed the image store) or an absolute mount path.
307+ /// `TARGET` is an absolute read-only mount path in the guest .
362308fn parse_volume ( spec : & str ) -> Result < VolumeSpec > {
363309 let mut parts = spec. splitn ( 3 , ':' ) ;
364310 let name = parts. next ( ) . unwrap_or_default ( ) ;
@@ -377,8 +323,8 @@ fn parse_volume(spec: &str) -> Result<VolumeSpec> {
377323 if root. len ( ) != 64 || !root. bytes ( ) . all ( |b| b. is_ascii_hexdigit ( ) ) {
378324 bail ! ( "verity_root '{root}' must be 64 hex chars (copy it from `dstack verity`)" ) ;
379325 }
380- if target != "docker" && !target. starts_with ( '/' ) {
381- bail ! ( "target '{target}' must be \" docker \" or an absolute path" ) ;
326+ if !target. starts_with ( '/' ) {
327+ bail ! ( "target '{target}' must be an absolute path" ) ;
382328 }
383329 Ok ( VolumeSpec {
384330 // verity volumes are read-only by construction; a writable one would let a
@@ -728,19 +674,17 @@ mod tests {
728674 #[ test]
729675 fn parses_volume_specs ( ) {
730676 let root = "a" . repeat ( 64 ) ;
731- let docker = parse_volume ( & format ! ( "images.img:{root}:docker" ) ) . unwrap ( ) ;
732- assert_eq ! ( docker. volume. source, "images.img" ) ;
733- assert ! ( docker. volume. read_only) ;
734- assert_eq ! ( docker. verity_root, root) ;
735- assert_eq ! ( docker. target, "docker" ) ;
736-
737677 let data = parse_volume ( & format ! ( "weights.img:{root}:/models/llama" ) ) . unwrap ( ) ;
678+ assert_eq ! ( data. volume. source, "weights.img" ) ;
679+ assert ! ( data. volume. read_only) ;
680+ assert_eq ! ( data. verity_root, root) ;
738681 assert_eq ! ( data. target, "/models/llama" ) ;
739682
740683 assert ! ( parse_volume( "weights.img" ) . is_err( ) ) ; // missing verity_root:target
741684 assert ! ( parse_volume( & format!( "weights.img:{root}" ) ) . is_err( ) ) ; // missing target
742- assert ! ( parse_volume( & format!( "../escape.img:{root}:docker" ) ) . is_err( ) ) ; // path separator
743- assert ! ( parse_volume( "x.img:nothex:docker" ) . is_err( ) ) ; // verity_root not hex
685+ assert ! ( parse_volume( & format!( "../escape.img:{root}:/models" ) ) . is_err( ) ) ; // path separator
686+ assert ! ( parse_volume( "x.img:nothex:/models" ) . is_err( ) ) ; // verity_root not hex
687+ assert ! ( parse_volume( & format!( "x.img:{root}:docker" ) ) . is_err( ) ) ; // docker seed removed
744688 assert ! ( parse_volume( & format!( "x.img:{root}:relative/path" ) ) . is_err( ) ) ; // bad target
745689 }
746690
@@ -782,13 +726,7 @@ mod tests {
782726 fn parses_verity_fs_image_flag ( ) {
783727 let cli = Cli :: parse_from ( [ "dstack" , "verity" , "--fs-image" , "rootfs.ext4" ] ) ;
784728 match cli. command {
785- Command :: Verity {
786- images,
787- dir,
788- fs_image,
789- ..
790- } => {
791- assert ! ( images. is_empty( ) ) ;
729+ Command :: Verity { dir, fs_image, .. } => {
792730 assert_eq ! ( dir, None ) ;
793731 assert_eq ! ( fs_image. as_deref( ) , Some ( "rootfs.ext4" ) ) ;
794732 }
0 commit comments