.. _golden-image: Extracting a "golden" image from the current state of the OS ------------------------------------------------------------------------- In many applications, it's beneficial to prepare the operating system with pre-installed packages and specific configurations. To enable reproducibility, flashing to other devices, and sharing, creating a size-optimized replica is essential. This section explores creating such a "golden" image by extracting the current operating system state. **Considerations** Creating an image with basic tools like ``dd`` can result in a large, inefficient image file. This is because the filesystem is often much larger than necessary. This large size limits installations on devices with smaller storage capacity. This guide aims to create an optimized, minimal copy of the OS state. The generation and validation of the golden image must be performed carefully to avoid issues. **Prerequisites** * A USB flash drive with sufficient storage (8 GB is usually enough; check disk utilization with ``df -h``). * A Linux-based PC or VM (this guide assumes Ubuntu 22.04) with administrative privileges. These operations should be adaptable to other OSs, but this guide won't cover all cases. * A gateway with the desired OS state and console access. * Administrative privileges on the device. * An OS with the ``cl-deploy`` utility installed (check with ``which cl-deploy``). .. admonition:: Known Limitations :class: callout If you have multiple kernels, verify the boot order after the procedure. Disabling unused kernels and checking the GRUB configuration is recommended. .. warning:: * Thoroughly test each image before production use. * Use a reliable USB flash drive. Poor-quality devices can cause data corruption. * The USB flash drive's contents will be erased. Back up any important data. **Steps** 1. Plug a sufficiently large USB flash drive into the device (use the fastest USB interface). Zeroing out the drive's contents is recommended but not mandatory. 2. Log in as root .. code:: console $ sudo su 3. Use ``lsblk`` to identify the USB drive. Typically, ``mmcblk*`` devices are internal eMMC. On Debian-based gateways, the USB drive (if only one is connected) usually appears as ``sda`` .. code:: console $ lsblk ... 4. Run ``cl-deploy`` to copy the filesystem .. code:: console $ cl-deploy 5. Select the destination device using the *Spacebar* and press *Enter* (after highlighting *OK*) .. image:: images/cl-deploy-step1.png :width: 75% :alt: cl-deploy: Destination device selection screen :align: center 6. Confirm data destruction on the destination device by pressing *Enter* (after highlighting *Yes*) .. image:: images/cl-deploy-step2.png :width: 75% :alt: cl-deploy: Destination device data destruction confirmation screen :align: center 7. After copying, ``cl-deploy`` prompts for a reboot. Press *Enter* (after highlighting *No*) .. image:: images/cl-deploy-step3.png :width: 75% :alt: cl-deploy: Reboot prompt :align: center 8. Shut down the system .. code:: console $ shutdown now 9. Unplug the USB flash drive. 10. Proceed to image extraction (unoptimized or optimized). **Extracting an Unoptimized Image** This can also be done on Windows (using Win32DiskImager) or macOS (using ``dd``). 1. Connect the USB flash drive to your Linux PC or VM. If using a VM, pass through the USB drive and enable port forwarding for port 22. 2. Create a working directory .. code:: console $ mkdir image && cd image 3. Use ``lsblk`` to identify the USB drive (e.g., ``/dev/sdb``) .. code:: console $ lsblk ... 4. Use ``dd`` to create an image replica (ensure sufficient disk space) .. code:: console $ sudo dd if=/dev/sdb of=image.img bs=1M status=progress conv=fsync 5. ``image.img`` is the unoptimized image. Note its large size. 6. Safely unmount and eject the USB flash drive. **Extracting an Optimized Image** 1. Connect the USB flash drive (see unoptimized instructions). 2. Create a working directory (see unoptimized instructions). 3. Install ``gparted`` .. code:: console $ sudo apt install -y gparted 4. Identify the USB drive with ``lsblk`` (see unoptimized instructions). 5. Start ``gparted`` .. code:: console $ sudo gparted /dev/sdb 6. Unmount all partitions in ``gparted``. 7. Resize the ``rootfs`` partition, minimizing used space .. image:: images/gparted-step1.png :width: 75% :alt: GParted: Partition layout before resize :align: center .. image:: images/gparted-step2.png :width: 50% :alt: GParted: Partition resize dialog :align: center .. image:: images/gparted-step3.png :width: 75% :alt: GParted: Partition layout after resize :align: center 8. Close ``gparted``. 9. Determine the last block and block size using ``fdisk`` .. code:: console $ sudo fdisk -l /dev/sdb ... 10. Calculate the total block count (including GPT sectors). 11. Use ``dd`` with the correct block size and count:: $ sudo dd if=/dev/sdb of=image.img bs=512 count=6645793 status=progress conv=fsync 12. Restore the GPT table using ``gdisk`` .. code:: console $ sudo gdisk image.img ... (gdisk commands) 13. ``image.img`` is now the optimized image. **Preparing the Image for Sharing** 1. Rename the image using a standard convention .. code:: console $ mv image.img cthingsco-gwlight-debian-bullseye-base-20221226.img 2. Calculate and store the SHA-256 checksum .. code:: console $ sha256sum cthingsco-gwlight-debian-bullseye-base-20221226.img ... 3. Install ``zip`` .. code:: console $ sudo apt install -y zip 4. Compress the image .. code:: console $ zip -9 cthingsco-gwlight-debian-bullseye-base-20221226.zip cthingsco-gwlight-debian-bullseye-base-20221226.img 5. The ``zip`` file is ready. Validate the image thoroughly before production use.