UBUNTU-IMAGE(1)
๐ UBUNTU-IMAGE ๐
okay bestie, gather round, because this is the manual page for ubuntu-image (that's the ubuntu-image command, section 1 of the manual, if you're keeping track) and she is busy in the best way. she makes bootable disk images. plural. a whole variety. let's get into it ๐ซถ
โจ NAME โจ
ubuntu-image โ generate a bootable disk image. that's the whole job. that's her whole thing. and she eats every time ๐
๐ธ SYNOPSIS ๐ธ
ubuntu-image snap [options] model.assertion
ubuntu-image classic [options] GADGET_TREE_URI
two modes, two vibes. pick your fighter โจ
๐ฆ DESCRIPTION ๐ฆ
so ubuntu-image is a program for generating a variety of bootable disk images. currently she supports building snap based and classic preinstalled Ubuntu images. two flavors, both iconic ๐
Snap-based images are built from a model assertion, which is a YAML file describing a particular combination of core, kernel, and gadget snaps, along with other declarations, signed with a digital signature asserting its authenticity. like, the signature is the whole point โ it's the vibe check that proves this file is legit. the assets defined in the model assertion uniquely describe the device for which the image is built. no cap.
as part of the model assertion, a gadget snap is specified. the gadget contains a gadget.yaml file which contains the exact description of the disk image's contents, in YAML format. the gadget.yaml file describes such things as the names of all the volumes to be produced [1], the structures [2] within the volume, whether the volume contains a bootloader and if so what kind of bootloader, etc. it's giving blueprint energy ๐
heads up bestie:ubuntu-imagecommunicates with the snap store using thesnap prepare-imagesubcommand. the model assertion file is passed tosnap prepare-imagewhich handles downloading the appropriate gadget and any extra snaps. so if you're confused about the download part, that's not her, that's snapd. see that command's documentation for additional details ๐
Classic images are built from a local gadget tree path. the gadget tree is nothing more than a primed gadget snap, containing a gadget.yaml file in the meta directory and all the necessary bootloader gadget bits built. for instance a gadget tree can be easily prepared by fetching a specially tailored gadget snap source and running snapcraft prime on it, with the resulting tree ending up in the prime/ directory. lowkey elegant.
the actual rootfs for a classic image is created by live-build with arguments passed as per the optional arguments to ubuntu-image. the livecd-rootfs configuration from the host system is used.
๐ OPTIONS ๐
๐ general ones ๐
-h,--helpโ show the program's message and exit. the "help me bestie" button, always there for you ๐ซถ--versionโ show the program's version number and exit. for when you need to know which ubuntu-image you're talking to.
๐ Snap command options ๐
these are the options for defining the contents of snap-based images. can only be used when the ubuntu-image snap command is used. like, they will not work in classic mode, she's not flexible about that.
model_assertionโ path to the model assertion file. this positional argument must be given for this mode of operation. no assertion, no image, periodt.--cloud-init USER-DATA-FILEโ cloud-config data to be copied to the image. yes, it gets copied straight in, so make it good โ๏ธ--disable-console-confโ disableconsole-confon the resulting image. bye bye console-conf, we hardly knew ye ๐--factory-imageโ hint that the image is meant to boot in a device factory. it's just a hint, not a command, she's not bossy like that.--validation=<ignore|enforce>โ control whether validations should be ignored or enforced. two choices, no in-between, choose wisely.
๐ Classic command options ๐
these are the options for defining the contents of classic preinstalled Ubuntu images. can only be used when the ubuntu-image classic command is used. again: mode-specific, she does not mix.
GADGET_TREE_URIโ an URI to the gadget tree to be used to build the image. this positional argument must be given for this mode of operation. must be a local path. like, don't go putting anhttps://in there, bestie, she will not know what to do with it ๐ญ-p PROJECT,--project PROJECTโ project name to be passed on to livecd-rootfs. mutually exclusive with--filesystem. pick one, you can't have both, that's the rule ๐-f FILESYSTEM,--filesystem FILESYSTEMโ unpacked Ubuntu filesystem to be copied to the system partition. mutually exclusive with--project. again: one or the other, not both.-s SUITE,--suite SUITEโ distribution name to be passed on to livecd-rootfs.-a CPU-ARCHITECTURE,--arch CPU-ARCHITECTUREโ CPU architecture to be passed on to livecd-rootfs. default value is the architecture of the host. so if you don't say anything, she just assumes you mean this machine, which is honestly so real of her โจ--subproject SUBPROJECTโ sub-project name to be passed on livecd-rootfs.--subarch SUBARCHโ sub-architecture to be passed on to livecd-rootfs.--with-proposedโ defines if the image should be built with-proposedenabled. this is passed through to livecd-rootfs. careful with this one,-proposedis exactly what it sounds like ๐--extra-ppas EXTRA_PPASโ extra ppas to install. this is passed through to livecd-rootfs.
๐ Common options ๐
there are two general operational modes to ubuntu-image. the usual mode is to run the script giving the required model assertion file as a required positional argument, generating a disk image file. these options are useful in this mode of operation. this is the everyday, main-character mode ๐
the second mode of operation is provided for debugging and testing purposes. it allows you to run the internal state machine step by step, and is described in more detail below. this is the "peek behind the curtain" mode, and honestly? kind of fascinating.
-d,--debugโ enable debugging output. turn it on when you want to see everything, bestie. she will tell you all her business ๐ฃ๏ธ-O DIRECTORY,--output-dir DIRECTORYโ write generated disk image files to this directory. the files will be named after thegadget.yamlvolume names, with.imgsuffix appended. if not given, the current working directory is used. this option replaces, and cannot be used with, the deprecated--outputoption. so if you were still using--output... ma'am. it's deprecated. move on ๐-i SIZE,--image-size SIZEโ the size of the generated disk image files. if this size is smaller than the minimum calculated size of the volume, a warning will be issued and--image-sizewill be ignored. the value is the size in bytes, with allowable suffixes'M'for MiB and'G'for GiB.
an extended syntax is supported for gadget.yaml files which specify multiple volumes (i.e. disk images). in that case, a single SIZE argument will be used for all the defined volumes, with the same rules for ignoring values which are too small. you can specify the image size for a single volume using an indexing prefix on the SIZE parameter, where the index is either a volume name or an integer index starting at zero. for example, to set the image size only on the second volume, which might be called sdcard in the gadget.yaml, you could use: --image-size 1:8G since the 1-th index names the second volume (volumes are 0-indexed). or you could use --image-size sdcard:8G.
you can also specify multiple volume sizes by separating them with commas, and you can mix and match integer indexes and volume name indexes. thus, if the gadget.yaml named three volumes, and you wanted to set all three to different sizes, you could use --image-size 0:2G,sdcard:8G,eMMC:4G. comma-separated chaos, but make it organized ๐
in the case of ambiguities, the size hint is ignored and the calculated size for the volume will be used instead. she's not gonna guess. she's gonna do the math herself.
--image-file-list FILENAMEโ print toFILENAME, a list of the file system paths to all the disk images created by the command, if any. great for scripts. great for "where did my images go" moments.--hooks-directory DIRECTORYโ directories in which scripts for build-time hooks will be located. this flag must be specified once for each hook directory.ubuntu-imagewill look for hooks inhooks_directory/name_of_hooks_step.dand a script with the namehooks_directory/name_of_hooks_step. currently the only supported hooks step ispopulate_rootfs_contents. note that: the ONLY supported hooks step. don't go inventing new ones, she won't call them ๐ช--disk-info DISK-INFO-CONTENTSโ file to be used as.disk/infoon the image's rootfs. this file can contain useful information about the target image, like image identification data, system name, build timestamp etc. basically her little name tag for the image ๐ท๏ธ--snap SNAPโ install an extra snap. this is passed through tosnap prepare-image. the snap argument can include additional information about the channel and/or risk with the following syntax:<snap>=<channel|risk>. so like, specify the snap and where to get it, in one little bundle.-c CHANNEL,--channel CHANNELโ the snap channel to use.--sector-size SIZEโ when creating the disk image file, use the given sector size. this can be either512or4096(4k sector size), defaulting to512. two options. just two. that's it. don't get creative.
๐ฎ State machine options ๐ฎ
CAUTION! the options described here are primarily for debugging and testing purposes and should not be considered part of the stable, public API. state machine step numbers and names can change between releases. so like, if you build your whole workflow on these, that's on you bestie ๐
ubuntu-image internally runs a state machine to create the disk image. these are some options for controlling this state machine. other than --workdir, these options are mutually exclusive. when --until or --thru is given, the state machine can be resumed later with --resume, but --workdir must be given in that case since the state is saved in a .ubuntu-image.pck file in the working directory.
-w DIRECTORY,--workdir DIRECTORYโ the working directory in which to download and unpack all the source files for the image. this directory can exist or not, and it is not removed after this program exits. if not given, a temporary working directory is used instead, which is deleted after this program exits. use--workdirif you want to be able to resume a partial state machine run. as an added bonus, thegadget.yamlfile is copied to the working directory after it's downloaded ๐-u STEP,--until STEPโ run the state machine until the givenSTEP, non-inclusively.STEPis the name of a state machine method. the list of all steps can be found in theSTEPSsection of this document. note: until = stop before it. non-inclusive. she stops just shy of the finish line ๐โโ๏ธ-t STEP,--thru STEPโ run the state machine through the givenSTEP, inclusively.STEPis the name of a state machine method. the list of all steps can be found in theSTEPSsection of this document. note: thru = go through it, inclusive, all the way in ๐-r,--resumeโ continue the state machine from the previously saved state. it is an error if there is no previous state. like, you can't resume what was never started, bestie ๐ญ
๐ FILES ๐
gadget.yamlโ https://github.com/snapcore/snapd/wiki/Gadget-snap#gadget.yaml- model assertion โ https://developer.ubuntu.com/en/snappy/guides/prepare-image/
- gadget tree (example) โ https://github.com/snapcore/pc-amd64-gadget
- cloud-config โ https://help.ubuntu.com/community/CloudInit
โจ ENVIRONMENT โจ
okay bestie, ubuntu-image is nosey (affectionate) and it reads these environment variables. here's the whole roster:
UBUNTU_IMAGE_PRESERVE_UNPACKโ set this and it names a directory where a pristine copy of the unpacked gadget contents gets stashed. important: the directory must already exist, and an unpack directory gets created under this directory. basically: the full contents of the<workdir>/unpackdirectory โ as it looks after the snapprepare-imagesubcommand has run โ get copied here. ๐UBUNTU_IMAGE_LIVECD_ROOTFS_AUTO_PATHโubuntu-imageuseslivecd-rootfsconfiguration files for its live-build runs. if this is set, it pulls the config files from the path you picked for its auto configuration. if it's not set, it goes and tries to localizelivecd-rootfsby making a call todpkg. ๐UBUNTU_IMAGE_QEMU_USER_STATIC_PATHโ when you're cross-compiling a classic image for a different architecture,ubuntu-imagetries to use theqemu-user-staticemulator with live-build. set this and it uses the path you chose for the cross-compilation. don't set it and it'll go hunting for a matching emulator binary in your current$PATH. ๐
also there are a few other environment variables floating around, but those are for building and testing only. not your business (respectfully). ๐
๐ช HOOKS ๐ช
so during an image build, at certain stages, you get to run custom scripts that modify the image contents or otherwise mess with the process itself. main character energy, honestly.
whenever a hook fires, the directories listed in the --hooks-directory parameter get scanned for matching scripts. and yes, there can be multiple scripts for a specific hook. here's the order, bestie:
HookManagerfirst looks for executable files in<hookdir>/<name-of-the-hook>.dand runs them in alphanumerical order. ๐- then, finally, the
<hookdir>/<name-of-the-hook>file gets executed โ if it exists.
hook scripts can also get extra data passed to them through environment variables, depending on which hook is firing. cute, right?
here's what's currently supported:
post-populate-rootfs
runs after the rootfs directory has been populated, so you can custom-modify its contents. added in version 1.2. ๐
environment variables present:
UBUNTU_IMAGE_HOOK_ROOTFSโ the absolute path to the rootfs contents. ๐
๐ STEPS ๐
the names of steps you can use with --until and --thru for each image type are listed below. slay.
Classic image steps
make_temporary_directoriesprepare_gadget_treerun_live_buildload_gadget_yamlpopulate_rootfs_contentspopulate_rootfs_contents_hooksgenerate_disk_infocalculate_rootfs_sizepopulate_bootfs_contentspopulate_prepare_partitionsmake_diskgenerate_manifestfinish
Snap image steps
make_temporary_directoriesprepare_imageload_gadget_yamlpopulate_rootfs_contentspopulate_rootfs_contents_hooksgenerate_disk_infocalculate_rootfs_sizepopulate_bootfs_contentspopulate_prepare_partitionsmake_diskgenerate_manifestfinish
๐ NOTES ๐
sometimes, for various reasons, ubuntu-image does specific little workarounds, and you might be sitting there like "whyโฆ". so here's the reasoning, bestie.
Classic swapfile manual unsparsing
when building a classic image, if ubuntu-image notices a /swapfile hanging out on the image's rootfs, it will proactively try to unsparse it.
why tho? because ubuntu-image assumes that /swapfile file is gonna be used as a swapfile on the target system. and due to undocumented behavior of mkfs.ext4 -d, large empty files get automatically converted into sparse files during filesystem population. which, lowkey, makes such files completely unusable as swapfiles. ๐ญ
so just in case, ubuntu-image does an in-place dd call of the hard-coded path swapfile to make sure it's not sparse anymore. problem solved, periodt. ๐
๐ SEE ALSO ๐
๐ฆ FOOTNOTES ๐ฆ
- [1] Volumes are roughly analogous to disk images.
- [2] Structures define the layout of the volume, including partitions, Master Boot Records, or any other relevant content.
๐ AUTHOR ๐
- Barry Warsaw
<barry@ubuntu.com> - ลukasz 'sil2100' Zemczak
<lukasz.zemczak@ubuntu.com> - William 'jawn-smith' Wilson
<william.wilson@canonical.com>
๐ COPYRIGHT ๐
2016-2021 Canonical Ltd.
and that's the whole page, bestie!! this one is version 2.0, dated 2021-10-21, and it lives under UBUNTU-IMAGE(1). go build something iconic with it ๐ซถโจ๐
๐ฆ where this page comes from
- ubuntu jammy: ubuntu-image 2.2+22.04ubuntu2 ยท GPL-3.0-only
- ubuntu jammy: ubuntu-image 2.2+22.04ubuntu3.22.04.2 ยท GPL-3.0-only
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms