Skip to content

add netboot-installer-nixos-unstable #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

inputs.nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable-small";
inputs.nixos-2211.url = "github:NixOS/nixpkgs/release-22.11";
inputs.disko.url = "github:nix-community/disko";

nixConfig.extra-substituters = [
"https://cache.garnix.io"
Expand All @@ -11,13 +12,14 @@
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
];

outputs = { self, nixos-unstable, nixos-2211 }: let
outputs = { self, nixos-unstable, nixos-2211, disko }: let
supportedSystems = [ "aarch64-linux" "x86_64-linux" ];
forAllSystems = nixos-unstable.lib.genAttrs supportedSystems;
in {
packages = forAllSystems (system: let
netboot = nixpkgs: (import (nixpkgs + "/nixos/release.nix") {}).netboot.${system};
kexec-installer = nixpkgs: modules: (nixpkgs.legacyPackages.${system}.nixos (modules ++ [self.nixosModules.kexec-installer])).config.system.build.kexecTarball;
netboot-installer = nixpkgs: (nixpkgs.legacyPackages.${system}.nixos [self.nixosModules.netboot-installer]).config.system.build.netboot;
in {
netboot-nixos-unstable = netboot nixos-unstable;
netboot-nixos-2211 = netboot nixos-2211;
Expand All @@ -32,10 +34,15 @@
{ system.kexec-installer.name = "nixos-kexec-installer-noninteractive"; }
self.nixosModules.noninteractive
];

netboot-installer-nixos-unstable = netboot-installer nixos-unstable;
netboot-installer-nixos-2211 = netboot-installer nixos-2211;
});
nixosModules = {
kexec-installer = ./nix/kexec-installer/module.nix;
noninteractive = ./nix/noninteractive.nix;
# TODO: also add a test here once we have https://github.com/NixOS/nixpkgs/pull/228346 merged
netboot-installer = ./nix/netboot-installer/module.nix;
};
checks.x86_64-linux = let
pkgs = nixos-unstable.legacyPackages.x86_64-linux;
Expand Down
56 changes: 56 additions & 0 deletions nix/installer.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{ config, lib, pkgs, ... }: {
# We are stateless, so just default to latest.
system.stateVersion = config.system.nixos.version;

# use latest kernel we can support to get more hardware support
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;

# IPMI SOL console redirection stuff
boot.kernelParams =
[ "console=tty0" ] ++
(lib.optional (pkgs.stdenv.hostPlatform.isAarch32 || pkgs.stdenv.hostPlatform.isAarch64) "console=ttyAMA0,115200") ++
(lib.optional (pkgs.stdenv.hostPlatform.isRiscV) "console=ttySIF0,115200") ++
[ "console=ttyS0,115200" ];

documentation.enable = false;
# Not really needed. Saves a few bytes and the only service we are running is sshd, which we want to be reachable.
networking.firewall.enable = false;

systemd.network.enable = true;
networking.dhcpcd.enable = false;

# for zapping of disko
environment.systemPackages = [ pkgs.jq ];

systemd.services.log-network-status = {
wantedBy = [ "multi-user.target" ];
# No point in restarting this. We just need this after boot
restartIfChanged = false;

serviceConfig = {
Type = "oneshot";
StandardOutput = "journal+console";
ExecStart = [
# Allow failures, so it still prints what interfaces we have even if we
# not get online
"-${pkgs.systemd}/lib/systemd/systemd-networkd-wait-online"
"${pkgs.iproute2}/bin/ip -c addr"
"${pkgs.iproute2}/bin/ip -c -6 route"
"${pkgs.iproute2}/bin/ip -c -4 route"
];
};
};

# Restore ssh host and user keys if they are available.
# This avoids warnings of unknown ssh keys.
boot.initrd.postMountCommands = ''
mkdir -m 700 -p /mnt-root/root/.ssh
mkdir -m 755 -p /mnt-root/etc/ssh
mkdir -m 755 -p /mnt-root/root/network
if [[ -f ssh/authorized_keys ]]; then
install -m 400 ssh/authorized_keys /mnt-root/root/.ssh
fi
install -m 400 ssh/ssh_host_* /mnt-root/etc/ssh
cp *.json /mnt-root/root/network/
'';
}
70 changes: 7 additions & 63 deletions nix/kexec-installer/module.nix
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
{ config, lib, modulesPath, pkgs, ... }:
let
restore-network = pkgs.writers.writePython3 "restore-network" {
flakeIgnore = ["E501"];
} ./restore_routes.py;
restore-network = pkgs.writers.writePython3 "restore-network" { flakeIgnore = [ "E501" ]; }
./restore_routes.py;

