Version scope: the examples below retain the tutorial's NixOS 24.05 context; that release is no longer maintained. For a real project, choose a supported release, pin the nixpkgs revision, and check the corresponding options.
system.stateVersiondefines a compatibility baseline and should not be changed mechanically on every upgrade. The commands in this article are teaching examples and have not been run or verified on the target system.
Overview#
NixOS can build custom bootable ISO images for:
- Creating custom installation media
- Making system maintenance media
- Deploying preconfigured systems
Basic configuration#
Create an iso.nix file:
{ pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix")
];
# ISO 标识
isoImage.makeEfiBootable = true;
isoImage.makeUsbBootable = true;
# 主机名
networking.hostName = "nixos-custom";
# 预装软件
environment.systemPackages = with pkgs; [
vim
git
htop
parted
gparted
];
# 系统版本
system.stateVersion = "24.05";
}Building the ISO#
# 构建 ISO
nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage \
-I nixos-config=./iso.nix \
-I nixpkgs=channel:nixos-24.05The generated ISO is in ./result/iso/. Its filename depends on the build configuration; confirm it with ls ./result/iso/ rather than assuming a fixed name.
A graphical ISO#
An ISO with the GNOME desktop environment:
{ pkgs, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/cd-dvd/installation-cd-graphical-gnome.nix")
];
# 添加额外的软件
environment.systemPackages = with pkgs; [
firefox
libreoffice
];
}Building with Flakes#
# flake.nix
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
outputs = { self, nixpkgs }: {
nixosConfigurations.iso = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
(nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix")
({ pkgs, ... }: {
isoImage.makeEfiBootable = true;
networking.hostName = "nixos-live";
environment.systemPackages = [ pkgs.vim ];
})
];
};
};
}Build:
nix build .#nixosConfigurations.iso.config.system.build.isoImageWriting the ISO to a USB drive#
Writing the image overwrites the entire target drive. Back up the target USB drive first, confirm its model, capacity, and device path, and unmount its mounted partitions. The target must be the whole drive, not an individual partition. Replace the placeholder below; do not run the command as written.
# 查看设备身份与挂载状态
lsblk -o NAME,SIZE,MODEL,TYPE,MOUNTPOINTS
ls ./result/iso/
# 确认目标后,逐个卸载其已挂载的分区
sudo umount /dev/<USB_PARTITION>
# 写入已经核对过的 ISO 和整盘设备
sudo dd if=./result/iso/<BUILT_IMAGE>.iso of=/dev/<USB_DISK> bs=4M status=progress conv=fsync
syncA successful ISO build does not guarantee a successful boot on physical hardware. You can first test the boot menu and required software in QEMU, then check UEFI/BIOS support, drivers, and networking on the target hardware.
References & further reading
Adapted from technical notes. Examples use generic names.