# This module creates a bootable SD card image containing the given NixOS # configuration. The generated image is MBR partitioned, with a FAT /boot # partition, and ext4 root partition. The generated image is sized to fit # its contents, and a boot script automatically resizes the root partition # to fit the device on the first boot. # # The derivation for the SD image will be placed in # config.system.build.sdImage { config, lib, pkgs, ... }: with lib; let rootfsImage = import ../../../lib/make-ext4-fs.nix { inherit pkgs; inherit (config.sdImage) storePaths; volumeLabel = "NIXOS_SD"; }; in { options.sdImage = { storePaths = mkOption { type = with types; listOf package; example = literalExample "[ pkgs.stdenv ]"; description = '' Derivations to be included in the Nix store in the generated SD image. ''; }; bootSize = mkOption { type = types.int; default = 120; description = '' Size of the /boot partition, in megabytes. ''; }; populateBootCommands = mkOption { example = literalExample "'' cp \${pkgs.myBootLoader}/u-boot.bin boot/ ''"; description = '' Shell commands to populate the ./boot directory. All files in that directory are copied to the /boot partition on the SD image. ''; }; }; config = { fileSystems = { "/boot" = { device = "/dev/disk/by-label/NIXOS_BOOT"; fsType = "vfat"; }; "/" = { device = "/dev/disk/by-label/NIXOS_SD"; fsType = "ext4"; }; }; sdImage.storePaths = [ config.system.build.toplevel ]; system.build.sdImage = pkgs.stdenv.mkDerivation { name = "sd-image-${pkgs.stdenv.system}.img"; buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ]; buildCommand = '' # Create the image file sized to fit /boot and /, plus 20M of slack rootSizeBlocks=$(du -B 512 --apparent-size ${rootfsImage} | awk '{ print $1 }') bootSizeBlocks=$((${toString config.sdImage.bootSize} * 1024 * 1024 / 512)) imageSize=$((rootSizeBlocks * 512 + bootSizeBlocks * 512 + 20 * 1024 * 1024)) truncate -s $imageSize $out # type=b is 'W95 FAT32', type=83 is 'Linux'. sfdisk $out <