# does not link with iptables enabled
iprouteStatic = pkgs.pkgsStatic.iproute2.override { iptables = null; };
in {
in
{
imports = [
(modulesPath + "/installer/netboot/netboot-minimal.nix")
../installer.nix
];
options = {
system.kexec-installer.name = lib.mkOption {
Expand All @@ -21,15 +22,9 @@ in {
};

config = {
# We are stateless, so just default to latest.
system.stateVersion = config.system.nixos.version;

# use latest kernel we can support to get more hardware support
boot.kernelPackages = config.boot.zfs.package.latestCompatibleLinuxPackages;

# This is a variant of the upstream kexecScript that also allows embedding
# a ssh key.
system.build.kexecRun = pkgs.runCommand "kexec-run" {} ''
system.build.kexecRun = pkgs.runCommand "kexec-run" { } ''
install -D -m 0755 ${./kexec-run.sh} $out

sed -i \
Expand All @@ -40,7 +35,7 @@ in {
${pkgs.shellcheck}/bin/shellcheck $out
'';

system.build.kexecTarball = pkgs.runCommand "kexec-tarball" {} ''
system.build.kexecTarball = pkgs.runCommand "kexec-tarball" { } ''
mkdir kexec $out
cp "${config.system.build.netbootRamdisk}/initrd" kexec/initrd
cp "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}" kexec/bzImage
Expand All @@ -54,28 +49,9 @@ in {
tar -czvf $out/${config.system.kexec-installer.name}-${pkgs.stdenv.hostPlatform.system}.tar.gz kexec
'';

# IPMI SOL console redirection stuff
boot.kernelParams =
[ "console=tty0" ] ++
(lib.optional (pkgs.stdenv.hostPlatform.isAarch32 || pkgs.stdenv.hostPlatform.isAarch64) "console=ttyAMA0,115200") ++
(lib.optional (pkgs.stdenv.hostPlatform.isRiscV) "console=ttySIF0,115200") ++
[ "console=ttyS0,115200" ];

documentation.enable = false;
# Not really needed. Saves a few bytes and the only service we are running is sshd, which we want to be reachable.
networking.firewall.enable = false;

systemd.network.enable = true;
networking.dhcpcd.enable = false;

# for detection if we are on kexec
environment.etc.is_kexec.text = "true";

# for zapping of disko
environment.systemPackages = [
pkgs.jq
];

systemd.services.restore-network = {
before = [ "network-pre.target" ];
wants = [ "network-pre.target" ];
Expand All @@ -95,37 +71,5 @@ in {
"/root/network/routes-v6.json"
];
};

systemd.services.log-network-status = {
wantedBy = [ "multi-user.target" ];
# No point in restarting this. We just need this after boot
restartIfChanged = false;

serviceConfig = {
Type = "oneshot";
StandardOutput = "journal+console";
ExecStart = [
# Allow failures, so it still prints what interfaces we have even if we
# not get online
"-${pkgs.systemd}/lib/systemd/systemd-networkd-wait-online"
"${pkgs.iproute2}/bin/ip -c addr"
"${pkgs.iproute2}/bin/ip -c -6 route"
"${pkgs.iproute2}/bin/ip -c -4 route"
];
};
};

# Restore ssh host and user keys if they are available.
# This avoids warnings of unknown ssh keys.
boot.initrd.postMountCommands = ''
mkdir -m 700 -p /mnt-root/root/.ssh
mkdir -m 755 -p /mnt-root/etc/ssh
mkdir -m 755 -p /mnt-root/root/network
if [[ -f ssh/authorized_keys ]]; then
install -m 400 ssh/authorized_keys /mnt-root/root/.ssh
fi
install -m 400 ssh/ssh_host_* /mnt-root/etc/ssh
cp *.json /mnt-root/root/network/
'';
};
}
Empty file.
55 changes: 55 additions & 0 deletions nix/netboot-installer/module.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{ config, lib, modulesPath, pkgs, ... }:
{
imports = [
(modulesPath + "/installer/netboot/netboot-minimal.nix")
../installer.nix
];

# We are stateless, so just default to latest.
system.stateVersion = config.system.nixos.version;

system.build.netboot = pkgs.symlinkJoin {
name = "netboot";
paths = with config.system.build; [
netbootRamdisk
kernel
(pkgs.runCommand "kernel-params" {} ''
mkdir -p $out
ln -s "${config.system.build.toplevel}/kernel-params" $out/kernel-params
ln -s "${config.system.build.toplevel}/init" $out/init
'')
];
preferLocalBuild = true;
};
systemd.network.networks."10-uplink" = {
matchConfig.Type = "ether";
networkConfig = {
DHCP = "yes";
LLMNR = "yes";
EmitLLDP = "yes";
IPv6AcceptRA = "no";
MulticastDNS = "yes";
LinkLocalAddressing = "yes";
LLDP = "yes";
};

dhcpV4Config = {
UseHostname = false;
ClientIdentifier = "mac";
};
};

networking.hostName = "";
# overrides normal activation script for setting hostname
system.activationScripts.hostname = lib.mkForce ''
# apply hostname from cmdline
for o in $(< /proc/cmdline); do
case $o in
hostname=*)
IFS== read -r -a hostParam <<< "$o"
;;
esac
done
hostname "''${hostParam[1]:-nixos}"
'';
}