Build a basic image¶
These instructions describe how to build a minimal classic
Ubuntu 24.04 AMD64
server image with Imagecraft.
Prerequisites¶
AMD64 machine with Ubuntu 24.04
snapd
installed (see Install snap on Ubuntu)15GiB or more disk space to process the build and hold the resulting image
Note
Following these instructions will build an AMD64 image on an AMD64 machine. Building on another architecture would need several modifications not described on this page.
Install Imagecraft¶
Imagecraft is available as a snap on the latest/beta
channel in the
Snap Store. Install it with:
sudo snap install imagecraft --channel=beta --classic
Verify that Imagecraft is properly installed:
imagecraft
Caution
Imagecraft mounts important (/dev
, /sys
, etc.) system directories
from the building environment. When running in destructive mode, a
invalid project file leading to a failure of Imagecraft could damage the
system.
Prepare the configuration¶
Project file¶
The name of the project file, imagecraft.yaml
, is important because Imagecraft
uses it automatically. Save the following content as imagecraft.yaml
:
imagecraft.yaml
name: ubuntu-minimal
version: "0.1"
base: bare
build-base: [email protected]
platforms:
amd64:
volumes:
pc:
schema: gpt
structure:
- name: efi
type: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
filesystem: vfat
role: system-boot
filesystem-label: UEFI
size: 256M
- name: rootfs
type: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
filesystem: ext4
filesystem-label: writable
role: system-data
size: 5G
filesystems:
default:
- mount: "/"
device: "(volume/pc/rootfs)"
- mount: "/boot/efi"
device: "(volume/pc/efi)"
parts:
# build a simple rootfs
rootfs:
plugin: nil
build-packages: ["mmdebstrap"]
overlay-script: |
mmdebstrap --arch $CRAFT_ARCH_BUILD_FOR \
--mode=sudo \
--format=dir \
--variant=minbase \
--include=apt \
noble \
$CRAFT_OVERLAY/ \
http://archive.ubuntu.com/ubuntu/
mkdir $CRAFT_OVERLAY/boot/efi
# add packages using chroot and apt to have maintainer scripts properly run
packages:
plugin: nil
after: [rootfs]
overlay-script: |
mkdir -p $CRAFT_OVERLAY/dev $CRAFT_OVERLAY/sys $CRAFT_OVERLAY/proc
mount -t devtmpfs devtmpfs-build $CRAFT_OVERLAY/dev
mount -t devpts devpts-build -o nodev,nosuid $CRAFT_OVERLAY/dev/pts
mount -t sysfs sysfs-build $CRAFT_OVERLAY/sys
mount -t proc proc-build $CRAFT_OVERLAY/proc
mount --bind /run $CRAFT_OVERLAY/run
DEBIAN_FRONTEND=noninteractive chroot $CRAFT_OVERLAY apt update
DEBIAN_FRONTEND=noninteractive chroot $CRAFT_OVERLAY apt install --assume-yes --quiet \
--option=Dpkg::options::=--force-unsafe-io --option=Dpkg::Options::=--force-confold \
ubuntu-server-minimal grub2-common grub-pc shim-signed linux-image-generic
mount --make-rprivate $CRAFT_OVERLAY/run
umount --recursive $CRAFT_OVERLAY/run
mount --make-rprivate $CRAFT_OVERLAY/sys
umount --recursive $CRAFT_OVERLAY/sys
mount --make-rprivate $CRAFT_OVERLAY/proc
umount --recursive $CRAFT_OVERLAY/proc
mount --make-rprivate $CRAFT_OVERLAY/dev/pts
umount --recursive $CRAFT_OVERLAY/dev/pts
mount --make-rprivate $CRAFT_OVERLAY/dev
umount --recursive $CRAFT_OVERLAY/dev
rm $CRAFT_OVERLAY/etc/cloud/cloud.cfg.d/90_dpkg.cfg
# prepare snaps
snaps:
plugin: nil
after: [packages]
overlay-script: |
snap prepare-image --classic --arch=amd64 \
--snap snapd --snap core24 "" $CRAFT_OVERLAY
# fix fstab and organize content to the partition
fstab:
plugin: nil
after: [snaps]
overlay-script: |
cat << EOF > $CRAFT_OVERLAY/etc/fstab
LABEL=writable / ext4 discard,errors=remount-ro 0 1
LABEL=UEFI /boot/efi vfat umask=0077 0 1
EOF
cloud-init:
plugin: dump
source: cloud-init/
Cloud-init configuration¶
Prepare needed directories:
mkdir -p cloud-init/var/lib/cloud/seed/nocloud
mkdir -p cloud-init/etc/cloud/cloud.cfg.d/
Write the following files in the cloud-init
directory:
cloud-init/var/lib/cloud/seed/nocloud/meta-data
dsmode: local instance_id: ubuntu-server
cloud-init/var/lib/cloud/seed/nocloud/user-data
#cloud-config chpasswd: expire: true users: - name: ubuntu password: ubuntu type: text
cloud-init/etc/cloud/cloud.cfg.d/90_dpkg.cfg
# to update this file, run dpkg-reconfigure cloud-init datasource_list: [ NoCloud ]
Pack the image¶
The packing can be run in two different environments:
In a
multipass
VM:sudo snap set imagecraft provider=multipass imagecraft --verbosity debug pack
On the local machine, with destructive mode. In this case the machine must be of the series of the
build-base
declared in theimagecraft.yaml
file.sudo imagecraft --verbosity debug pack --destructive-mode
The resulting image file, pc.img
, will be deposited in the current directory.
Note
Without any specific option imagecraft will rely by default on LXD
to build the image. However this mode of operation is not working yet.
Run the image¶
Finally, test your new image with QEMU.
First, install QEMU and the Open Virtual Machine Firmware UEFI firmware for 64-bit x86 virtual machines:
sudo apt install ovmf qemu-system-x86
Then, copy the UEFI variables to a temporary directory:
cp /usr/share/OVMF/OVMF_VARS_4M.fd /tmp/OVMF_VARS_4M.fd
Boot the resulting image with QEMU:
qemu-system-x86_64 \
-accel kvm \
-m 4G \
-cpu host \
-smp 8 \
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
-drive if=pflash,format=raw,file=/tmp/OVMF_VARS_4M.fd \
-drive file=pc.img,format=raw,index=0,media=disk
The image should boot and give access to a shell.