├── .gitignore ├── .travis.yml ├── .envrc ├── garnix.yaml ├── formats ├── vm-bootloader.nix ├── kexec-bundle.nix ├── proxmox.nix ├── azure.nix ├── hyperv.nix ├── vagrant-virtualbox.nix ├── vmware.nix ├── kubevirt.nix ├── virtualbox.nix ├── amazon.nix ├── do.nix ├── gce.nix ├── vm.nix ├── install-iso-hyperv.nix ├── openstack.nix ├── sd-aarch64-installer.nix ├── sd-aarch64.nix ├── sd-x86_64.nix ├── proxmox-lxc.nix ├── iso.nix ├── lxc.nix ├── lxc-metadata.nix ├── docker.nix ├── install-iso.nix ├── vm-nogui.nix ├── raw-efi.nix ├── cloudstack.nix ├── raw.nix ├── qcow.nix ├── linode.nix ├── qcow-efi.nix └── kexec.nix ├── shell.nix ├── .github ├── dependabot.yml └── workflows │ └── update-flake-lock.yml ├── default.nix ├── checks ├── is-formatted.nix ├── test-customize-format.nix ├── test-all-formats.nix └── test-all-formats-flake │ └── flake.nix ├── .mergify.yml ├── configuration.nix ├── Makefile ├── package.nix ├── format-module.nix ├── nixos-generate.nix ├── .included.yml ├── LICENSE ├── flake.lock ├── lib.nix ├── all-formats.nix ├── .gitlab-ci.yml ├── nixos-generate ├── flake.nix └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.qcow2 2 | result 3 | result-* 4 | .direnv 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: nix 2 | 3 | sudo: false 4 | 5 | script: 6 | - nix-build 7 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if has lorri; then 2 | eval "$(lorri direnv)" 3 | else 4 | use nix 5 | fi 6 | -------------------------------------------------------------------------------- /garnix.yaml: -------------------------------------------------------------------------------- 1 | builds: 2 | include: 3 | - '*.x86_64-linux.*' 4 | - 'packages.aarch64-darwin.*' 5 | - nixosConfigurations.* 6 | -------------------------------------------------------------------------------- /formats/vm-bootloader.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | ./vm.nix 4 | ]; 5 | 6 | virtualisation.useBootLoader = true; 7 | } 8 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import (builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") { 2 | src = ./.; 3 | }) 4 | .shellNix 5 | .default 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import (builtins.fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") { 2 | src = ./.; 3 | }) 4 | .defaultNix 5 | .default 6 | -------------------------------------------------------------------------------- /checks/is-formatted.nix: -------------------------------------------------------------------------------- 1 | {pkgs ? import {}}: 2 | pkgs.runCommand "check-format" {} '' 3 | ${pkgs.alejandra}/bin/alejandra -c ${./.} 4 | touch $out 5 | '' 6 | -------------------------------------------------------------------------------- /formats/kexec-bundle.nix: -------------------------------------------------------------------------------- 1 | {lib, ...}: { 2 | imports = [./kexec.nix]; 3 | 4 | formatAttr = lib.mkForce "kexec_bundle"; 5 | fileExtension = lib.mkForce "-kexec_bundle"; 6 | } 7 | -------------------------------------------------------------------------------- /formats/proxmox.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/proxmox-image.nix" 4 | ]; 5 | formatAttr = "VMA"; 6 | fileExtension = ".vma.zst"; 7 | } 8 | -------------------------------------------------------------------------------- /formats/azure.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/azure-image.nix" 4 | ]; 5 | 6 | formatAttr = "azureImage"; 7 | fileExtension = ".vhd"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/hyperv.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/hyperv-image.nix" 4 | ]; 5 | 6 | formatAttr = "hypervImage"; 7 | fileExtension = ".vhdx"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/vagrant-virtualbox.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/vagrant-virtualbox-image.nix" 4 | ]; 5 | 6 | formatAttr = "vagrantVirtualbox"; 7 | } 8 | -------------------------------------------------------------------------------- /formats/vmware.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/vmware-image.nix" 4 | ]; 5 | 6 | formatAttr = "vmwareImage"; 7 | fileExtension = ".vmdk"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/kubevirt.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/kubevirt.nix" 4 | ]; 5 | 6 | formatAttr = "kubevirtImage"; 7 | fileExtension = ".qcow2"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/virtualbox.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/virtualbox-image.nix" 4 | ]; 5 | 6 | formatAttr = "virtualBoxOVA"; 7 | fileExtension = ".ova"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/amazon.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/../maintainers/scripts/ec2/amazon-image.nix" 4 | ]; 5 | 6 | formatAttr = "amazonImage"; 7 | fileExtension = ".vhd"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/do.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/digital-ocean-image.nix" 4 | ]; 5 | 6 | formatAttr = "digitalOceanImage"; 7 | fileExtension = ".qcow2.gz"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/gce.nix: -------------------------------------------------------------------------------- 1 | {modulesPath, ...}: { 2 | imports = [ 3 | "${toString modulesPath}/virtualisation/google-compute-image.nix" 4 | ]; 5 | 6 | formatAttr = "googleComputeImage"; 7 | fileExtension = ".raw.tar.gz"; 8 | } 9 | -------------------------------------------------------------------------------- /formats/vm.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | modulesPath, 4 | ... 5 | }: { 6 | imports = [ 7 | "${toString modulesPath}/virtualisation/qemu-vm.nix" 8 | ]; 9 | virtualisation.diskSize = lib.mkDefault (2 * 1024); 10 | formatAttr = "vm"; 11 | } 12 | -------------------------------------------------------------------------------- /formats/install-iso-hyperv.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | ... 4 | }: { 5 | imports = [ 6 | ./install-iso.nix 7 | ]; 8 | 9 | systemd.services.wpa_supplicant.wantedBy = lib.mkOverride 40 []; 10 | virtualisation.hypervGuest.enable = true; 11 | } 12 | -------------------------------------------------------------------------------- /formats/openstack.nix: -------------------------------------------------------------------------------- 1 | { 2 | modulesPath, 3 | ... 4 | }: 5 | { 6 | imports = [ 7 | "${toString modulesPath}/../maintainers/scripts/openstack/openstack-image.nix" 8 | ]; 9 | formatAttr = "openstackImage"; 10 | fileExtension = ".qcow2"; 11 | } 12 | -------------------------------------------------------------------------------- /formats/sd-aarch64-installer.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | modulesPath, 4 | ... 5 | }: { 6 | imports = [ 7 | "${toString modulesPath}/installer/sd-card/sd-image-aarch64-installer.nix" 8 | ]; 9 | 10 | formatAttr = "sdImage"; 11 | fileExtension = ".img.*"; 12 | } 13 | -------------------------------------------------------------------------------- /formats/sd-aarch64.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | imports = [ 9 | "${toString modulesPath}/installer/sd-card/sd-image-aarch64.nix" 10 | ]; 11 | 12 | formatAttr = "sdImage"; 13 | fileExtension = ".img.*"; 14 | } 15 | -------------------------------------------------------------------------------- /formats/sd-x86_64.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | imports = [ 9 | "${toString modulesPath}/installer/sd-card/sd-image-x86_64.nix" 10 | ]; 11 | 12 | formatAttr = "sdImage"; 13 | fileExtension = ".img.*"; 14 | } 15 | -------------------------------------------------------------------------------- /formats/proxmox-lxc.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | modulesPath, 4 | ... 5 | }: { 6 | imports = [ 7 | "${toString modulesPath}/virtualisation/proxmox-lxc.nix" 8 | ]; 9 | boot.loader.grub.enable = lib.mkForce false; 10 | boot.loader.systemd-boot.enable = lib.mkForce false; 11 | formatAttr = "tarball"; 12 | fileExtension = ".tar.xz"; 13 | } 14 | -------------------------------------------------------------------------------- /formats/iso.nix: -------------------------------------------------------------------------------- 1 | { 2 | modulesPath, 3 | ... 4 | }: { 5 | imports = [ 6 | "${toString modulesPath}/installer/cd-dvd/iso-image.nix" 7 | ]; 8 | 9 | # EFI booting 10 | isoImage.makeEfiBootable = true; 11 | 12 | # USB booting 13 | isoImage.makeUsbBootable = true; 14 | 15 | formatAttr = "isoImage"; 16 | fileExtension = ".iso"; 17 | } 18 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | queue_rules: 2 | - name: default 3 | queue_conditions: 4 | - base=master 5 | - label~=merge-queue|dependencies 6 | merge_conditions: 7 | - check-success=buildbot/nix-build 8 | merge_method: rebase 9 | 10 | pull_request_rules: 11 | - name: merge using the merge queue 12 | conditions: [] 13 | actions: 14 | queue: 15 | -------------------------------------------------------------------------------- /formats/lxc.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | modulesPath, 6 | ... 7 | }: { 8 | imports = [ 9 | "${toString modulesPath}/virtualisation/lxc-container.nix" 10 | ]; 11 | 12 | boot.loader.grub.enable = lib.mkForce false; 13 | boot.loader.systemd-boot.enable = lib.mkForce false; 14 | formatAttr = "tarball"; 15 | fileExtension = ".tar.xz"; 16 | } 17 | -------------------------------------------------------------------------------- /formats/lxc-metadata.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | modulesPath, 5 | pkgs, 6 | ... 7 | }: { 8 | imports = [ 9 | "${toString modulesPath}/virtualisation/lxc-container.nix" 10 | ]; 11 | 12 | boot.loader.grub.enable = lib.mkForce false; 13 | boot.loader.systemd-boot.enable = lib.mkForce false; 14 | formatAttr = "metadata"; 15 | fileExtension = ".tar.xz"; 16 | } 17 | -------------------------------------------------------------------------------- /formats/docker.nix: -------------------------------------------------------------------------------- 1 | { 2 | modulesPath, 3 | lib, 4 | ... 5 | }: { 6 | imports = [ 7 | "${toString modulesPath}/virtualisation/docker-image.nix" 8 | ]; 9 | 10 | boot.loader.grub.enable = lib.mkForce false; 11 | boot.loader.systemd-boot.enable = lib.mkForce false; 12 | services.journald.console = "/dev/console"; 13 | 14 | formatAttr = "tarball"; 15 | fileExtension = ".tar.xz"; 16 | } 17 | -------------------------------------------------------------------------------- /configuration.nix: -------------------------------------------------------------------------------- 1 | { config, lib, ... }: 2 | { 3 | services.sshd.enable = true; 4 | services.nginx.enable = true; 5 | 6 | networking.firewall.allowedTCPPorts = [ 80 ]; 7 | 8 | system.stateVersion = config.system.nixos.release; 9 | 10 | users.users.root.password = "nixos"; 11 | services.openssh.settings.PermitRootLogin = lib.mkOverride 999 "yes"; 12 | services.getty.autologinUser = lib.mkOverride 999 "root"; 13 | } 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | SHARE ?= $(PREFIX)/share/nixos-generator 3 | 4 | all: 5 | 6 | SOURCES = formats format-module.nix configuration.nix lib.nix nixos-generate.nix 7 | 8 | install: 9 | mkdir -p $(PREFIX)/bin $(SHARE) 10 | sed \ 11 | -e "s|libexec_dir=\".*\"|libexec_dir=\"$(SHARE)\"|" \ 12 | -e "s|#!/usr/bin/env.*|#!/usr/bin/env bash|" \ 13 | nixos-generate > $(PREFIX)/bin/nixos-generate 14 | chmod 755 $(PREFIX)/bin/nixos-generate 15 | cp -r $(SOURCES) $(SHARE) 16 | -------------------------------------------------------------------------------- /formats/install-iso.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | modulesPath, 4 | ... 5 | }: { 6 | imports = [ 7 | "${toString modulesPath}/installer/cd-dvd/installation-cd-base.nix" 8 | ]; 9 | 10 | # override installation-cd-base and enable wpa and sshd start at boot 11 | systemd.services.wpa_supplicant.wantedBy = lib.mkForce ["multi-user.target"]; 12 | systemd.services.sshd.wantedBy = lib.mkForce ["multi-user.target"]; 13 | 14 | formatAttr = "isoImage"; 15 | fileExtension = ".iso"; 16 | } 17 | -------------------------------------------------------------------------------- /package.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenv, 3 | makeWrapper, 4 | jq, 5 | coreutils, 6 | findutils, 7 | lib, 8 | gawk, 9 | }: 10 | stdenv.mkDerivation { 11 | name = "nixos-generate"; 12 | src = ./.; 13 | meta.description = "Collection of image builders"; 14 | nativeBuildInputs = [makeWrapper]; 15 | installFlags = ["PREFIX=$(out)"]; 16 | postFixup = '' 17 | wrapProgram $out/bin/nixos-generate \ 18 | --prefix PATH : ${lib.makeBinPath [jq coreutils findutils gawk]} 19 | ''; 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/update-flake-lock.yml: -------------------------------------------------------------------------------- 1 | name: update-flake-lock 2 | on: 3 | workflow_dispatch: # allows manual triggering 4 | schedule: 5 | - cron: '0 0 * * 1,4' # Run twice a week 6 | 7 | jobs: 8 | lockfile: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@v4 13 | - name: Install Nix 14 | uses: cachix/install-nix-action@v31 15 | with: 16 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 17 | - name: Update flake.lock 18 | uses: DeterminateSystems/update-flake-lock@v26 19 | with: 20 | pr-labels: | 21 | merge-queue 22 | -------------------------------------------------------------------------------- /formats/vm-nogui.nix: -------------------------------------------------------------------------------- 1 | {pkgs, ...}: let 2 | resize = pkgs.writeScriptBin "resize" '' 3 | if [ -e /dev/tty ]; then 4 | old=$(stty -g) 5 | stty raw -echo min 0 time 5 6 | printf '\033[18t' > /dev/tty 7 | IFS=';t' read -r _ rows cols _ < /dev/tty 8 | stty "$old" 9 | stty cols "$cols" rows "$rows" 10 | fi 11 | ''; # https://unix.stackexchange.com/questions/16578/resizable-serial-console-window 12 | in { 13 | imports = [ 14 | ./vm.nix 15 | ]; 16 | virtualisation.graphics = false; 17 | virtualisation.qemu.options = ["-serial mon:stdio"]; 18 | 19 | environment.systemPackages = [resize]; 20 | environment.loginShellInit = "${resize}/bin/resize"; 21 | } 22 | -------------------------------------------------------------------------------- /formats/raw-efi.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | options, 5 | pkgs, 6 | modulesPath, 7 | ... 8 | }: let 9 | inherit (import ../lib.nix {inherit lib options;}) maybe; 10 | in { 11 | imports = [./raw.nix]; 12 | 13 | boot.loader.grub = { 14 | device = "nodev"; 15 | efiSupport = true; 16 | efiInstallAsRemovable = true; 17 | }; 18 | 19 | fileSystems."/boot" = { 20 | device = "/dev/disk/by-label/ESP"; 21 | fsType = "vfat"; 22 | }; 23 | 24 | system.build.raw = maybe.mkOverride 99 (import "${toString modulesPath}/../lib/make-disk-image.nix" { 25 | inherit lib config pkgs; 26 | partitionTableType = "efi"; 27 | inherit (config.virtualisation) diskSize; 28 | format = "raw"; 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /formats/cloudstack.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | imports = [ 9 | "${toString modulesPath}/virtualisation/cloudstack-config.nix" 10 | ]; 11 | 12 | fileSystems."/".fsType = lib.mkDefault "ext4"; 13 | 14 | system.build.cloudstackImage = import "${toString modulesPath}/../lib/make-disk-image.nix" { 15 | inherit lib config pkgs; 16 | inherit (config.virtualisation) diskSize; 17 | format = "qcow2"; 18 | configFile = 19 | pkgs.writeText "configuration.nix" 20 | '' 21 | { 22 | imports = [ "${toString modulesPath}/virtualisation/cloudstack-config.nix" ]; 23 | } 24 | ''; 25 | }; 26 | 27 | formatAttr = "cloudstackImage"; 28 | } 29 | -------------------------------------------------------------------------------- /checks/test-customize-format.nix: -------------------------------------------------------------------------------- 1 | { 2 | nixpkgs ? , 3 | system ? builtins.currentSystem, 4 | lib ? import (nixpkgs + /lib), 5 | }: let 6 | nixosSystem = import (nixpkgs + /nixos/lib/eval-config.nix); 7 | 8 | userModule1 = {...}: { 9 | formatConfigs.amazon.amazonImage.name = "xyz"; 10 | }; 11 | 12 | userModule2 = {...}: { 13 | formatConfigs.amazon.amazonImage.name = lib.mkForce "custom-name"; 14 | }; 15 | 16 | conf = nixosSystem { 17 | inherit system; 18 | modules = [ 19 | ../configuration.nix 20 | ../all-formats.nix 21 | userModule1 22 | userModule2 23 | ]; 24 | }; 25 | in 26 | assert lib.hasInfix "custom-name" "${conf.config.formats.amazon}"; 27 | conf.config.formats.amazon 28 | -------------------------------------------------------------------------------- /formats/raw.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | fileSystems."/" = { 9 | device = "/dev/disk/by-label/nixos"; 10 | autoResize = true; 11 | fsType = "ext4"; 12 | }; 13 | 14 | boot = { 15 | growPartition = true; 16 | kernelParams = ["console=ttyS0"]; 17 | loader.grub.device = lib.mkDefault "/dev/vda"; 18 | loader.timeout = lib.mkDefault 0; 19 | initrd.availableKernelModules = ["uas"]; 20 | }; 21 | 22 | system.build.raw = import "${toString modulesPath}/../lib/make-disk-image.nix" { 23 | inherit lib config pkgs; 24 | inherit (config.virtualisation) diskSize; 25 | format = "raw"; 26 | }; 27 | 28 | formatAttr = "raw"; 29 | fileExtension = ".img"; 30 | } 31 | -------------------------------------------------------------------------------- /checks/test-all-formats.nix: -------------------------------------------------------------------------------- 1 | { 2 | nixpkgs ? , 3 | system ? builtins.currentSystem, 4 | lib ? import (nixpkgs + /lib), 5 | }: let 6 | nixosSystem = import (nixpkgs + /nixos/lib/eval-config.nix); 7 | 8 | conf = nixosSystem { 9 | inherit system; 10 | modules = [ 11 | ../configuration.nix 12 | ../all-formats.nix 13 | ]; 14 | }; 15 | 16 | exclude = 17 | (lib.optionalAttrs (system != "aarch64-linux") { 18 | sd-aarch64 = true; 19 | sd-aarch64-installer = true; 20 | }) 21 | // (lib.optionalAttrs (system != "x86_64-linux") { 22 | azure = true; 23 | vagrant-virtualbox = true; 24 | virtualbox = true; 25 | vmware = true; 26 | }); 27 | 28 | testedFormats = 29 | lib.filterAttrs 30 | (name: _: ! exclude ? ${name}) 31 | conf.config.formats; 32 | in 33 | testedFormats 34 | -------------------------------------------------------------------------------- /format-module.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | modulesPath, 4 | ... 5 | }: { 6 | _file = ./format-module.nix; 7 | # This deliberate key makes sure this module will be deduplicated 8 | # regardless of the accessor path: either via flake's nixosModule 9 | # or as part of the nixos-generate command. These two store paths 10 | # of the module may differ and hence don't serve as a key 11 | key = "github:nix-community/nixos-generators/format-module.nix"; 12 | 13 | imports = ["${modulesPath}/virtualisation/disk-size-option.nix"]; 14 | 15 | options = { 16 | fileExtension = lib.mkOption { 17 | type = lib.types.str; 18 | description = "Declare the path of the wanted file in the output directory"; 19 | default = ""; 20 | }; 21 | formatAttr = lib.mkOption { 22 | type = lib.types.str; 23 | description = "Declare the default attribute to build"; 24 | }; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /nixos-generate.nix: -------------------------------------------------------------------------------- 1 | { 2 | nixpkgs ? , 3 | configuration ? , 4 | system ? builtins.currentSystem, 5 | diskSize ? "auto", 6 | formatConfig, 7 | flakeUri ? null, 8 | flakeAttr ? null, 9 | }: let 10 | module = import ./format-module.nix; 11 | 12 | # Will only get evaluated when used, so no worries 13 | flake = builtins.getFlake flakeUri; 14 | flakeSystem = flake.outputs.packages."${system}".nixosConfigurations."${flakeAttr}" or flake.outputs.nixosConfigurations."${flakeAttr}"; 15 | in 16 | if flakeUri != null 17 | then 18 | flakeSystem.extendModules { 19 | modules = [module formatConfig]; 20 | } 21 | else 22 | import "${toString nixpkgs}/nixos/lib/eval-config.nix" { 23 | inherit system; 24 | modules = [ 25 | {virtualisation.diskSize = diskSize;} 26 | module 27 | formatConfig 28 | configuration 29 | ]; 30 | } 31 | -------------------------------------------------------------------------------- /.included.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | 4 | .tar_option: 5 | after_script: 6 | - tar -cvhf $uploadPath.tar ./$uploadPath 7 | artifacts: 8 | name: "$uploadPath" 9 | paths: 10 | - $uploadPath.tar 11 | 12 | .template: 13 | only: 14 | - web 15 | stage: build 16 | image: lnl7/nix:latest 17 | before_script: 18 | - nix --version 19 | - chmod +w /etc/nix/nix.conf 20 | - echo "system-features = kvm" >> /etc/nix/nix.conf 21 | - sed -i -e 's/ --no-out-link//g' nixos-generate 22 | - mkdir $uploadPath 23 | script: 24 | - nix-shell --command './nixos-generate -f $formats -I nixpkgs=channel:nixos-$nixpkgs_ver' |& tee $uploadPath/build.log 25 | # Last line of output should be the path of a regular file (or symlink 26 | # to a regular file) in the Nix store. 27 | - storePath=$(tail -n 1 $uploadPath/build.log) && test -f "$storePath" && test "/nix/store/${storePath#/nix/store/}" = "$storePath" 28 | - mv $(realpath result) $uploadPath 29 | artifacts: 30 | name: "$uploadPath" 31 | paths: 32 | - $uploadPath 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 lassulus and the nixos-generators contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /formats/qcow.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | # for virtio kernel drivers 9 | imports = [ 10 | "${toString modulesPath}/profiles/qemu-guest.nix" 11 | ]; 12 | 13 | fileSystems."/" = { 14 | device = "/dev/disk/by-label/nixos"; 15 | autoResize = true; 16 | fsType = "ext4"; 17 | }; 18 | 19 | boot.growPartition = true; 20 | boot.kernelParams = ["console=ttyS0"]; 21 | boot.loader.grub.device = 22 | if (pkgs.stdenv.system == "x86_64-linux") 23 | then (lib.mkDefault "/dev/vda") 24 | else (lib.mkDefault "nodev"); 25 | 26 | boot.loader.grub.efiSupport = lib.mkIf (pkgs.stdenv.system != "x86_64-linux") (lib.mkDefault true); 27 | boot.loader.grub.efiInstallAsRemovable = lib.mkIf (pkgs.stdenv.system != "x86_64-linux") (lib.mkDefault true); 28 | boot.loader.timeout = 0; 29 | 30 | system.build.qcow = import "${toString modulesPath}/../lib/make-disk-image.nix" { 31 | inherit lib config pkgs; 32 | inherit (config.virtualisation) diskSize; 33 | format = "qcow2"; 34 | partitionTableType = "hybrid"; 35 | }; 36 | 37 | formatAttr = "qcow"; 38 | fileExtension = ".qcow2"; 39 | } 40 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixlib": { 4 | "locked": { 5 | "lastModified": 1736643958, 6 | "narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=", 7 | "owner": "nix-community", 8 | "repo": "nixpkgs.lib", 9 | "rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nix-community", 14 | "repo": "nixpkgs.lib", 15 | "type": "github" 16 | } 17 | }, 18 | "nixpkgs": { 19 | "locked": { 20 | "lastModified": 1736657626, 21 | "narHash": "sha256-FWlPMUzp0lkQBdhKlPqtQdqmp+/C+1MBiEytaYfrCTY=", 22 | "owner": "NixOS", 23 | "repo": "nixpkgs", 24 | "rev": "2f9e2f85cb14a46410a1399aa9ea7ecf433e422e", 25 | "type": "github" 26 | }, 27 | "original": { 28 | "owner": "NixOS", 29 | "ref": "nixpkgs-unstable", 30 | "repo": "nixpkgs", 31 | "type": "github" 32 | } 33 | }, 34 | "root": { 35 | "inputs": { 36 | "nixlib": "nixlib", 37 | "nixpkgs": "nixpkgs" 38 | } 39 | } 40 | }, 41 | "root": "root", 42 | "version": 7 43 | } 44 | -------------------------------------------------------------------------------- /lib.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | options, 4 | }: let 5 | # See https://github.com/NixOS/nixpkgs/commit/ccb85a53b6a496984073227fd8c4d4c58889f421 6 | # This commit changed the type of `system.build` from a lazy attribute set to 7 | # a submodule. Prior to this commit, it doesn't make sense to qualify, e.g. 8 | # the `system.build.kexec_tarball` definition with `lib.mkForce`, as this 9 | # would result in setting the (final/resolved) value of 10 | # `system.build.kexec_tarball` to something like: 11 | # { 12 | # _type = "override"; 13 | # content = <...>; 14 | # priority = 50; 15 | # } 16 | # However, since this commit, `system.build.kexec_tarball` *must* be defined 17 | # using `lib.mkForce`; otherwise, Nix bails out with a complaint about 18 | # `system.build.kexec_tarball` being defined in multiple locations. 19 | systemBuildIsSubmodule = options.system.build.type.name == "submodule"; 20 | 21 | optionsLookSane = lib.hasAttrByPath ["system" "build" "type" "name"] options; 22 | in 23 | assert (lib.assertMsg optionsLookSane "`options' must be the NixOS module `options' argument"); { 24 | maybe = 25 | { 26 | mkForce = lib.id; 27 | mkOverride = _: lib.id; 28 | } 29 | // (lib.optionalAttrs systemBuildIsSubmodule { 30 | inherit (lib) mkForce mkOverride; 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /formats/linode.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | imports = [ 9 | "${toString modulesPath}/virtualisation/linode-image.nix" 10 | ]; 11 | 12 | formatAttr = "linodeImage"; 13 | fileExtension = ".img.gz"; 14 | 15 | system.build.linodeImage = lib.mkForce (import "${toString modulesPath}/../lib/make-disk-image.nix" { 16 | inherit lib config pkgs; 17 | partitionTableType = "none"; 18 | format = "raw"; 19 | postVM = '' 20 | ${pkgs.pigz}/bin/pigz -9 $out/nixos.img 21 | ''; 22 | }); 23 | 24 | # Enable LISH and Linode booting w/ GRUB 25 | boot = { 26 | growPartition = true; 27 | 28 | loader = { 29 | grub = { 30 | fsIdentifier = "label"; 31 | 32 | # Link /boot/grub2 to /boot/grub: 33 | extraInstallCommands = '' 34 | ${pkgs.coreutils}/bin/ln -fs /boot/grub /boot/grub2 35 | ''; 36 | 37 | # Remove GRUB splash image: 38 | splashImage = null; 39 | }; 40 | }; 41 | }; 42 | 43 | # Hardware option detected by nixos-generate-config: 44 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 45 | 46 | # Install diagnostic tools for Linode support: 47 | environment.systemPackages = with pkgs; [ 48 | linode-cli 49 | ]; 50 | 51 | networking = { 52 | enableIPv6 = true; 53 | interfaces.eth0 = { 54 | tempAddress = "disabled"; 55 | useDHCP = true; 56 | }; 57 | }; 58 | 59 | services.qemuGuest.enable = true; 60 | } 61 | -------------------------------------------------------------------------------- /formats/qcow-efi.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | modulesPath, 6 | ... 7 | }: { 8 | # for virtio kernel drivers 9 | imports = [ 10 | "${toString modulesPath}/profiles/qemu-guest.nix" 11 | ]; 12 | 13 | options = { 14 | boot = { 15 | consoles = lib.mkOption { 16 | default = 17 | ["ttyS0"] 18 | ++ (lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200") 19 | ++ (lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200"); 20 | description = "Kernel console boot flags to pass to boot.kernelParams"; 21 | example = ["ttyS2,115200"]; 22 | }; 23 | }; 24 | }; 25 | 26 | config = { 27 | fileSystems."/" = { 28 | device = "/dev/disk/by-label/nixos"; 29 | autoResize = true; 30 | fsType = "ext4"; 31 | }; 32 | 33 | fileSystems."/boot" = { 34 | device = "/dev/disk/by-label/ESP"; 35 | fsType = "vfat"; 36 | }; 37 | 38 | boot.growPartition = true; 39 | boot.kernelParams = map (c: "console=${c}") config.boot.consoles; 40 | boot.loader.grub.device = "nodev"; 41 | 42 | boot.loader.grub.efiSupport = true; 43 | boot.loader.grub.efiInstallAsRemovable = true; 44 | boot.loader.timeout = 0; 45 | 46 | system.build.qcow-efi = import "${toString modulesPath}/../lib/make-disk-image.nix" { 47 | inherit lib config pkgs; 48 | inherit (config.virtualisation) diskSize; 49 | format = "qcow2"; 50 | partitionTableType = "efi"; 51 | }; 52 | 53 | formatAttr = "qcow-efi"; 54 | fileExtension = ".qcow2"; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /checks/test-all-formats-flake/flake.nix: -------------------------------------------------------------------------------- 1 | /* 2 | Tests using the all-formats module through a flake. 3 | - Tests if foramts can be customized. 4 | - Tests if new foramts can be added 5 | */ 6 | { 7 | inputs = { 8 | nixpkgs.url = "nixpkgs/nixos-unstable"; 9 | nixos-generators = { 10 | url = "github:nix-community/nixos-generators"; 11 | inputs.nixpkgs.follows = "nixpkgs"; 12 | }; 13 | }; 14 | outputs = { 15 | self, 16 | nixpkgs, 17 | nixos-generators, 18 | ... 19 | }: { 20 | nixosModules.my-machine = {config, ...}: { 21 | imports = [ 22 | nixos-generators.nixosModules.all-formats 23 | ]; 24 | 25 | nixpkgs.hostPlatform = "x86_64-linux"; 26 | 27 | # customize an existing format 28 | formatConfigs.vmware = {config, ...}: { 29 | services.openssh.enable = false; 30 | }; 31 | 32 | # define a new format 33 | formatConfigs.my-custom-format = { 34 | config, 35 | modulesPath, 36 | ... 37 | }: { 38 | imports = ["${toString modulesPath}/installer/cd-dvd/installation-cd-base.nix"]; 39 | formatAttr = "isoImage"; 40 | fileExtension = ".iso"; 41 | networking.wireless.networks = { 42 | # ... 43 | }; 44 | }; 45 | }; 46 | 47 | nixosConfigurations.my-machine = nixpkgs.lib.nixosSystem { 48 | modules = [self.nixosModules.my-machine]; 49 | }; 50 | 51 | checks.x86_64-linux = { 52 | test-flake_vmware = 53 | self.nixosConfigurations.my-machine.config.formats.vmware; 54 | test-flake_my-custom-format = 55 | self.nixosConfigurations.my-machine.config.formats.my-custom-format; 56 | }; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /all-formats.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | extendModules, 6 | ... 7 | }: let 8 | inherit 9 | (lib) 10 | types 11 | ; 12 | # attrs of all format modules from ./formats 13 | formatModules = 14 | lib.flip lib.mapAttrs' (builtins.readDir ./formats) 15 | (fname: type: { 16 | name = lib.removeSuffix ".nix" fname; 17 | value = ./formats + "/${fname}"; 18 | }); 19 | 20 | # function to evaluate a given format to a config 21 | evalFormat = formatModule: 22 | extendModules { 23 | modules = [ 24 | ./format-module.nix 25 | formatModule 26 | ]; 27 | }; 28 | 29 | # evaluated configs for all formats 30 | allConfigs = lib.mapAttrs (formatName: evalFormat) config.formatConfigs; 31 | 32 | # adds an evaluated `config` to the derivation attributes of a format for introspection 33 | exposeConfig = conf: output: 34 | output.overrideAttrs (old: { 35 | passthru.config = conf.config; 36 | }); 37 | 38 | # attrset of formats to be exposed under config.system.formats 39 | formats = lib.flip lib.mapAttrs allConfigs ( 40 | formatName: conf: 41 | exposeConfig conf ( 42 | pkgs.runCommand "${conf.config.system.build.${conf.config.formatAttr}.name}" {} '' 43 | set -efu 44 | target=$(find '${conf.config.system.build.${conf.config.formatAttr}}' -name '*${conf.config.fileExtension}' -xtype f -print -quit) 45 | if [ -z "$target" ]; then 46 | echo "No target file found for ${conf.config.formatAttr} format" 47 | echo "Check the content of this build path: ${conf.config.system.build.${conf.config.formatAttr}}" 48 | exit 1 49 | fi 50 | mkdir $out 51 | ln -s "$target" "$out/$(basename "$target")" 52 | '' 53 | ) 54 | ); 55 | in { 56 | _file = ./all-formats.nix; 57 | # This deliberate key makes sure this module will be deduplicated 58 | # regardless of the accessor path: either via flake's nixosModule 59 | # or as part of the nixos-generate command. These two store paths 60 | # of the module may differ and hence don't serve as a key 61 | key = "github:nix-community/nixos-generators/all-formats.nix"; 62 | 63 | # declare option for exposing all formats 64 | options.formats = lib.mkOption { 65 | type = lib.types.lazyAttrsOf lib.types.raw; 66 | description = '' 67 | Different target formats generated for this NixOS configuration. 68 | ''; 69 | }; 70 | 71 | options.formatConfigs = lib.mkOption { 72 | type = types.attrsOf types.deferredModule; 73 | }; 74 | 75 | # expose all formats 76 | config.formats = formats; 77 | 78 | # 79 | config.formatConfigs = lib.flip lib.mapAttrs formatModules (name: module: { 80 | imports = [module]; 81 | }); 82 | } 83 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | include: .included.yml 2 | 3 | variables: 4 | GIT_DEPTH: 1 5 | nixpkgs_ver: "19.09" 6 | uploadPath: ./nixos-$CI_JOB_NAME-$CI_PIPELINE_ID 7 | 8 | # job names are sorted alphabetically 9 | 10 | azure: 11 | variables: 12 | formats: azure 13 | extends: 14 | - .template 15 | 16 | # doesn't build 17 | .cloudstack: 18 | variables: 19 | formats: cloudstack 20 | extends: 21 | - .template 22 | 23 | do: 24 | variables: 25 | nixpkgs_ver: unstable 26 | formats: do 27 | extends: 28 | - .template 29 | 30 | gce: 31 | variables: 32 | formats: gce 33 | extends: 34 | - .template 35 | 36 | install-iso: 37 | variables: 38 | formats: install-iso 39 | extends: 40 | - .template 41 | 42 | install-iso-hyperv: 43 | variables: 44 | formats: install-iso-hyperv 45 | extends: 46 | - .template 47 | 48 | iso: 49 | variables: 50 | formats: iso 51 | extends: 52 | - .template 53 | 54 | kexec: 55 | variables: 56 | formats: kexec 57 | extends: 58 | - .template 59 | 60 | kexec-bundle: 61 | variables: 62 | formats: kexec-bundle 63 | extends: 64 | - .template 65 | 66 | lxc: 67 | variables: 68 | formats: lxc 69 | extends: 70 | - .template 71 | 72 | lxc-metadata: 73 | variables: 74 | formats: lxc-metadata 75 | extends: 76 | - .template 77 | 78 | openstack: 79 | variables: 80 | formats: openstack 81 | extends: 82 | - .template 83 | 84 | qcow: 85 | variables: 86 | formats: qcow 87 | extends: 88 | - .template 89 | 90 | raw: 91 | variables: 92 | formats: raw 93 | extends: 94 | - .template 95 | 96 | # todo 97 | .sd-aarch64: 98 | variables: 99 | formats: sd-aarch64 100 | script: 101 | - nix-shell --command './nixos-generate -f $formats --nixpkgs_ver $nixpkgs_ver --system aarch64-linux' 102 | extends: 103 | - .template 104 | 105 | # todo 106 | .sd-aarch64-installer: 107 | variables: 108 | formats: sd-aarch64-installer 109 | script: 110 | - nix-shell --command './nixos-generate -f $formats --nixpkgs_ver $nixpkgs_ver --system aarch64-linux' 111 | extends: 112 | - .template 113 | 114 | virtualbox: 115 | variables: 116 | formats: virtualbox 117 | extends: 118 | - .template 119 | 120 | vm: 121 | variables: 122 | formats: vm 123 | extends: 124 | - .template 125 | - .tar_option 126 | 127 | vm-nogui: 128 | variables: 129 | formats: vm-nogui 130 | extends: 131 | - .template 132 | - .tar_option 133 | -------------------------------------------------------------------------------- /formats/kexec.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | pkgs, 4 | lib, 5 | modulesPath, 6 | options, 7 | ... 8 | }: let 9 | inherit (import ../lib.nix {inherit lib options;}) maybe; 10 | in { 11 | imports = [ 12 | "${toString modulesPath}/installer/netboot/netboot-minimal.nix" 13 | ]; 14 | 15 | system.build = rec { 16 | image = pkgs.runCommand "image" {buildInputs = [pkgs.nukeReferences];} '' 17 | mkdir $out 18 | cp ${config.system.build.kernel}/${config.system.boot.loader.kernelFile} $out/kernel 19 | cp ${config.system.build.netbootRamdisk}/initrd $out/initrd 20 | echo "init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" > $out/cmdline 21 | nuke-refs $out/kernel 22 | ''; 23 | 24 | kexec_script = pkgs.writeTextFile { 25 | executable = true; 26 | name = "kexec-nixos"; 27 | text = '' 28 | #!${pkgs.stdenv.shell} 29 | export PATH=${pkgs.kexec-tools}/bin:${pkgs.cpio}/bin:$PATH 30 | set -x 31 | set -e 32 | cd $(mktemp -d) 33 | pwd 34 | mkdir initrd 35 | pushd initrd 36 | if [ -e /ssh_pubkey ]; then 37 | cat /ssh_pubkey >> authorized_keys 38 | fi 39 | find -type f | cpio -o -H newc | gzip -9 > ../extra.gz 40 | popd 41 | cat ${image}/initrd extra.gz > final.gz 42 | 43 | kexec -l ${image}/kernel --initrd=final.gz --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" 44 | sync 45 | echo "executing kernel, filesystems will be improperly umounted" 46 | kexec -e 47 | ''; 48 | }; 49 | 50 | kexec_tarball = maybe.mkForce (pkgs.callPackage "${toString modulesPath}/../lib/make-system-tarball.nix" { 51 | storeContents = [ 52 | { 53 | object = config.system.build.kexec_script; 54 | symlink = "/kexec_nixos"; 55 | } 56 | ]; 57 | contents = []; 58 | }); 59 | 60 | kexec_tarball_self_extract_script = pkgs.writeTextFile { 61 | executable = true; 62 | name = "kexec-nixos"; 63 | text = '' 64 | #!/bin/sh 65 | set -eu 66 | ARCHIVE=`awk '/^__ARCHIVE_BELOW__/ { print NR + 1; exit 0; }' $0` 67 | 68 | tail -n+$ARCHIVE $0 | tar xJ -C / 69 | /kexec_nixos 70 | 71 | exit 1 72 | 73 | __ARCHIVE_BELOW__ 74 | ''; 75 | }; 76 | 77 | kexec_bundle = pkgs.runCommand "kexec_bundle" {} '' 78 | cat \ 79 | ${kexec_tarball_self_extract_script} \ 80 | ${config.system.build.kexec_tarball}/tarball/nixos-system-${config.system.build.kexec_tarball.system}.tar.xz \ 81 | > $out 82 | chmod +x $out 83 | ''; 84 | }; 85 | 86 | boot.loader.grub.enable = lib.mkForce false; 87 | boot.loader.systemd-boot.enable = lib.mkForce false; 88 | boot.kernelParams = [ 89 | "console=ttyS0,115200" # allows certain forms of remote access, if the hardware is setup right 90 | "panic=30" 91 | "boot.panic_on_fail" # reboot the machine upon fatal boot issues 92 | ]; 93 | systemd.services.sshd.wantedBy = lib.mkForce ["multi-user.target"]; 94 | networking.hostName = lib.mkDefault "kexec"; 95 | 96 | formatAttr = "kexec_tarball"; 97 | fileExtension = ".tar.xz"; 98 | 99 | boot.initrd.postMountCommands = '' 100 | mkdir -p /mnt-root/root/.ssh/ 101 | cp /authorized_keys /mnt-root/root/.ssh/ 102 | ''; 103 | } 104 | -------------------------------------------------------------------------------- /nixos-generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | ## Configuration 5 | 6 | readonly libexec_dir="${0%/*}" 7 | readonly format_dir=$libexec_dir/formats 8 | 9 | configuration=${NIXOS_CONFIG:-$libexec_dir/configuration.nix} 10 | flake_uri= 11 | flake_attr= 12 | format_path= 13 | target_system= 14 | cores= 15 | run= 16 | nix_args=( 17 | "$libexec_dir/nixos-generate.nix" 18 | ) 19 | has_outlink=false 20 | nix_build_args=() 21 | 22 | ## Functions 23 | 24 | showUsage() { 25 | cat <&2 58 | exit 1 59 | } 60 | 61 | # TODO: Is there a better name for this? 62 | fixDiskSizeFormat() { 63 | # If the arg is an int, pass it back unchanged: 64 | if [[ "$1" =~ ^[0-9][0-9]*$ ]]; then 65 | echo "$1" 66 | return 67 | fi 68 | 69 | # If the arg is _not_ an int, we'll assume it's a string. 70 | # Therefore, we'll make sure it's wrapped in quotes, so its eval'd as a string by Nix: 71 | echo "\"$1\"" 72 | } 73 | 74 | ## Main ## 75 | 76 | while [[ $# -gt 0 ]]; do 77 | case "$1" in 78 | -c | --configuration) 79 | configuration=$2 80 | shift 81 | ;; 82 | --flake) 83 | # Note: The reason I'm using awk over cut is because cutting with an 84 | # out-of-bounds field will return the last in-bound field instead of empty 85 | # string. 86 | flake="$(echo "$2" | awk -F'#' '{ print $1; }')" 87 | 88 | flake_uri="$(nix flake metadata --json -- "$flake" | jq -r .url)" 89 | flake_attr="$(echo "$2" | awk -F'#' '{ print $2; }')" 90 | shift 91 | ;; 92 | --cores) 93 | cores=$2 94 | shift 95 | ;; 96 | --disk-size) 97 | # Note: make sure integers are not incorrectly interpreted as strings by Nix: 98 | nix_build_args+=("--arg" "diskSize" "$(fixDiskSizeFormat "$2")") 99 | shift 100 | ;; 101 | --special-arg) 102 | nix_build_args+=("--argstr" "$2" "$3") 103 | shift 2 104 | ;; 105 | --option) 106 | nix_args+=("$1" "$2" "$3") 107 | shift 2 108 | ;; 109 | -f | --format) 110 | format_path=$format_dir/$2.nix 111 | shift 112 | ;; 113 | --format-path) 114 | format_path=$2 115 | shift 116 | ;; 117 | --help) 118 | showUsage 119 | exit 120 | ;; 121 | --list) 122 | listFormats 123 | exit 124 | ;; 125 | --run) 126 | run=1 127 | # default to the VM format 128 | if [[ -z $format_path ]]; then 129 | format_path=$format_dir/vm.nix 130 | fi 131 | ;; 132 | --show-trace) 133 | nix_args+=(--show-trace) 134 | ;; 135 | --system) 136 | target_system=$2 137 | shift 138 | ;; 139 | -I) 140 | nix_args+=(-I "$2") 141 | shift 142 | ;; 143 | -o | --out-link) 144 | nix_build_args+=(--out-link "$2") 145 | has_outlink=true 146 | shift 147 | ;; 148 | *) 149 | abort "unknown option $1" 150 | ;; 151 | esac 152 | shift 153 | done 154 | 155 | if ! $has_outlink; then 156 | nix_build_args+=(--no-link) 157 | fi 158 | 159 | if [[ -z $format_path ]]; then 160 | abort "missing format. use --help for more details" 161 | fi 162 | 163 | if [[ ! -f $format_path ]]; then 164 | abort "format file not found: $format_path" 165 | fi 166 | 167 | nix_args+=(--argstr formatConfig "$(realpath "$format_path")") 168 | 169 | if [[ -z "$flake_uri" ]]; then 170 | nix_args+=( 171 | -I "nixos-config=$configuration" 172 | ) 173 | else 174 | nix_args+=( 175 | --argstr flakeUri "$flake_uri" 176 | --argstr flakeAttr "${flake_attr:-"$(hostname)"}" 177 | ) 178 | fi 179 | 180 | if [[ -n $target_system ]]; then 181 | nix_args+=(--argstr system "$target_system") 182 | fi 183 | 184 | if [[ -n $cores ]]; then 185 | nix_args+=(--cores "$cores") 186 | fi 187 | 188 | formatAttr=$(nix-instantiate "${nix_args[@]}" --eval --json -A config.formatAttr | jq -r .) 189 | fileExtension=$(nix-instantiate "${nix_args[@]}" --eval --json -A config.fileExtension | jq -r .) 190 | 191 | out=$(nix build --extra-experimental-features nix-command -L --print-out-paths --file "${nix_args[@]}" "${nix_build_args[@]}" "config.system.build.$formatAttr") 192 | 193 | if [[ -z $run ]]; then 194 | # show the first file, ignoring nix-support 195 | find "$out" -name "*$fileExtension" -xtype f -print -quit 196 | else 197 | runner=$(find "$out"/bin -type l -print -quit) 198 | exec "$runner" 199 | fi 200 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "nixos-generators - one config, multiple formats"; 3 | 4 | # Lib dependency 5 | inputs.nixlib.url = "github:nix-community/nixpkgs.lib"; 6 | 7 | # Bin dependency 8 | inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 9 | 10 | outputs = { 11 | self, 12 | nixpkgs, 13 | nixlib, 14 | } @ inputs: let 15 | lib = nixpkgs.lib; 16 | 17 | callFlake = flake: let 18 | args = 19 | inputs 20 | // { 21 | nixos-generators = self; 22 | self = subFlake; 23 | }; 24 | subFlake = (import flake).outputs args; 25 | in 26 | subFlake; 27 | 28 | # Ensures a derivation's name can be accessed without evaluating it deeply. 29 | # Prevents `nix flake show` from being very slow. 30 | makeLazyDrv = name: drv: { 31 | inherit name; 32 | inherit 33 | (drv) 34 | drvPath 35 | outPath 36 | outputName 37 | system 38 | ; 39 | type = "derivation"; 40 | }; 41 | in 42 | # Library modules (depend on nixlib) 43 | { 44 | # export all generator formats in ./formats 45 | nixosModules = 46 | { 47 | all-formats = ./all-formats.nix; 48 | } 49 | // (nixlib.lib.mapAttrs' (file: _: { 50 | name = nixlib.lib.removeSuffix ".nix" file; 51 | # The exported module should include the internal format* options 52 | value.imports = [(./formats + "/${file}") ./format-module.nix]; 53 | }) (builtins.readDir ./formats)); 54 | 55 | # example usage in flakes: 56 | # outputs = { self, nixpkgs, nixos-generators, ...}: { 57 | # vmware = nixos-generators.nixosGenerate { 58 | # system = "x86_64-linux"; 59 | # modules = [./configuration.nix]; 60 | # format = "vmware"; 61 | # }; 62 | # } 63 | 64 | nixosGenerate = { 65 | pkgs ? null, 66 | lib ? nixpkgs.lib, 67 | nixosSystem ? nixpkgs.lib.nixosSystem, 68 | format, 69 | system ? null, 70 | specialArgs ? {}, 71 | modules ? [], 72 | customFormats ? {}, 73 | }: let 74 | extraFormats = 75 | lib.mapAttrs' ( 76 | name: value: 77 | lib.nameValuePair 78 | name 79 | { 80 | imports = [ 81 | value 82 | ./format-module.nix 83 | ]; 84 | } 85 | ) 86 | customFormats; 87 | formatModule = builtins.getAttr format (self.nixosModules // extraFormats); 88 | image = nixosSystem { 89 | inherit pkgs specialArgs; 90 | system = 91 | if system != null 92 | then system 93 | else pkgs.system; 94 | lib = 95 | if lib != null 96 | then lib 97 | else pkgs.lib; 98 | modules = 99 | [ 100 | formatModule 101 | ] 102 | ++ modules; 103 | }; 104 | in 105 | image.config.system.build.${image.config.formatAttr}; 106 | } 107 | // 108 | # Binary and Devshell outputs (depend on nixpkgs) 109 | ( 110 | let 111 | forAllSystems = nixpkgs.lib.genAttrs ["x86_64-linux" "x86_64-darwin" "i686-linux" "aarch64-linux" "aarch64-darwin"]; 112 | in { 113 | formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.alejandra); 114 | 115 | packages = forAllSystems (system: let 116 | pkgs = nixpkgs.legacyPackages."${system}"; 117 | in rec { 118 | default = nixos-generate; 119 | nixos-generate = pkgs.callPackage ./package.nix {}; 120 | }); 121 | 122 | checks = 123 | lib.recursiveUpdate 124 | (callFlake ./checks/test-all-formats-flake/flake.nix).checks 125 | ( 126 | lib.genAttrs [ 127 | "x86_64-linux" 128 | # We currently don't have kvm support on our builder 129 | #"aarch64-linux" 130 | ] 131 | ( 132 | system: let 133 | allFormats = import ./checks/test-all-formats.nix { 134 | inherit nixpkgs system; 135 | }; 136 | test-customize-format = import ./checks/test-customize-format.nix { 137 | inherit nixpkgs system; 138 | }; 139 | in 140 | lib.mapAttrs makeLazyDrv ( 141 | { 142 | inherit 143 | (self.packages.${system}) 144 | nixos-generate 145 | ; 146 | 147 | inherit test-customize-format; 148 | 149 | is-formatted = import ./checks/is-formatted.nix { 150 | pkgs = nixpkgs.legacyPackages.${system}; 151 | }; 152 | } 153 | // allFormats 154 | ) 155 | ) 156 | ); 157 | 158 | devShells = forAllSystems (system: let 159 | pkgs = nixpkgs.legacyPackages."${system}"; 160 | in { 161 | default = pkgs.mkShell { 162 | buildInputs = with pkgs; [jq coreutils findutils]; 163 | }; 164 | }); 165 | 166 | # Make it runnable with `nix run` 167 | apps = forAllSystems (system: let 168 | nixos-generate = { 169 | type = "app"; 170 | program = "${self.packages."${system}".nixos-generate}/bin/nixos-generate"; 171 | }; 172 | in { 173 | inherit nixos-generate; 174 | 175 | # Nix >= 2.7 flake output schema uses `apps..default` instead 176 | # of `defaultApp.` to signify the default app (the thing that 177 | # gets run with `nix run . -- `) 178 | default = nixos-generate; 179 | }); 180 | } 181 | ); 182 | } 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nixos-generators - one config, multiple formats 2 | 3 | The nixos-generators project allows to take the same NixOS configuration, and 4 | generate outputs for different target formats. 5 | 6 | Just put your stuff into the configuration.nix and then call one of the image builders. 7 | 8 | For example: 9 | ``` 10 | nixos-generate -f iso 11 | ``` 12 | 13 | or 14 | 15 | ``` 16 | nixos-generate -f iso -c /etc/nixos/configuration.nix 17 | ``` 18 | 19 | it echoes the path to a iso image, which you then can flash onto an usb-stick 20 | or mount & boot in a virtual machine. 21 | 22 | # Installation 23 | 24 | nixos-generators is part of [nixpkgs](https://search.nixos.org/packages?channel=unstable&show=nixos-generators&from=0&size=50&sort=relevance&type=packages&query=nixos-generator) and can be installed from there. 25 | 26 | nixos-generators can be also installed from source into the user profile like this: 27 | 28 | ```console 29 | nix-env -f https://github.com/nix-community/nixos-generators/archive/master.tar.gz -i 30 | ``` 31 | 32 | or for flakes users like this: 33 | 34 | ```console 35 | nix profile install github:nix-community/nixos-generators 36 | ``` 37 | 38 | or run from the nix flake without installing: 39 | 40 | ``` 41 | nix run github:nix-community/nixos-generators -- --help 42 | ``` 43 | 44 | ## Supported formats 45 | 46 | format | description 47 | --- | --- 48 | amazon | Amazon EC2 image 49 | azure | Microsoft azure image (Generation 1 / VHD) 50 | cloudstack | qcow2 image for cloudstack. 51 | do | Digital Ocean image 52 | docker | Docker image (uses systemd to run, probably only works in podman) 53 | gce | Google Compute image 54 | hyperv | Hyper-V Image (Generation 2 / VHDX) 55 | install-iso | Installer ISO 56 | install-iso-hyperv | Installer ISO with enabled hyper-v support 57 | iso | ISO 58 | kexec | kexec tarball (extract to / and run /kexec_nixos) 59 | kexec-bundle | same as before, but it's just an executable 60 | kubevirt | KubeVirt image 61 | linode | Linode image 62 | lxc | create a tarball which is importable as an lxc container, use together with lxc-metadata 63 | lxc-metadata | the necessary metadata for the lxc image to start, usage: `lxc image import $(nixos-generate -f lxc-metadata) $(nixos-generate -f lxc)` 64 | openstack | qcow2 image for openstack 65 | proxmox | [VMA](https://pve.proxmox.com/wiki/VMA) file for proxmox 66 | proxmox-lxc | LXC template for proxmox 67 | qcow | qcow2 image 68 | qcow-efi | qcow2 image with efi support 69 | raw | raw image with bios/mbr. for physical hardware, see the 'raw and raw-efi' section 70 | raw-efi | raw image with efi support. for physical hardware, see the 'raw and raw-efi' section 71 | sd-aarch64 | Like sd-aarch64-installer, but does not use default installer image config. 72 | sd-aarch64-installer | create an installer sd card for aarch64. For cross compiling use `--system aarch64-linux` and read the cross-compile section. 73 | sd-x86_64 | sd card image for x86_64 systems 74 | vagrant-virtualbox | VirtualBox image for [Vagrant](https://www.vagrantup.com/) 75 | virtualbox | virtualbox VM 76 | vm | only used as a qemu-kvm runner 77 | vm-bootloader | same as vm, but uses a real bootloader instead of netbooting 78 | vm-nogui | same as vm, but without a GUI 79 | vmware | VMWare image (VMDK) 80 | 81 | ## Usage 82 | 83 | Run `nixos-generate --help` for detailed usage information. 84 | 85 | ## select a specific nixpkgs channel 86 | 87 | Adds ability to select a specific channel version. 88 | 89 | Example: 90 | ``` 91 | nix-shell --command './nixos-generate -f iso -I nixpkgs=channel:nixos-19.09' 92 | ``` 93 | 94 | ## Using a particular nixpkgs 95 | 96 | To use features found in a different nixpkgs (for instance the Digital Ocean 97 | image was recently merged in nixpkgs): 98 | 99 | ``` 100 | NIX_PATH=nixpkgs=../nixpkgs nixos-generate -f do 101 | ``` 102 | 103 | ## Setting the disk image size 104 | 105 | To specify the size of the generated disk image, use the `--disk-size` argument, 106 | specifying the size in megabytes. This is currently supported by the following 107 | formats. If this argument is unspecified it defaults to automatic sizing based 108 | on the generated NixOS build. 109 | 110 | - hyperv 111 | - proxmox 112 | - qcow 113 | - raw-efi 114 | - raw 115 | - vm 116 | - vm-nogui 117 | - vmware 118 | 119 | Example (20GB disk): 120 | 121 | ```bash 122 | nixos-generate -c -f --disk-size 20480 123 | ``` 124 | 125 | To set the disk size in `flake.nix`, set the `virtualisation.diskSize` module option. 126 | 127 | ```nix 128 | { 129 | inputs = { 130 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; 131 | nixos-generators = { 132 | url = "github:nix-community/nixos-generators"; 133 | inputs.nixpkgs.follows = "nixpkgs"; 134 | }; 135 | xc = { 136 | url = "github:joerdav/xc"; 137 | inputs.nixpkgs.follows = "nixpkgs"; 138 | }; 139 | }; 140 | 141 | outputs = { nixpkgs, nixos-generators, xc, ... }: 142 | let 143 | pkgsForSystem = system: import nixpkgs { 144 | inherit system; 145 | overlays = [ 146 | (final: prev: { xc = xc.packages.${system}.xc; }) 147 | ]; 148 | }; 149 | allVMs = [ "x86_64-linux" "aarch64-linux" ]; 150 | forAllVMs = f: nixpkgs.lib.genAttrs allVMs (system: f { 151 | inherit system; 152 | pkgs = pkgsForSystem system; 153 | }); 154 | in 155 | { 156 | packages = forAllVMs ({ system, pkgs }: { 157 | vm = nixos-generators.nixosGenerate { 158 | system = system; 159 | specialArgs = { 160 | pkgs = pkgs; 161 | }; 162 | modules = [ 163 | { 164 | # Pin nixpkgs to the flake input, so that the packages installed 165 | # come from the flake inputs.nixpkgs.url. 166 | nix.registry.nixpkgs.flake = nixpkgs; 167 | # set disk size to to 20G 168 | virtualisation.diskSize = 20 * 1024; 169 | } 170 | # Apply the rest of the config. 171 | ./configuration.nix 172 | ]; 173 | format = "raw"; 174 | }; 175 | }); 176 | }; 177 | } 178 | ``` 179 | 180 | ## Cross Compiling 181 | 182 | To cross compile nixos images for other architectures you have to configure 183 | `boot.binfmt.emulatedSystems` or `boot.binfmt.registrations` on your host system. 184 | 185 | In your system `configuration.nix`: 186 | 187 | ```nix 188 | { 189 | # Enable binfmt emulation of aarch64-linux. 190 | boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; 191 | } 192 | ``` 193 | 194 | Alternatively, if you want to target other architectures: 195 | 196 | ```nix 197 | # Define qemu-arm-static source. 198 | let qemu-arm-static = pkgs.stdenv.mkDerivation { 199 | name = "qemu-arm-static"; 200 | src = builtins.fetchurl { 201 | url = "https://github.com/multiarch/qemu-user-static/releases/download/v6.1.0-8/qemu-arm-static"; 202 | sha256 = "06344d77d4f08b3e1b26ff440cb115179c63ca8047afb978602d7922a51231e3"; 203 | }; 204 | dontUnpack = true; 205 | installPhase = "install -D -m 0755 $src $out/bin/qemu-arm-static"; 206 | }; 207 | in { 208 | # Enable binfmt emulation of extra binary formats (armv7l-linux, for exmaple). 209 | boot.binfmt.registrations.arm = { 210 | interpreter = "${qemu-arm-static}/bin/qemu-arm-static"; 211 | magicOrExtension = ''\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00''; 212 | mask = ''\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\x00\xff\xfe\xff\xff\xff''; 213 | }; 214 | 215 | # Define additional settings for nix. 216 | nix.extraOptions = '' 217 | extra-platforms = armv7l-linux 218 | ''; 219 | nix.sandboxPaths = [ "/run/binfmt/arm=${qemu-arm-static}/bin/qemu-arm-static" ]; 220 | } 221 | ``` 222 | 223 | For more details on configuring `binfmt`, have a look at: 224 | [binfmt options](https://search.nixos.org/options?channel=unstable&query=boot.binfmt), 225 | [binfmt.nix](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/system/boot/binfmt.nix), 226 | [this comment](https://github.com/NixOS/nixpkgs/issues/109661#issuecomment-762629438) and 227 | [clevers qemu-user](https://github.com/cleverca22/nixos-configs/blob/master/qemu.nix). 228 | 229 | Once you've run `nixos-rebuild` with these options, 230 | you can use the `--system` option to create images for other architectures. 231 | 232 | ## Using as a nixos-module 233 | 234 | `nixos-generators` can be included as a `NixOS module` into your existing `configuration.nix` making all available formats available through `config.formats` and configurable through `config.formatConfigs`. New formats can be defined by adding a new entry like `config.formatConfigs.my-new-format = {config, ...}: {}`. 235 | 236 | An example `flake.nix` demonstrating this approach is below. 237 | 238 | Images can be built from that flake by running: 239 | 240 | - `nix build .#nixosConfigurations.my-machine.config.formats.vmware` or 241 | - `nix build .#nixosConfigurations.my-machine.config.formats.my-custom-format` or 242 | - `nix build .#nixosConfigurations.my-machine.config.formats.` 243 | 244 | ```nix 245 | { 246 | inputs = { 247 | nixpkgs.url = "nixpkgs/nixos-unstable"; 248 | nixos-generators = { 249 | url = "github:nix-community/nixos-generators"; 250 | inputs.nixpkgs.follows = "nixpkgs"; 251 | }; 252 | }; 253 | outputs = { self, nixpkgs, nixos-generators, ... }: { 254 | 255 | # A single nixos config outputting multiple formats. 256 | # Alternatively put this in a configuration.nix. 257 | nixosModules.myFormats = { config, ... }: { 258 | imports = [ 259 | nixos-generators.nixosModules.all-formats 260 | ]; 261 | 262 | nixpkgs.hostPlatform = "x86_64-linux"; 263 | 264 | # customize an existing format 265 | formatConfigs.vmware = { config, ... }: { 266 | services.openssh.enable = true; 267 | }; 268 | 269 | # define a new format 270 | formatConfigs.my-custom-format = { config, modulesPath, ... }: { 271 | imports = [ "${toString modulesPath}/installer/cd-dvd/installation-cd-base.nix" ]; 272 | formatAttr = "isoImage"; 273 | fileExtension = ".iso"; 274 | networking.wireless.networks = { 275 | # ... 276 | }; 277 | }; 278 | }; 279 | 280 | # a machine consuming the module 281 | nixosConfigurations.my-machine = nixpkgs.lib.nixosSystem { 282 | modules = [ self.nixosModules.myFormats ]; 283 | }; 284 | }; 285 | } 286 | ``` 287 | 288 | ## Using in a Flake 289 | 290 | `nixos-generators` can be included as a `Flake` input and provides 291 | a `nixosGenerate` function for building images as `Flake` outputs. This 292 | approach pins all dependencies and allows for conveniently defining multiple 293 | output types based on one config. 294 | 295 | An example `flake.nix` demonstrating this approach is below. `vmware` or 296 | `virtualbox` images can be built from the same `configuration.nix` by running 297 | `nix build .#vmware` or `nix build .#virtualbox` 298 | 299 | Custom formats can be defined by building a format module (see the 300 | [formats](./formats) directory for examples) and passing it to `nixosGenerate` 301 | via an the `customFormats` argument. `customFormats` should be in the form of 302 | an attribute sets of the form ` = ` and can define 303 | multiple custom formats. `nixosGenerate` will then match against these custom formats as well as the built in ones. 304 | 305 | ```nix 306 | { 307 | inputs = { 308 | nixpkgs.url = "nixpkgs/nixos-unstable"; 309 | nixos-generators = { 310 | url = "github:nix-community/nixos-generators"; 311 | inputs.nixpkgs.follows = "nixpkgs"; 312 | }; 313 | }; 314 | outputs = { self, nixpkgs, nixos-generators, ... }: { 315 | packages.x86_64-linux = { 316 | vmware = nixos-generators.nixosGenerate { 317 | system = "x86_64-linux"; 318 | modules = [ 319 | # you can include your own nixos configuration here, i.e. 320 | # ./configuration.nix 321 | ]; 322 | format = "vmware"; 323 | 324 | # optional arguments: 325 | # explicit nixpkgs and lib: 326 | # pkgs = nixpkgs.legacyPackages.x86_64-linux; 327 | # lib = nixpkgs.legacyPackages.x86_64-linux.lib; 328 | # additional arguments to pass to modules: 329 | # specialArgs = { myExtraArg = "foobar"; }; 330 | 331 | # you can also define your own custom formats 332 | # customFormats = { "myFormat" = ; ... }; 333 | # format = "myFormat"; 334 | }; 335 | vbox = nixos-generators.nixosGenerate { 336 | system = "x86_64-linux"; 337 | format = "virtualbox"; 338 | }; 339 | }; 340 | }; 341 | } 342 | ``` 343 | 344 | ## Format-specific notes 345 | 346 | ### `raw` and `raw-efi` 347 | 348 | `raw` and `raw-efi` images can be used on physical hardware, but benefit from some tweaks. 349 | * These images are configured to log to the serial console, and not to your display. One workaround for this is to add `boot.kernelParams = [ "console=tty0" ];` to your configuration, which will override the image's default `console=ttyS0`. 350 | * By default, grub will timeout after 1 second. To extend this, set `boot.loader.timeout = 5;` (or longer) 351 | * If boot fails for some reason, you will not get a recovery shell unless the root user is enabled, which you can do by setting a password for them (`users.users.root.password = "something";`, possibly `users.mutableUsers = true;` so you can interactively change the passwords after boot) 352 | * After booting, if you intend to use `nixos-switch`, consider using `nixos-generate-config`. 353 | 354 | ### License 355 | 356 | This project is licensed under the [MIT License](LICENSE). 357 | 358 | # FAQ 359 | 360 | #### No space left on device 361 | 362 | This means either /tmp, /run/user/$UID or your TMPFS runs full. Sometimes setting TMPDIR to some other location can help, sometimes /tmp needs to be on a bigger partition (not a tmpfs). 363 | --------------------------------------------------------------------------------