Skip to content

Commit

Permalink
Add nixos-generators devshell module
Browse files Browse the repository at this point in the history
that injects our custom formats (at present, limited to `bootstrap-iso`)
into the nixos-generators format search path.

Additionally, introduce the `bootstrap-iso` command that wraps
`nixos-generate --format bootstrap-iso`.

fix: divnix#450
  • Loading branch information
tomeon committed Apr 15, 2022
1 parent e2bb8ea commit 5c202b4
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 88 deletions.
9 changes: 6 additions & 3 deletions doc/start/iso.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# ISO

Making and writing an installable iso for `hosts/bootstrap.nix` is as simple as:
Making and writing an installable iso for a host is as simple as
entering the devshell and running `boostrap-iso burn <host>`. For instance, to
burn an iso for the host defined in `hosts/bootstrap.nix`, run:

```sh
bud build bootstrap bootstrapIso
sudo -E $(which bud) burn
nix develop
bootstrap-iso burn bootstrap # note: uses sudo
```

This works for any host.
Expand Down
3 changes: 2 additions & 1 deletion examples/devos/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
nixos.url = "github:nixos/nixpkgs/nixos-21.11";
latest.url = "github:nixos/nixpkgs/nixos-unstable";

digga.url = "github:divnix/digga";
#digga.url = "github:divnix/digga";
digga.url = "path:/home/matt/git/packaging/nix/digga";
digga.inputs.nixpkgs.follows = "nixos";
digga.inputs.nixlib.follows = "nixos";
digga.inputs.home-manager.follows = "home";
Expand Down
14 changes: 12 additions & 2 deletions examples/devos/hosts/bootstrap.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
{ profiles, ... }:
{
# build with: `bud build bootstrap bootstrapIso`
# build (from within a devshell) with:
#
# nixos-generate --format bootstrap-iso --flake '.#bootstrap'
#
# or:
#
# bootstrap-iso build bootstrap
#
# which does the same thing.
#
# reachable on the local link via ssh root@fe80::47%eno1
# where 'eno1' is replaced by your own machine's network
# interface that has the local link to the target machine
Expand All @@ -13,6 +22,7 @@

boot.loader.systemd-boot.enable = true;

# will be overridden by the bootstrapIso instrumentation
# will be overridden by the bootstrap-iso `nixos-generate` format profile
# defined by the digga "nixos-generators" devshell module
fileSystems."/" = { device = "/dev/disk/by-label/nixos"; };
}
1 change: 1 addition & 0 deletions examples/devos/shell/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
modules = with inputs; [
bud.devshellModules.bud
digga.devshellModules.nixos-generators
];
exportedModules = [
./devos.nix
Expand Down
12 changes: 9 additions & 3 deletions examples/devos/shell/devos.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,14 @@ in
++ lib.optional
(system != "i686-linux")
(devos cachix)
++ lib.optional
(system != "aarch64-darwin")
(devos inputs.nixos-generators.defaultPackage.${pkgs.system})
;

# digga-supplied extensions to nixos-generators. Provides the
# "bootstrap-iso" nixos-generators format, plus the "bootstrap-iso" wrapper
# command.
digga.nixos-generators = {
enable = pkgs.system != "aarch64-darwin";
category = "devos";
package = inputs.nixos-generators.defaultPackage.${pkgs.system};
};
}
3 changes: 2 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@

# a little extra service ...
overlays = import ./overlays { inherit inputs; };
nixosModules = import ./modules;
nixosModules = import ./modules/nixos;
devshellModules = import ./modules/devShell;

defaultTemplate = self.templates.devos;
templates.devos.path = ./examples/devos;
Expand Down
74 changes: 0 additions & 74 deletions modules/bootstrap-iso.nix

This file was deleted.

4 changes: 0 additions & 4 deletions modules/default.nix

This file was deleted.

3 changes: 3 additions & 0 deletions modules/devShell/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
nixos-generators = import ./nixos-generators;
}
64 changes: 64 additions & 0 deletions modules/devShell/nixos-generators/bootstrap-iso
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/sh

set -eu

if [ -z "${PRJ_ROOT:-}" ]; then
if ! PRJ_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"; then
# shellcheck disable=SC2016
printf 1>&2 -- '%s: %s. %s. %s.\n' \
"${0##*/}" 'unable to locate your project root ($PRJ_ROOT)' \
'bud relies on the project root for locating the bootstrap ISO' \
'Aborting'

exit 1
fi
fi

boostrapIsoRequireHost() {
if [ "$#" -lt 1 ]; then
printf 1>&2 -- 'Error: missing required <host> argument.\n' "${0##*/}"
bootstrapIsoHelp 1
fi
}

