paranix-configs/images/make-image.nix

181 lines
4.8 KiB
Nix
Raw Permalink Normal View History

{ pkgs
, lib
, # The NixOS configuration to be installed onto the disk image.
config
, # The size of the disk, in megabytes.
diskSize ? 8192
, # size of the boot partition, is only used if partitionTableType is
# either "efi" or "hybrid"
bootSize ? 512
, # The files and directories to be placed in the target file system.
# This is a list of attribute sets {source, target} where `source'
# is the file system object (regular file or directory) to be
# grafted in the file system at path `target'.
contents ? []
, # The initial NixOS configuration file to be copied to
# /etc/nixos/configuration.nix.
configFile
, # Shell code executed after the VM has finished.
postVM ? ""
, name ? "nixos-disk-image"
, # Disk image format, one of qcow2, qcow2-compressed, vdi, vpc, raw.
format ? "raw"
, # Include a copy of Nixpkgs in the disk image
includeChannel ? true
, ...
}:
let
formatOpt = if format == "qcow2-compressed" then "qcow2" else format;
compress = lib.optionalString (format == "qcow2-compressed") "-c";
filename = "nixos." + {
qcow2 = "qcow2";
vdi = "vdi";
vpc = "vhd";
raw = "img";
}.${formatOpt} or formatOpt;
channelSources =
let
nixpkgs = lib.cleanSource pkgs.path;
in
pkgs.runCommand "nixos-${config.system.nixos.version}" {} ''
mkdir -p $out
cp -prd ${nixpkgs.outPath} $out/nixos
chmod -R u+w $out/nixos
if [ ! -e $out/nixos/nixpkgs ]; then
ln -s . $out/nixos/nixpkgs
fi
rm -rf $out/nixos/.git
echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
'';
closureInfo = pkgs.closureInfo {
rootPaths = [ config.system.build.toplevel ]
++ (lib.optional includeChannel channelSources);
};
modulesTree = pkgs.aggregateModules
(with config.boot.kernelPackages; [ kernel ]);
tools = lib.makeBinPath (
with pkgs; [
config.system.build.nixos-enter
config.system.build.nixos-install
dosfstools
e2fsprogs
nix
parted
utillinux
]
);
stringifyProperties = prefix: properties: lib.concatStringsSep " \\\n" (
lib.mapAttrsToList
(
property: value: "${prefix} ${lib.escapeShellArg property}=${lib.escapeShellArg value}"
)
properties
);
image = (
pkgs.vmTools.override {
rootModules =
[ "9p" "9pnet_virtio" "virtio_pci" "virtio_blk" "rtc_cmos" ];
kernel = modulesTree;
}
).runInLinuxVM (
pkgs.runCommand name
{
preVM = ''
PATH=$PATH:${pkgs.qemu_kvm}/bin
mkdir $out
diskImage=nixos.raw
qemu-img create -f raw $diskImage ${toString diskSize}M
'';
postVM = ''
${if formatOpt == "raw" then ''
mv $diskImage $out/${filename}
'' else ''
${pkgs.qemu}/bin/qemu-img convert -f raw -O ${formatOpt} ${compress} $diskImage $out/${filename}
''}
diskImage=$out/${filename}
${postVM}
'';
} ''
export PATH=${tools}:$PATH
set -x
cp -sv /dev/vda /dev/sda
cp -sv /dev/vda /dev/xvda
parted --script /dev/vda -- \
mklabel gpt \
mkpart no-fs 1MB 2MB \
align-check optimal 1 \
set 1 bios_grub on \
mkpart ESP fat32 8MB ${toString bootSize}MB \
align-check optimal 2 \
set 2 boot on \
mkpart primary ${toString bootSize}MB -1 \
align-check optimal 3 \
print
mkdir /mnt
mount -t tmpfs none /mnt
mkdir -p /mnt/{boot,nix,etc/{nixos,ssh},var/{lib,log},srv}
mkdir -p /mnt/boot
mkfs.vfat /dev/vda2 -n ESP
mount -t vfat /dev/vda2 /mnt/boot
mkfs.ext4 -L nix /dev/vda3
mount /dev/vda3 /mnt/nix
mkdir -p /mnt/nix/persist/{etc/{nixos,ssh},var/{lib,log},srv}
mount -o bind /mnt/nix/persist/etc/nixos /mnt/etc/nixos
mount -o bind /mnt/nix/persist/var/lib /mnt/var/lib
mount -o bind /mnt/nix/persist/var/log /mnt/var/log
mount
# Install a configuration.nix
mkdir -p /mnt/etc/nixos
# `cat` so it is mutable on the fs
cat ${configFile} > /mnt/etc/nixos/configuration.nix
export NIX_STATE_DIR=$TMPDIR/state
nix-store --load-db < ${closureInfo}/registration
echo copying toplevel
time nix copy --no-check-sigs --to 'local?root=/mnt/' ${config.system.build.toplevel}
${lib.optionalString includeChannel ''
echo copying channels
time nix copy --no-check-sigs --to 'local?root=/mnt/' ${channelSources}
''}
echo installing bootloader
time nixos-install --root /mnt --no-root-passwd \
--system ${config.system.build.toplevel} \
--substituters " " ${lib.optionalString includeChannel "--channel ${channelSources}"}
df -h
umount /mnt/boot
''
);
in
image