You’ll hate it until you love it. Welcome to the abyss.

https://nlewo.github.io/nixos-manual-sphinx/index.html

Important

We are now using deterministic-nix which has additional, yet unexplored functionality

Useful Snippets#

Remote Building for Darwin Hosts#

Darwin hosts tagged builder in hosts/default.nix are automatically added to each host’s nix.buildMachines. Linux hosts can offload Darwin derivations to them without any extra flags.

To test or force a build through a specific Darwin remote builder:

nix build .#darwinConfigurations.work-laptop.config.system.build.toplevel \
  --builders "ssh://builder@work-laptop.armadillo-banfish.ts.net aarch64-darwin /run/secrets/nix/builder/priv-key 4 1 big-parallel"

Format: ssh://builder@<host>.<tailnet> <system> <key-path> <maxJobs> <speedFactor> <features>

Note

Do not use --store ssh-ng://... — that redirects the local store, which is a different operation. Do not use --max-jobs 0 — that forces all derivations (including Linux ones) through the remote, which fails for cross-arch.

Copying NixOS Configurations#

Using Nix copy

nix copy --to ssh://user@host:port/path/to/store .#system-octopi
# or
nix copy --to ssh://host ./result

An SD Image for Raspberry Pi#

Note: Needs the moduleClosue overlay and "${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix" to work

nom build .#nixosConfigurations.octopi.config.system.build.sdImage
sudo dd if=result/sd-image/nixos-sd-image-*-aarch64-linux.img of=/dev/sdh bs=4096 conv=fsync status=progress

Debugging#

Repl#

nix repl is your friend.

  1. enter repl
  2. :lf . - Loads the flake into the context. Needs redone after file changes.
  3. :te - Enables trace outputs (toggles)
  4. :p config.some... - Prints the evaluated value to screen or errors
  5. :.<tab> - Search through what is available to look at

Debugging and Analysis Commands#

For deeper analysis of your configuration:

# Show detailed derivation information
nix show-derivation .#nixosConfigurations.octopi.config.system.build.toplevel

# Get closure information
nix path-info --recursive .#nixosConfigurations.octopi.config.system.build.toplevel

# Analyze what will be built
nix build --dry-run .#nixosConfigurations.octopi.config.system.build.toplevel

Using nix eval for Different Outputs#

For various system components, you can use nix eval:

# Get the toplevel system path
nix eval --raw .#nixosConfigurations.octopi.config.system.build.toplevel

# Get networking information
nix eval --json .#nixosConfigurations.octopi.config.system.networking | jq 

# Get just the derivation store path
nix eval --raw .#nixosConfigurations.octopi.config.system.build.toplevel.drvPath

Pipe Operator#

# before
let digital_ocean_loadbalancer_regions = lib.lists.unique (lib.map (value: value.region) (builtins.attrValues (lib.filterAttrs (name: value: value.loadbalancer.enable) digital_ocean_clouds)));
# after
let digital_ocean_loadbalancer_regions = digital_ocean_clouds |> lib.filterAttrs (name: value: value.loadbalancer.enable) |> lib.mapAttrs (name: value: value.region) |> builtins.attrValues |> lib.lists.unique

# before
let
    # I hate this but I can't think of a better way to do this
    list_of_clouds = lib.map
        ({name, value}: {name = name; replicas = value.replicas; region = value.region; talos_image_version = value.talos_image_version;})
        (lib.attrsToList digital_ocean_clouds);
    f = {name, replicas, region, talos_image_version}:
        lib.map (replica: {name = name; replica = replica; region = region; talos_image_version = talos_image_version;})
        replicas;
    x = lib.lists.concatMap f list_of_clouds;

in lib.map createResource x;

# after
digital_ocean_clouds
|> lib.attrsToList
|> lib.map ({name, value}:
    { inherit name; inherit (value) replicas region talos_image_version; }
)
|> lib.map (x:
    x.replicas
    |> lib.map (replica: { inherit (x) name region talos_image_version; inherit replica; })
)
|> lib.concatLists
|> lib.map createDroplet;