bootstrapIsoBuild() {
boostrapIsoRequireHost "$@" || return

local host="$1"
shift

# XXX the way nixos-generate handles flake specifications requires that we do
# not quote the host as we would with, e.g.:
# nix build ".#nixosConfigurations.\"my.host.name\".config.system.build.toplevel"
nixos-generate "$@" --format bootstrap-iso --flake "${PRJ_ROOT}#${host}"
}

bootstrapIsoBurn() {
boostrapIsoRequireHost "$@" || return
bud="$(command -v bud)" || return
bootstrapIsoBuild "$@" --out-link "${PRJ_ROOT?}/result" || return
sudo -E "$bud" burn
}

bootstrapIsoHelp() {
printf 1>&2 -- 'Usage: %s {build,burn,help} <host> [<nixos-generate-arg> ...]\n' "${0##*/}"
return "${1:-0}"
}

cmd="${1:-}"
shift 2>/dev/null || :

case "$cmd" in
build)
bootstrapIsoBuild "$@"
;;
burn)
bootstrapIsoBurn "$@"
;;
help)
bootstrapIsoHelp
;;
*)
bootstrapIsoHelp 1
;;
esac
53 changes: 53 additions & 0 deletions modules/devShell/nixos-generators/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{ config, lib, pkgs, ... }:

let
cfg = config.digga.nixos-generators;

searchPathVar = "NIXOS_GENERATORS_FORMAT_SEARCH_PATH";

bootstrap-iso = {
category = "devos";
name = "bootstrap-iso";
help = "Create and burn a bootstrap ISO for the specified NixOS configuration";
command = builtins.readFile ./bootstrap-iso;
};
in
{
options.digga.nixos-generators =
let
inherit (lib) mkOption mkEnableOption types;
in
{
enable = mkEnableOption "nixos-generators extensions";

category = mkOption {
type = types.str;
default = "generators";
description = "category for the nixos-generate and bootstrap-iso commands";
};

package = mkOption {
type = types.package;
default = pkgs.nixos-generators;
description = "package providing nixos-generators";
};
};

config = lib.mkIf cfg.enable {
commands = [
{ inherit (cfg) category package; }
bootstrap-iso
];

env = [
{
name = searchPathVar;

# prepend our formats directory to the nixos-generate search path
eval = ''
''${${searchPathVar}:+''${${searchPathVar}}:}${toString ./formats}
'';
}
];
};
}
68 changes: 68 additions & 0 deletions modules/devShell/nixos-generators/formats/bootstrap-iso.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
let
getFqdn = config:
let
net = config.networking;
fqdn =
if net.domain != null
then "${net.hostName}.${net.domain}"
else net.hostName;
in
fqdn;
in

{ config, lib, modulesPath, suites, self, inputs, ... }@args: {

imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ];

isoImage.isoBaseName = "bootstrap-" + (getFqdn config);
isoImage.contents = [{
source = self;
target = "/devos/";
}];
isoImage.storeContents = [
self.devShell.${config.nixpkgs.system}
# include also closures that are "switched off" by the
# above profile filter on the local config attribute
config.system.build.toplevel
] ++ builtins.attrValues inputs;

# confilcts with networking.wireless which might be slightly
# more useful on a stick
networking.networkmanager.enable = lib.mkForce false;
# confilcts with networking.wireless
networking.wireless.iwd.enable = lib.mkForce false;

# Set up a link-local boostrap network
# See also: https://github.com/NixOS/nixpkgs/issues/75515#issuecomment-571661659
networking.usePredictableInterfaceNames = lib.mkForce true; # so prefix matching works
networking.useNetworkd = lib.mkForce true;
networking.useDHCP = lib.mkForce false;
networking.dhcpcd.enable = lib.mkForce false;
systemd.network = {
# https://www.freedesktop.org/software/systemd/man/systemd.network.html
networks."boostrap-link-local" = {
matchConfig = {
Name = "en* wl* ww*";
};
networkConfig = {
Description = "Link-local host bootstrap network";
MulticastDNS = true;
LinkLocalAddressing = "ipv6";
DHCP = "yes";
};
address = [
# fall back well-known link-local for situations where MulticastDNS is not available
"fe80::47" # 47: n=14 i=9 x=24; n+i+x
];
extraConfig = ''
# Unique, yet stable. Based off the MAC address.
IPv6LinkLocalAddressGenerationMode = "eui64"
'';
};
};

# Required by nixos-generate
formatAttr = "isoImage";
filename = "*.iso";
}

3 changes: 3 additions & 0 deletions modules/nixos/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
nixConfig = import ./nix-config.nix;
}
File renamed without changes.

0 comments on commit 5c202b4

Please sign in to comment.