Compare commits
3 commits
Author | SHA1 | Date | |
---|---|---|---|
|
65c6e9d432 | ||
|
7582b40ce3 | ||
|
2d72a425a2 |
21 changed files with 241 additions and 524 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: cachix/install-nix-action@v30
|
- uses: cachix/install-nix-action@V27
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixpkgs-unstable.tar.gz
|
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixpkgs-unstable.tar.gz
|
||||||
- name: Build image
|
- name: Build image
|
||||||
|
|
4
.github/workflows/update-flake-lock.yml
vendored
4
.github/workflows/update-flake-lock.yml
vendored
|
@ -11,9 +11,9 @@ jobs:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: cachix/install-nix-action@v30
|
uses: cachix/install-nix-action@V27
|
||||||
- name: Update flake.lock
|
- name: Update flake.lock
|
||||||
uses: DeterminateSystems/update-flake-lock@v24
|
uses: DeterminateSystems/update-flake-lock@v22
|
||||||
with:
|
with:
|
||||||
pr-labels: |
|
pr-labels: |
|
||||||
merge-queue
|
merge-queue
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
queue_rules:
|
queue_rules:
|
||||||
- name: default
|
- name: default
|
||||||
merge_conditions:
|
merge_conditions:
|
||||||
- check-success=buildbot/nix-build
|
- check-success=buildbot/nix-eval
|
||||||
defaults:
|
defaults:
|
||||||
actions:
|
actions:
|
||||||
queue:
|
queue:
|
||||||
|
|
10
README.md
10
README.md
|
@ -11,10 +11,10 @@ Kexec is a mechanism in Linux to load a new kernel from a running Linux to
|
||||||
replace the current kernel. This is useful for booting the Nixos installer from
|
replace the current kernel. This is useful for booting the Nixos installer from
|
||||||
existing Linux distributions, such as server provider that do not offer a NixOS
|
existing Linux distributions, such as server provider that do not offer a NixOS
|
||||||
option. After running kexec, the NixOS installer exists only in memory. At the
|
option. After running kexec, the NixOS installer exists only in memory. At the
|
||||||
time of writing, this requires secure boot off in BIOS settings and at least 1GB
|
time of writing, this requires at least 1GB of physical RAM (swap does not
|
||||||
of physical RAM (swap does not count) in the system. If not enough RAM is available,
|
count) in the system. If not enough RAM is available, the initrd cannot be
|
||||||
the initrd cannot be loaded. Because the NixOS runs only in RAM, users can reformat
|
loaded. Because the NixOS runs only in RAM, users can reformat all the system's
|
||||||
all the system's discs to prepare for a new NixOS installation.
|
discs to prepare for a new NixOS installation.
|
||||||
|
|
||||||
It can be booted as follows by running these commands as root:
|
It can be booted as follows by running these commands as root:
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ integration into automated nixos installation scripts, since you can cleanly
|
||||||
disconnect from the running machine before the kexec takes place. The tarball
|
disconnect from the running machine before the kexec takes place. The tarball
|
||||||
is also designed to be run from NixOS, which can be useful for new installations
|
is also designed to be run from NixOS, which can be useful for new installations
|
||||||
|
|
||||||
## Iso installer images
|
## ISO installer images
|
||||||
|
|
||||||
This image allows to boot a NixOS installer off a USB-Stick.
|
This image allows to boot a NixOS installer off a USB-Stick.
|
||||||
This installer has been optimized for remote installation i.e.
|
This installer has been optimized for remote installation i.e.
|
||||||
|
|
18
flake.lock
18
flake.lock
|
@ -2,11 +2,11 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixos-stable": {
|
"nixos-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1729181673,
|
"lastModified": 1719253556,
|
||||||
"narHash": "sha256-LDiPhQ3l+fBjRATNtnuDZsBS7hqoBtPkKBkhpoBHv3I=",
|
"narHash": "sha256-A/76RFUVxZ/7Y8+OMVL1Lc8LRhBxZ8ZE2bpMnvZ1VpY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "4eb33fe664af7b41a4c446f87d20c9a0a6321fa3",
|
"rev": "fc07dc3bdf2956ddd64f24612ea7fc894933eb2e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -18,16 +18,16 @@
|
||||||
},
|
},
|
||||||
"nixos-unstable": {
|
"nixos-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1729450260,
|
"lastModified": 1719456624,
|
||||||
"narHash": "sha256-3GNZr0V4b19RZ5mlyiY/4F8N2pzitvjDU6aHMWjAqLI=",
|
"narHash": "sha256-j0iox16+eMO2ptZ/IfM57R/1OpnPu0H03wXwggmLBfg=",
|
||||||
"owner": "NixOS",
|
"owner": "jmbaur",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e3f55158e7587c5a5fdb0e86eb7ca4f455f0928f",
|
"rev": "560cd874a37396968aea0bd9abc54fb1122424b7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "jmbaur",
|
||||||
"ref": "nixos-unstable-small",
|
"ref": "etc-overlay-cross",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
130
flake.nix
130
flake.nix
|
@ -1,53 +1,90 @@
|
||||||
{
|
{
|
||||||
description = "NixOS images";
|
description = "NixOS images";
|
||||||
|
|
||||||
inputs.nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable-small";
|
#inputs.nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable-small";
|
||||||
|
inputs.nixos-unstable.url = "github:jmbaur/nixpkgs/etc-overlay-cross";
|
||||||
inputs.nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.05";
|
inputs.nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||||
|
|
||||||
nixConfig.extra-substituters = [ "https://nix-community.cachix.org" ];
|
nixConfig.extra-substituters = [ "https://nix-community.cachix.org" ];
|
||||||
nixConfig.extra-trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ];
|
nixConfig.extra-trusted-public-keys = [
|
||||||
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
|
];
|
||||||
|
|
||||||
outputs = { self, nixos-unstable, nixos-stable }:
|
outputs =
|
||||||
let
|
|
||||||
supportedSystems = [ "riscv64-linux" ];
|
|
||||||
forAllSystems = nixos-unstable.lib.genAttrs supportedSystems;
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
hydraJobs = { inherit (self) checks; };
|
self,
|
||||||
packages = forAllSystems (system:
|
nixos-unstable,
|
||||||
|
nixos-stable,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
supportedSystems = [
|
||||||
|
"aarch64-linux"
|
||||||
|
"x86_64-linux"
|
||||||
|
];
|
||||||
|
forAllSystems = nixos-unstable.lib.genAttrs supportedSystems;
|
||||||
|
|
||||||
|
packages = forAllSystems (
|
||||||
|
system:
|
||||||
let
|
let
|
||||||
netboot = nixpkgs: (import (nixpkgs + "/nixos/release.nix") { }).netboot.${system};
|
netboot = nixpkgs: (import (nixpkgs + "/nixos/release.nix") { }).netboot.${system};
|
||||||
kexec-installer = nixpkgs: module: (nixpkgs.legacyPackages.${system}.nixos [ module self.nixosModules.kexec-installer ]).config.system.build.kexecTarball;
|
kexec-installer =
|
||||||
netboot-installer = nixpkgs: (nixpkgs.legacyPackages.${system}.nixos [ self.nixosModules.netboot-installer ]).config.system.build.netboot;
|
nixpkgs: modules:
|
||||||
image-installer = nixpkgs: (nixpkgs.legacyPackages.${system}.nixos [ self.nixosModules.image-installer ]).config.system.build.isoImage;
|
(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;
|
||||||
|
image-installer =
|
||||||
|
nixpkgs:
|
||||||
|
(nixpkgs.legacyPackages.${system}.nixos [ self.nixosModules.image-installer ])
|
||||||
|
.config.system.build.isoImage;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
netboot-nixos-unstable = netboot nixos-unstable;
|
netboot-nixos-unstable = netboot nixos-unstable;
|
||||||
netboot-nixos-stable = netboot nixos-stable;
|
netboot-nixos-stable = netboot nixos-stable;
|
||||||
kexec-installer-nixos-unstable = kexec-installer nixos-unstable {};
|
kexec-installer-nixos-unstable = kexec-installer nixos-unstable [ ];
|
||||||
kexec-installer-nixos-stable = kexec-installer nixos-stable {};
|
kexec-installer-nixos-stable = kexec-installer nixos-stable [ ];
|
||||||
|
|
||||||
image-installer-nixos-unstable = image-installer nixos-unstable;
|
image-installer-nixos-unstable = image-installer nixos-unstable;
|
||||||
image-installer-nixos-stable = image-installer nixos-stable;
|
image-installer-nixos-stable = image-installer nixos-stable;
|
||||||
|
|
||||||
kexec-installer-nixos-unstable-noninteractive = kexec-installer nixos-unstable {
|
kexec-installer-nixos-unstable-noninteractive = kexec-installer nixos-unstable [
|
||||||
_file = __curPos.file;
|
{ system.kexec-installer.name = "nixos-kexec-installer-noninteractive"; }
|
||||||
system.kexec-installer.name = "nixos-kexec-installer-noninteractive";
|
self.nixosModules.noninteractive
|
||||||
imports = [
|
];
|
||||||
self.nixosModules.noninteractive
|
kexec-installer-nixos-stable-noninteractive = kexec-installer nixos-stable [
|
||||||
];
|
{ system.kexec-installer.name = "nixos-kexec-installer-noninteractive"; }
|
||||||
};
|
self.nixosModules.noninteractive
|
||||||
kexec-installer-nixos-stable-noninteractive = kexec-installer nixos-stable {
|
];
|
||||||
_file = __curPos.file;
|
|
||||||
system.kexec-installer.name = "nixos-kexec-installer-noninteractive";
|
|
||||||
imports = [
|
|
||||||
self.nixosModules.noninteractive
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
netboot-installer-nixos-unstable = netboot-installer nixos-unstable;
|
netboot-installer-nixos-unstable = netboot-installer nixos-unstable;
|
||||||
netboot-installer-nixos-stable = netboot-installer nixos-stable;
|
netboot-installer-nixos-stable = netboot-installer nixos-stable;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
crossPackages = {
|
||||||
|
x86_64-linux =
|
||||||
|
let
|
||||||
|
kexec-installer =
|
||||||
|
nixpkgs: modules:
|
||||||
|
(nixpkgs.legacyPackages.x86_64-linux.pkgsCross.riscv64.nixos (
|
||||||
|
modules
|
||||||
|
++ [
|
||||||
|
self.nixosModules.kexec-installer
|
||||||
|
self.nixosModules.noninteractive
|
||||||
|
]
|
||||||
|
)).config.system.build.kexecTarball;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
kexec-installer-nixos-unstable-noninteractive-riscv64 = kexec-installer nixos-unstable [ ];
|
||||||
|
# needs a backport to nixpkgs-24.05
|
||||||
|
#kexec-installer-nixos-stable-noninteractive-riscv64 = kexec-installer nixos-stable [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = nixos-unstable.lib.recursiveUpdate packages crossPackages;
|
||||||
nixosModules = {
|
nixosModules = {
|
||||||
kexec-installer = ./nix/kexec-installer/module.nix;
|
kexec-installer = ./nix/kexec-installer/module.nix;
|
||||||
noninteractive = ./nix/noninteractive.nix;
|
noninteractive = ./nix/noninteractive.nix;
|
||||||
|
@ -58,28 +95,29 @@
|
||||||
checks =
|
checks =
|
||||||
let
|
let
|
||||||
# re-export the packages as checks
|
# re-export the packages as checks
|
||||||
packages = forAllSystems (system: nixos-unstable.lib.mapAttrs' (n: nixos-unstable.lib.nameValuePair "package-${n}") self.packages.${system});
|
packages = forAllSystems (
|
||||||
|
system:
|
||||||
|
nixos-unstable.lib.mapAttrs' (
|
||||||
|
n: nixos-unstable.lib.nameValuePair "package-${n}"
|
||||||
|
) self.packages.${system}
|
||||||
|
);
|
||||||
checks =
|
checks =
|
||||||
let
|
let
|
||||||
pkgsUnstable = nixos-unstable.legacyPackages.riscv64-linux;
|
pkgs = nixos-unstable.legacyPackages.x86_64-linux;
|
||||||
pkgsStable = nixos-stable.legacyPackages.riscv64-linux;
|
|
||||||
|
|
||||||
bootTests = pkgs: channel: suffix: pkgs.lib.mapAttrs' (name: pkgs.lib.nameValuePair "${name}${suffix}") (pkgs.callPackages ./nix/image-installer/tests.nix {
|
|
||||||
nixpkgs = channel;
|
|
||||||
nixosModules = self.nixosModules;
|
|
||||||
});
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
kexec-installer-unstable = pkgsUnstable.callPackage ./nix/kexec-installer/test.nix {
|
kexec-installer-unstable = pkgs.callPackage ./nix/kexec-installer/test.nix {
|
||||||
kexecTarball = self.packages.riscv64-linux.kexec-installer-nixos-unstable-noninteractive;
|
kexecTarball = self.packages.x86_64-linux.kexec-installer-nixos-unstable-noninteractive;
|
||||||
};
|
};
|
||||||
|
shellcheck = pkgs.runCommand "shellcheck" { nativeBuildInputs = [ pkgs.shellcheck ]; } ''
|
||||||
kexec-installer-stable = nixos-stable.legacyPackages.riscv64-linux.callPackage ./nix/kexec-installer/test.nix {
|
shellcheck ${(pkgs.nixos [ self.nixosModules.kexec-installer ]).config.system.build.kexecRun}
|
||||||
kexecTarball = self.packages.riscv64-linux.kexec-installer-nixos-stable-noninteractive;
|
touch $out
|
||||||
};
|
'';
|
||||||
} // (bootTests pkgsUnstable nixos-unstable "-nixos-unstable")
|
kexec-installer-stable =
|
||||||
// (bootTests pkgsStable nixos-stable "-nixos-stable");
|
nixos-stable.legacyPackages.x86_64-linux.callPackage ./nix/kexec-installer/test.nix
|
||||||
|
{ kexecTarball = self.packages.x86_64-linux.kexec-installer-nixos-stable-noninteractive; };
|
||||||
|
};
|
||||||
in
|
in
|
||||||
nixos-unstable.lib.recursiveUpdate packages { riscv64-linux = checks; };
|
nixos-unstable.lib.recursiveUpdate packages { x86_64-linux = checks; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
5
garnix.yaml
Normal file
5
garnix.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
builds:
|
||||||
|
include:
|
||||||
|
- '*.x86_64-linux.*'
|
||||||
|
- '*.aarch64-linux.*'
|
||||||
|
- nixosConfigurations.*
|
|
@ -40,9 +40,8 @@ in
|
||||||
imports = [
|
imports = [
|
||||||
(modulesPath + "/installer/cd-dvd/installation-cd-base.nix")
|
(modulesPath + "/installer/cd-dvd/installation-cd-base.nix")
|
||||||
../installer.nix
|
../installer.nix
|
||||||
../noveau-workaround.nix
|
|
||||||
./hidden-ssh-announcement.nix
|
|
||||||
./wifi.nix
|
./wifi.nix
|
||||||
|
./hidden-ssh-announcement.nix
|
||||||
];
|
];
|
||||||
systemd.tmpfiles.rules = [ "d /var/shared 0777 root root - -" ];
|
systemd.tmpfiles.rules = [ "d /var/shared 0777 root root - -" ];
|
||||||
services.openssh.settings.PermitRootLogin = "yes";
|
services.openssh.settings.PermitRootLogin = "yes";
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
nixpkgs,
|
|
||||||
nixos,
|
|
||||||
nixosModules,
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
testConfig = (
|
|
||||||
nixos [
|
|
||||||
(
|
|
||||||
{ modulesPath, ... }:
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
nixosModules.image-installer
|
|
||||||
"${modulesPath}/testing/test-instrumentation.nix"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
iso = testConfig.config.system.build.isoImage;
|
|
||||||
mkStartCommand =
|
|
||||||
{
|
|
||||||
memory ? 2048,
|
|
||||||
cdrom ? null,
|
|
||||||
usb ? null,
|
|
||||||
uefi ? false,
|
|
||||||
extraFlags ? [ ],
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
qemu-common = import (nixpkgs + "/nixos/lib/qemu-common.nix") { inherit lib pkgs; };
|
|
||||||
qemu = qemu-common.qemuBinary pkgs.qemu_test;
|
|
||||||
|
|
||||||
flags =
|
|
||||||
[
|
|
||||||
"-m"
|
|
||||||
(toString memory)
|
|
||||||
"-netdev"
|
|
||||||
"user,id=net0"
|
|
||||||
"-device"
|
|
||||||
"virtio-net-pci,netdev=net0"
|
|
||||||
]
|
|
||||||
++ lib.optionals (cdrom != null) [
|
|
||||||
"-cdrom"
|
|
||||||
cdrom
|
|
||||||
]
|
|
||||||
++ lib.optionals (usb != null) [
|
|
||||||
"-device"
|
|
||||||
"usb-ehci"
|
|
||||||
"-drive"
|
|
||||||
"id=usbdisk,file=${usb},if=none,readonly"
|
|
||||||
"-device"
|
|
||||||
"usb-storage,drive=usbdisk"
|
|
||||||
]
|
|
||||||
++ lib.optionals uefi [
|
|
||||||
"-drive"
|
|
||||||
"if=pflash,format=raw,unit=0,readonly=on,file=${pkgs.OVMF.firmware}"
|
|
||||||
"-drive"
|
|
||||||
"if=pflash,format=raw,unit=1,readonly=on,file=${pkgs.OVMF.variables}"
|
|
||||||
]
|
|
||||||
++ extraFlags;
|
|
||||||
|
|
||||||
flagsStr = lib.concatStringsSep " " flags;
|
|
||||||
in
|
|
||||||
"${qemu} ${flagsStr}";
|
|
||||||
|
|
||||||
makeBootTest =
|
|
||||||
name: config:
|
|
||||||
let
|
|
||||||
startCommand = mkStartCommand config;
|
|
||||||
in
|
|
||||||
pkgs.testers.runNixOSTest {
|
|
||||||
name = "boot-${name}";
|
|
||||||
nodes = { };
|
|
||||||
testScript = ''
|
|
||||||
machine = create_machine("${startCommand}")
|
|
||||||
machine.start()
|
|
||||||
machine.wait_for_unit("multi-user.target")
|
|
||||||
machine.succeed("nix store verify --no-trust -r --option experimental-features nix-command /run/current-system")
|
|
||||||
|
|
||||||
machine.shutdown()
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
uefi-cdrom = makeBootTest "uefi-cdrom" {
|
|
||||||
uefi = true;
|
|
||||||
cdrom = "${iso}/iso/nixos-installer-${pkgs.hostPlatform.system}.iso";
|
|
||||||
};
|
|
||||||
|
|
||||||
uefi-usb = makeBootTest "uefi-usb" {
|
|
||||||
uefi = true;
|
|
||||||
usb = "${iso}/iso/nixos-installer-${pkgs.hostPlatform.system}.iso";
|
|
||||||
};
|
|
||||||
|
|
||||||
bios-cdrom = makeBootTest "bios-cdrom" {
|
|
||||||
cdrom = "${iso}/iso/nixos-installer-${pkgs.hostPlatform.system}.iso";
|
|
||||||
};
|
|
||||||
|
|
||||||
bios-usb = makeBootTest "bios-usb" {
|
|
||||||
usb = "${iso}/iso/nixos-installer-${pkgs.hostPlatform.system}.iso";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -2,42 +2,39 @@
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
imports = [
|
|
||||||
# ./latest-zfs-kernel.nix
|
|
||||||
./nix-settings.nix
|
|
||||||
];
|
|
||||||
# more descriptive hostname than just "nixos"
|
# more descriptive hostname than just "nixos"
|
||||||
networking.hostName = lib.mkDefault "nixos-installer";
|
networking.hostName = lib.mkDefault "nixos-installer";
|
||||||
|
|
||||||
# We are stateless, so just default to latest.
|
# We are stateless, so just default to latest.
|
||||||
system.stateVersion = config.system.nixos.version;
|
system.stateVersion = config.system.nixos.version;
|
||||||
|
|
||||||
# Enable bcachefs support
|
|
||||||
boot.supportedFilesystems.bcachefs = lib.mkDefault true;
|
|
||||||
|
|
||||||
# use latest kernel we can support to get more hardware support
|
# use latest kernel we can support to get more hardware support
|
||||||
# boot.zfs.package = pkgs.zfsUnstable;
|
boot.kernelPackages =
|
||||||
|
lib.mkDefault
|
||||||
|
(pkgs.zfs.override { removeLinuxDRM = pkgs.hostPlatform.isAarch64; }).latestCompatibleLinuxPackages;
|
||||||
|
boot.zfs.removeLinuxDRM = lib.mkDefault pkgs.hostPlatform.isAarch64;
|
||||||
|
|
||||||
documentation.enable = false;
|
documentation.enable = false;
|
||||||
documentation.man.man-db.enable = false;
|
documentation.man.man-db.enable = false;
|
||||||
|
|
||||||
# make it easier to debug boot failures
|
|
||||||
boot.initrd.systemd.emergencyAccess = true;
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
pkgs.nixos-install-tools
|
pkgs.nixos-install-tools
|
||||||
# for zapping of disko
|
# for zapping of disko
|
||||||
pkgs.jq
|
pkgs.jq
|
||||||
# for copying extra files of nixos-anywhere
|
# for copying extra files of nixos-anywhere
|
||||||
pkgs.rsync
|
pkgs.rsync
|
||||||
# alternative to nixos-generate-config
|
];
|
||||||
# TODO: use nixpkgs again after next nixos release
|
|
||||||
(pkgs.callPackage ./nixos-facter.nix {})
|
|
||||||
|
|
||||||
pkgs.disko
|
imports = [
|
||||||
|
./nix-settings.nix
|
||||||
|
# reduce closure size by removing perl
|
||||||
|
"${modulesPath}/profiles/perlless.nix"
|
||||||
|
# FIXME: we still are left with nixos-generate-config due to nixos-install-tools
|
||||||
|
{ system.forbiddenDependenciesRegexes = lib.mkForce []; }
|
||||||
];
|
];
|
||||||
|
|
||||||
# Don't add nixpkgs to the image to save space, for our intended use case we don't need it
|
# Don't add nixpkgs to the image to save space, for our intended use case we don't need it
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
#!/usr/bin/env -S nix shell --inputs-from .# nixos-unstable#bash nixos-unstable#iproute2 nixos-unstable#findutils nixos-unstable#coreutils nixos-unstable#python3 nixos-unstable#jq --command bash
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
||||||
|
|
||||||
# This script can be used to see what network configuration would be restored by the restore_routes.py script for the current system.
|
|
||||||
|
|
||||||
tmp=$(mktemp -d)
|
|
||||||
trap "rm -rf $tmp" EXIT
|
|
||||||
ip --json address >"$tmp/addrs.json"
|
|
||||||
ip -6 --json route >"$tmp/routes-v6.json"
|
|
||||||
ip -4 --json route >"$tmp/routes-v4.json"
|
|
||||||
python3 "$SCRIPT_DIR/restore_routes.py" "$tmp/addrs.json" "$tmp/routes-v4.json" "$tmp/routes-v6.json" "$tmp"
|
|
||||||
ls -la "$tmp"
|
|
||||||
|
|
||||||
find "$tmp" -type f -name "*.json" -print0 | while IFS= read -r -d '' file; do
|
|
||||||
echo -e "\033[0;31m$(basename "$file")\033[0m"
|
|
||||||
jq . "$file"
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
find "$tmp" -type f -name "*.network" -print0 | while IFS= read -r -d '' file; do
|
|
||||||
echo -e "\033[0;31m$(basename "$file")\033[0m"
|
|
||||||
cat "$file"
|
|
||||||
echo ""
|
|
||||||
done
|
|
|
@ -1,17 +1,33 @@
|
||||||
{ config, lib, modulesPath, pkgs, ... }:
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
modulesPath,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
writePython3 = pkgs.writers.makePythonWriter
|
restore-network = pkgs.writers.writePython3 "restore-network" {
|
||||||
pkgs.python3Minimal pkgs.python3Packages pkgs.buildPackages.python3Packages;
|
flakeIgnore = [ "E501" ];
|
||||||
|
|
||||||
# writePython3Bin takes the same arguments as writePython3 but outputs a directory (like writeScriptBin)
|
|
||||||
writePython3Bin = name: writePython3 "/bin/${name}";
|
|
||||||
|
|
||||||
restore-network = writePython3Bin "restore-network" {
|
|
||||||
flakeIgnore = [ "E501" ];
|
|
||||||
} ./restore_routes.py;
|
} ./restore_routes.py;
|
||||||
|
|
||||||
# does not link with iptables enabled
|
# does not link with iptables enabled
|
||||||
iprouteStatic = pkgs.pkgsStatic.iproute2.override { iptables = null; };
|
iprouteStatic = pkgs.pkgsStatic.iproute2.override { iptables = null; };
|
||||||
|
|
||||||
|
kexec-tools = pkgs.pkgsStatic.kexec-tools.overrideAttrs (old: {
|
||||||
|
patches = old.patches ++ [
|
||||||
|
(pkgs.fetchpatch {
|
||||||
|
url = "https://marc.info/?l=kexec&m=166636009110699&q=mbox";
|
||||||
|
hash = "sha256-wi0/Ajy/Ac+7npKEvDsMzgNhEWhOMFeoUWcpgGrmVDc=";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
nativeBuildInputs = (old.nativeBuildInputs or []) ++ [
|
||||||
|
pkgs.pkgsStatic.buildPackages.autoreconfHook
|
||||||
|
];
|
||||||
|
meta = old.meta // {
|
||||||
|
badPlatforms = [ ]; # allow riscv64
|
||||||
|
};
|
||||||
|
});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
|
@ -21,7 +37,6 @@ in
|
||||||
../serial.nix
|
../serial.nix
|
||||||
../restore-remote-access.nix
|
../restore-remote-access.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
system.kexec-installer.name = lib.mkOption {
|
system.kexec-installer.name = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
|
@ -33,26 +48,27 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
boot.initrd.compressor = "xz";
|
|
||||||
# This is a variant of the upstream kexecScript that also allows embedding
|
# This is a variant of the upstream kexecScript that also allows embedding
|
||||||
# a ssh key.
|
# a ssh key.
|
||||||
system.build.kexecRun = pkgs.runCommand "kexec-run" { } ''
|
system.build.kexecRun =
|
||||||
install -D -m 0755 ${./kexec-run.sh} $out
|
pkgs.runCommand "kexec-run" { nativeBuildInputs = [ pkgs.buildPackages.shellcheck ]; }
|
||||||
|
''
|
||||||
|
install -D -m 0755 ${./kexec-run.sh} $out
|
||||||
|
|
||||||
sed -i \
|
sed -i \
|
||||||
-e 's|@init@|${config.system.build.toplevel}/init|' \
|
-e 's|@init@|${config.system.build.toplevel}/init|' \
|
||||||
-e 's|@kernelParams@|${lib.escapeShellArgs config.boot.kernelParams}|' \
|
-e 's|@kernelParams@|${lib.escapeShellArgs config.boot.kernelParams}|' \
|
||||||
$out
|
$out
|
||||||
|
|
||||||
${pkgs.shellcheck}/bin/shellcheck $out
|
shellcheck $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
system.build.kexecTarball = pkgs.runCommand "kexec-tarball" { } ''
|
system.build.kexecTarball = pkgs.runCommand "kexec-tarball" { } ''
|
||||||
mkdir kexec $out
|
mkdir kexec $out
|
||||||
cp "${config.system.build.netbootRamdisk}/initrd" kexec/initrd
|
cp "${config.system.build.netbootRamdisk}/initrd" kexec/initrd
|
||||||
cp "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}" kexec/bzImage
|
cp "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}" kexec/bzImage
|
||||||
cp "${config.system.build.kexecRun}" kexec/run
|
cp "${config.system.build.kexecRun}" kexec/run
|
||||||
cp "${pkgs.pkgsStatic.kexec-tools}/bin/kexec" kexec/kexec
|
cp "${kexec-tools}/bin/kexec" kexec/kexec
|
||||||
cp "${iprouteStatic}/bin/ip" kexec/ip
|
cp "${iprouteStatic}/bin/ip" kexec/ip
|
||||||
${lib.optionalString (pkgs.hostPlatform == pkgs.buildPlatform) ''
|
${lib.optionalString (pkgs.hostPlatform == pkgs.buildPlatform) ''
|
||||||
kexec/ip -V
|
kexec/ip -V
|
||||||
|
@ -73,7 +89,7 @@ in
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
ExecStart = [
|
ExecStart = [
|
||||||
"${restore-network}/bin/restore-network /root/network/addrs.json /root/network/routes-v4.json /root/network/routes-v6.json /etc/systemd/network"
|
"${restore-network} /root/network/addrs.json /root/network/routes-v4.json /root/network/routes-v6.json /etc/systemd/network"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,80 +1,34 @@
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Iterator
|
from typing import Any
|
||||||
from dataclasses import dataclass
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
def filter_interfaces(network: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||||
class Address:
|
output = []
|
||||||
address: str
|
|
||||||
family: str
|
|
||||||
prefixlen: int
|
|
||||||
preferred_life_time: int = 0
|
|
||||||
valid_life_time: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Interface:
|
|
||||||
name: str
|
|
||||||
ifname: str | None
|
|
||||||
mac_address: str
|
|
||||||
dynamic_addresses: list[Address]
|
|
||||||
static_addresses: list[Address]
|
|
||||||
static_routes: list[dict[str, Any]]
|
|
||||||
|
|
||||||
|
|
||||||
def filter_interfaces(network: list[dict[str, Any]]) -> list[Interface]:
|
|
||||||
interfaces = []
|
|
||||||
for net in network:
|
for net in network:
|
||||||
if net.get("link_type") == "loopback":
|
if net.get("link_type") == "loopback":
|
||||||
continue
|
continue
|
||||||
if not (mac_address := net.get("address")):
|
if not net.get("address"):
|
||||||
# We need a mac address to match devices reliable
|
# We need a mac address to match devices reliable
|
||||||
continue
|
continue
|
||||||
static_addresses = []
|
addr_info = []
|
||||||
dynamic_addresses = []
|
has_dynamic_address = False
|
||||||
for info in net.get("addr_info", []):
|
for addr in net.get("addr_info", []):
|
||||||
# no link-local ipv4/ipv6
|
# no link-local ipv4/ipv6
|
||||||
if info.get("scope") == "link":
|
if addr.get("scope") == "link":
|
||||||
continue
|
continue
|
||||||
if (preferred_life_time := info.get("preferred_life_time")) is None:
|
# do not explicitly configure addresses from dhcp or router advertisement
|
||||||
|
if addr.get("dynamic", False):
|
||||||
|
has_dynamic_address = True
|
||||||
continue
|
continue
|
||||||
if (valid_life_time := info.get("valid_life_time")) is None:
|
|
||||||
continue
|
|
||||||
if (prefixlen := info.get("prefixlen")) is None:
|
|
||||||
continue
|
|
||||||
if (family := info.get("family")) not in ["inet", "inet6"]:
|
|
||||||
continue
|
|
||||||
if (local := info.get("local")) is None:
|
|
||||||
continue
|
|
||||||
if (dynamic := info.get("dynamic", False)) is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
address = Address(
|
|
||||||
address=local,
|
|
||||||
family=family,
|
|
||||||
prefixlen=prefixlen,
|
|
||||||
preferred_life_time=preferred_life_time,
|
|
||||||
valid_life_time=valid_life_time,
|
|
||||||
)
|
|
||||||
|
|
||||||
if dynamic:
|
|
||||||
dynamic_addresses.append(address)
|
|
||||||
else:
|
else:
|
||||||
static_addresses.append(address)
|
addr_info.append(addr)
|
||||||
interfaces.append(
|
if addr_info != [] or has_dynamic_address:
|
||||||
Interface(
|
net["addr_info"] = addr_info
|
||||||
name=net.get("ifname", mac_address.replace(":", "-")),
|
output.append(net)
|
||||||
ifname=net.get("ifname"),
|
|
||||||
mac_address=mac_address,
|
|
||||||
dynamic_addresses=dynamic_addresses,
|
|
||||||
static_addresses=static_addresses,
|
|
||||||
static_routes=[],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return interfaces
|
return output
|
||||||
|
|
||||||
|
|
||||||
def filter_routes(routes: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
def filter_routes(routes: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||||
|
@ -88,54 +42,38 @@ def filter_routes(routes: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||||
return filtered
|
return filtered
|
||||||
|
|
||||||
|
|
||||||
def find_most_recent_v4_lease(addresses: list[Address]) -> Address | None:
|
|
||||||
most_recent_address = None
|
|
||||||
most_recent_lifetime = -1
|
|
||||||
for addr in addresses:
|
|
||||||
if addr.family == "inet6":
|
|
||||||
continue
|
|
||||||
lifetime = max(addr.preferred_life_time, addr.valid_life_time)
|
|
||||||
if lifetime > most_recent_lifetime:
|
|
||||||
most_recent_lifetime = lifetime
|
|
||||||
most_recent_address = addr
|
|
||||||
return most_recent_address
|
|
||||||
|
|
||||||
|
|
||||||
def generate_routes(
|
|
||||||
interface: Interface, routes: list[dict[str, Any]]
|
|
||||||
) -> Iterator[str]:
|
|
||||||
for route in routes:
|
|
||||||
if interface.ifname is None or route.get("dev") != interface.ifname:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# we may ignore on-link default routes here, but I don't see how
|
|
||||||
# they would be useful for internet connectivity anyway
|
|
||||||
|
|
||||||
yield "[Route]"
|
|
||||||
if route.get("dst") != "default":
|
|
||||||
# can be skipped for default routes
|
|
||||||
yield f"Destination = {route['dst']}"
|
|
||||||
gateway = route.get("gateway")
|
|
||||||
# route v4 via v6
|
|
||||||
route_via = route.get("via")
|
|
||||||
if route_via and route_via.get("family") == "inet6":
|
|
||||||
gateway = route_via.get("host")
|
|
||||||
if route.get("dst") == "default":
|
|
||||||
yield "Destination = 0.0.0.0/0"
|
|
||||||
if gateway:
|
|
||||||
yield f"Gateway = {gateway}"
|
|
||||||
|
|
||||||
|
|
||||||
def generate_networkd_units(
|
def generate_networkd_units(
|
||||||
interfaces: list[Interface], routes: list[dict[str, Any]], directory: Path
|
interfaces: list[dict[str, Any]], routes: list[dict[str, Any]], directory: Path
|
||||||
) -> None:
|
) -> None:
|
||||||
directory.mkdir(exist_ok=True)
|
directory.mkdir(exist_ok=True)
|
||||||
for interface in interfaces:
|
for interface in interfaces:
|
||||||
|
name = f"00-{interface['ifname']}.network"
|
||||||
|
addresses = [
|
||||||
|
f"Address = {addr['local']}/{addr['prefixlen']}"
|
||||||
|
for addr in interface.get("addr_info", [])
|
||||||
|
]
|
||||||
|
|
||||||
|
route_sections = []
|
||||||
|
for route in routes:
|
||||||
|
if route.get("dev", "nodev") != interface.get("ifname", "noif"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
route_section = "[Route]\n"
|
||||||
|
if route.get("dst") != "default":
|
||||||
|
# can be skipped for default routes
|
||||||
|
route_section += f"Destination = {route['dst']}\n"
|
||||||
|
gateway = route.get("gateway")
|
||||||
|
if gateway:
|
||||||
|
route_section += f"Gateway = {gateway}\n"
|
||||||
|
|
||||||
|
# we may ignore on-link default routes here, but I don't see how
|
||||||
|
# they would be useful for internet connectivity anyway
|
||||||
|
route_sections.append(route_section)
|
||||||
|
|
||||||
# FIXME in some networks we might not want to trust dhcp or router advertisements
|
# FIXME in some networks we might not want to trust dhcp or router advertisements
|
||||||
unit_sections = [
|
unit = f"""
|
||||||
f"""
|
|
||||||
[Match]
|
[Match]
|
||||||
MACAddress = {interface.mac_address}
|
MACAddress = {interface["address"]}
|
||||||
|
|
||||||
[Network]
|
[Network]
|
||||||
# both ipv4 and ipv6
|
# both ipv4 and ipv6
|
||||||
|
@ -145,24 +83,12 @@ LLDP = yes
|
||||||
# ipv6 router advertisements
|
# ipv6 router advertisements
|
||||||
IPv6AcceptRA = yes
|
IPv6AcceptRA = yes
|
||||||
# allows us to ping "nixos.local"
|
# allows us to ping "nixos.local"
|
||||||
MulticastDNS = yes"""
|
MulticastDNS = yes
|
||||||
]
|
|
||||||
unit_sections.extend(
|
|
||||||
f"Address = {addr.address}/{addr.prefixlen}"
|
|
||||||
for addr in interface.static_addresses
|
|
||||||
)
|
|
||||||
unit_sections.extend(generate_routes(interface, routes))
|
|
||||||
most_recent_v4_lease = find_most_recent_v4_lease(interface.dynamic_addresses)
|
|
||||||
if most_recent_v4_lease:
|
|
||||||
unit_sections.append("[DHCPv4]")
|
|
||||||
unit_sections.append(f"RequestAddress = {most_recent_v4_lease.address}")
|
|
||||||
|
|
||||||
# trailing newline at the end
|
"""
|
||||||
unit_sections.append("")
|
unit += "\n".join(addresses)
|
||||||
|
unit += "\n" + "\n".join(route_sections)
|
||||||
(directory / f"00-{interface.name}.network").write_text(
|
(directory / name).write_text(unit)
|
||||||
"\n".join(unit_sections)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
{ pkgs
|
{ pkgs
|
||||||
, lib
|
, lib
|
||||||
, kexecTarball
|
, kexecTarball
|
||||||
, nixos-facter ? null
|
|
||||||
}:
|
}:
|
||||||
|
|
||||||
pkgs.testers.runNixOSTest {
|
let
|
||||||
|
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
|
||||||
|
makeTest' = args: makeTest args {
|
||||||
|
inherit pkgs;
|
||||||
|
inherit (pkgs) system;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
makeTest' {
|
||||||
name = "kexec-installer";
|
name = "kexec-installer";
|
||||||
meta = with pkgs.lib.maintainers; {
|
meta = with pkgs.lib.maintainers; {
|
||||||
maintainers = [ mic92 ];
|
maintainers = [ mic92 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
node1 = { modulesPath, pkgs, ... }: {
|
node1 = { modulesPath, ... }: {
|
||||||
virtualisation.vlans = [ ];
|
virtualisation.vlans = [ ];
|
||||||
|
environment.noXlibs = false; # avoid recompilation
|
||||||
imports = [
|
imports = [
|
||||||
(modulesPath + "/profiles/minimal.nix")
|
(modulesPath + "/profiles/minimal.nix")
|
||||||
];
|
];
|
||||||
|
@ -47,17 +54,10 @@ pkgs.testers.runNixOSTest {
|
||||||
"192.168.42.1/24"
|
"192.168.42.1/24"
|
||||||
"42::1/64"
|
"42::1/64"
|
||||||
];
|
];
|
||||||
routes = if pkgs.lib.versionAtLeast lib.version "24.11" then [
|
routes = [
|
||||||
{ Destination = "192.168.43.0/24"; }
|
|
||||||
{ Destination = "192.168.44.0/24"; Gateway = "192.168.43.1"; }
|
|
||||||
{ Destination = "192.168.45.0/24"; Gateway = "43::1"; }
|
|
||||||
{ Destination = "43::0/64"; }
|
|
||||||
{ Destination = "44::1/64"; Gateway = "43::1"; }
|
|
||||||
] else [
|
|
||||||
# Some static routes that we want to see in the kexeced image
|
# Some static routes that we want to see in the kexeced image
|
||||||
{ routeConfig = { Destination = "192.168.43.0/24"; }; }
|
{ routeConfig = { Destination = "192.168.43.0/24"; }; }
|
||||||
{ routeConfig = { Destination = "192.168.44.0/24"; Gateway = "192.168.43.1"; }; }
|
{ routeConfig = { Destination = "192.168.44.0/24"; Gateway = "192.168.43.1"; }; }
|
||||||
{ routeConfig = { Destination = "192.168.45.0/24"; Gateway = "43::1"; }; }
|
|
||||||
{ routeConfig = { Destination = "43::0/64"; }; }
|
{ routeConfig = { Destination = "43::0/64"; }; }
|
||||||
{ routeConfig = { Destination = "44::1/64"; Gateway = "43::1"; }; }
|
{ routeConfig = { Destination = "44::1/64"; Gateway = "43::1"; }; }
|
||||||
];
|
];
|
||||||
|
@ -65,14 +65,10 @@ pkgs.testers.runNixOSTest {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // lib.optionalAttrs (lib.versionOlder lib.version "24.11pre") {
|
|
||||||
# avoid second overlay
|
|
||||||
environment.noXlibs = false;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = /*python*/ ''
|
testScript = ''
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
import subprocess
|
import subprocess
|
||||||
import socket
|
import socket
|
||||||
|
@ -167,11 +163,6 @@ pkgs.testers.runNixOSTest {
|
||||||
host = ssh(["hostname"], stdout=subprocess.PIPE).stdout.strip()
|
host = ssh(["hostname"], stdout=subprocess.PIPE).stdout.strip()
|
||||||
assert host == "nixos-installer", f"hostname is {host}, not nixos-installer"
|
assert host == "nixos-installer", f"hostname is {host}, not nixos-installer"
|
||||||
|
|
||||||
has_nixos_facter=${if nixos-facter != null then "True" else "False"}
|
|
||||||
if has_nixos_facter == True:
|
|
||||||
data = json.loads(ssh(["nixos-facter"], stdout=subprocess.PIPE).stdout)
|
|
||||||
assert data["virtualisation"] == "kvm", f"virtualisation is {data['virtualisation']}, not kvm"
|
|
||||||
|
|
||||||
host_ed25519_after = ssh(["cat", "/etc/ssh/ssh_host_ed25519_key.pub"], stdout=subprocess.PIPE).stdout.strip()
|
host_ed25519_after = ssh(["cat", "/etc/ssh/ssh_host_ed25519_key.pub"], stdout=subprocess.PIPE).stdout.strip()
|
||||||
assert host_ed25519_before == host_ed25519_after, f"'{host_ed25519_before}' != '{host_ed25519_after}'"
|
assert host_ed25519_before == host_ed25519_after, f"'{host_ed25519_before}' != '{host_ed25519_after}'"
|
||||||
|
|
||||||
|
@ -194,10 +185,6 @@ pkgs.testers.runNixOSTest {
|
||||||
print(out)
|
print(out)
|
||||||
assert "192.168.44.2 via 192.168.43.1" in out, f"route to `192.168.44.2 via 192.168.43.1` not found: {out}"
|
assert "192.168.44.2 via 192.168.43.1" in out, f"route to `192.168.44.2 via 192.168.43.1` not found: {out}"
|
||||||
|
|
||||||
out = ssh(["ip", "route", "get", "192.168.45.2"], stdout=subprocess.PIPE).stdout
|
|
||||||
print(out)
|
|
||||||
assert "192.168.45.2 via inet6 43::1" in out, f"route to `192.168.45.2 via inet6 43::1` not found: {out}"
|
|
||||||
|
|
||||||
out = ssh(["ip", "route", "get", "43::2"], stdout=subprocess.PIPE).stdout
|
out = ssh(["ip", "route", "get", "43::2"], stdout=subprocess.PIPE).stdout
|
||||||
print(out)
|
print(out)
|
||||||
assert "43::2 from :: dev" in out, f"route `43::2 from dev` not found: {out}"
|
assert "43::2 from :: dev" in out, f"route `43::2 from dev` not found: {out}"
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
isUnstable = config.boot.zfs.package == pkgs.zfsUnstable;
|
|
||||||
zfsCompatibleKernelPackages = lib.filterAttrs (
|
|
||||||
name: kernelPackages:
|
|
||||||
(builtins.match "linux_[0-9]+_[0-9]+" name) != null
|
|
||||||
&& (builtins.tryEval kernelPackages).success
|
|
||||||
&& (
|
|
||||||
(!isUnstable && !kernelPackages.zfs.meta.broken)
|
|
||||||
|| (isUnstable && !kernelPackages.zfs_unstable.meta.broken)
|
|
||||||
)
|
|
||||||
) pkgs.linuxKernel.packages;
|
|
||||||
latestKernelPackage = lib.last (
|
|
||||||
lib.sort (a: b: (lib.versionOlder a.kernel.version b.kernel.version)) (builtins.attrValues zfsCompatibleKernelPackages)
|
|
||||||
);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Note this might jump back and worth as kernel get added or removed.
|
|
||||||
boot.kernelPackages = latestKernelPackage;
|
|
||||||
}
|
|
|
@ -5,7 +5,11 @@
|
||||||
nix.settings.connect-timeout = 5;
|
nix.settings.connect-timeout = 5;
|
||||||
|
|
||||||
# Enable flakes
|
# Enable flakes
|
||||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
nix.settings.experimental-features = [
|
||||||
|
"nix-command"
|
||||||
|
"flakes"
|
||||||
|
"repl-flake"
|
||||||
|
];
|
||||||
|
|
||||||
# The default at 10 is rarely enough.
|
# The default at 10 is rarely enough.
|
||||||
nix.settings.log-lines = lib.mkDefault 25;
|
nix.settings.log-lines = lib.mkDefault 25;
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
{
|
|
||||||
lib,
|
|
||||||
buildGoModule,
|
|
||||||
fetchFromGitHub,
|
|
||||||
hwinfo,
|
|
||||||
libusb1,
|
|
||||||
gcc,
|
|
||||||
pkg-config,
|
|
||||||
util-linux,
|
|
||||||
pciutils,
|
|
||||||
stdenv,
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
# We are waiting on some changes to be merged upstream: https://github.com/openSUSE/hwinfo/pulls
|
|
||||||
hwinfoOverride = hwinfo.overrideAttrs {
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "numtide";
|
|
||||||
repo = "hwinfo";
|
|
||||||
rev = "a559f34934098d54096ed2078e750a8245ae4044";
|
|
||||||
hash = "sha256-3abkWPr98qXXQ17r1Z43gh2M5hl/DHjW2hfeWl+GSAs=";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
buildGoModule rec {
|
|
||||||
pname = "nixos-facter";
|
|
||||||
version = "0.1.1";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "numtide";
|
|
||||||
repo = "nixos-facter";
|
|
||||||
rev = "v${version}";
|
|
||||||
hash = "sha256-vlPmvCrgX64dcf//BPtQszBt7dkq35JpgQg+/LW0AqM=";
|
|
||||||
};
|
|
||||||
|
|
||||||
vendorHash = "sha256-5leiTNp3FJmgFd0SKhu18hxYZ2G9SuQPhZJjki2SDVs=";
|
|
||||||
|
|
||||||
CGO_ENABLED = 1;
|
|
||||||
|
|
||||||
buildInputs = [
|
|
||||||
libusb1
|
|
||||||
hwinfoOverride
|
|
||||||
];
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
|
||||||
gcc
|
|
||||||
pkg-config
|
|
||||||
];
|
|
||||||
|
|
||||||
runtimeInputs = [
|
|
||||||
libusb1
|
|
||||||
util-linux
|
|
||||||
pciutils
|
|
||||||
];
|
|
||||||
|
|
||||||
ldflags = [
|
|
||||||
"-s"
|
|
||||||
"-w"
|
|
||||||
"-X git.numtide.com/numtide/nixos-facter/build.Name=nixos-facter"
|
|
||||||
"-X git.numtide.com/numtide/nixos-facter/build.Version=v${version}"
|
|
||||||
"-X github.com/numtide/nixos-facter/pkg/build.System=${stdenv.hostPlatform.system}"
|
|
||||||
];
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "Declarative hardware configuration for NixOS";
|
|
||||||
homepage = "https://github.com/numtide/nixos-facter";
|
|
||||||
license = lib.licenses.gpl3Plus;
|
|
||||||
maintainers = [ lib.maintainers.brianmcgee ];
|
|
||||||
mainProgram = "nixos-facter";
|
|
||||||
platforms = lib.platforms.linux;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
# This module optimizes for non-interactive deployments by remove some store paths
|
# This module optimizes for non-interactive deployments by remove some store paths
|
||||||
# which are primarily useful for interactive installations.
|
# which are primarily useful for interactive installations.
|
||||||
|
|
||||||
{ lib, pkgs, modulesPath, ... }:
|
{ lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
disabledModules = [
|
disabledModules = [
|
||||||
# This module adds values to multiple lists (systemPackages, supportedFilesystems)
|
# This module adds values to multiple lists (systemPackages, supportedFilesystems)
|
||||||
|
@ -10,14 +10,8 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
# ./zfs-minimal.nix
|
./zfs-minimal.nix
|
||||||
./no-bootloaders.nix
|
./no-bootloaders.nix
|
||||||
./python-minimal.nix
|
|
||||||
./noveau-workaround.nix
|
|
||||||
# reduce closure size by removing perl
|
|
||||||
"${modulesPath}/profiles/perlless.nix"
|
|
||||||
# FIXME: we still are left with nixos-generate-config due to nixos-install-tools
|
|
||||||
{ system.forbiddenDependenciesRegexes = lib.mkForce []; }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# among others, this prevents carrying a stdenv with gcc in the image
|
# among others, this prevents carrying a stdenv with gcc in the image
|
||||||
|
@ -30,29 +24,10 @@
|
||||||
programs.nano.enable = false;
|
programs.nano.enable = false;
|
||||||
|
|
||||||
# prevents strace
|
# prevents strace
|
||||||
environment.defaultPackages = lib.mkForce [
|
environment.defaultPackages = lib.mkForce [ pkgs.rsync pkgs.parted pkgs.gptfdisk ];
|
||||||
pkgs.rsync
|
|
||||||
pkgs.parted
|
|
||||||
pkgs.gptfdisk
|
|
||||||
pkgs.e2fsprogs
|
|
||||||
];
|
|
||||||
|
|
||||||
# normal users are not allowed with sys-users
|
|
||||||
# see https://github.com/NixOS/nixpkgs/pull/328926
|
|
||||||
users.users.nixos = {
|
|
||||||
isSystemUser = true;
|
|
||||||
isNormalUser = lib.mkForce false;
|
|
||||||
shell = "/run/current-system/sw/bin/bash";
|
|
||||||
group = "nixos";
|
|
||||||
};
|
|
||||||
users.groups.nixos = {};
|
|
||||||
|
|
||||||
# we prefer root as this is also what we use in nixos-anywhere
|
|
||||||
services.getty.autologinUser = lib.mkForce "root";
|
|
||||||
|
|
||||||
# we are missing this from base.nix
|
# we are missing this from base.nix
|
||||||
boot.supportedFilesystems = [
|
boot.supportedFilesystems = [
|
||||||
"ext4"
|
|
||||||
"btrfs"
|
"btrfs"
|
||||||
# probably not needed but does not seem to increase closure size
|
# probably not needed but does not seem to increase closure size
|
||||||
"cifs"
|
"cifs"
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
# fixes blank screen on boot for some cards
|
|
||||||
boot.kernelParams = [ "nouveau.modeset=0" ];
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
nixpkgs.overlays = [
|
|
||||||
(final: prev: {
|
|
||||||
bcachefs-tools = prev.bcachefs-tools.override { python3 = final.python3Minimal; };
|
|
||||||
cifs-utils = prev.cifs-utils.override { python3 = final.python3Minimal; };
|
|
||||||
nfs-utils = prev.nfs-utils.override { python3 = final.python3Minimal; };
|
|
||||||
talloc = prev.talloc.override { python3 = final.python3Minimal; };
|
|
||||||
})
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -1,21 +1,33 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
# incorperate a space-optimized version of zfs
|
# incorperate a space-optimized version of zfs
|
||||||
let
|
let
|
||||||
zfs = pkgs.zfsUnstable.override {
|
zfs = pkgs.zfs.override {
|
||||||
# this overrides saves 10MB
|
# this overrides saves 10MB
|
||||||
samba = pkgs.coreutils;
|
samba = pkgs.coreutils;
|
||||||
|
|
||||||
python3 = pkgs.python3Minimal;
|
|
||||||
};
|
};
|
||||||
|
hasZfs = lib.meta.availableOn pkgs.stdenv.hostPlatform config.boot.zfs.package;
|
||||||
in
|
in
|
||||||
{
|
lib.mkIf hasZfs {
|
||||||
services.udev.packages = [ zfs ]; # to hook zvol naming, etc.
|
services.udev.packages = [ zfs ]; # to hook zvol naming, etc.
|
||||||
# unsure if need this, but in future udev rules could potentially point to systemd services.
|
# unsure if need this, but in future udev rules could potentially point to systemd services.
|
||||||
systemd.packages = [ zfs ];
|
systemd.packages = [ zfs ];
|
||||||
environment.defaultPackages = lib.mkForce [ zfs ]; # this merges with outer noninteractive module.
|
environment.defaultPackages = lib.mkForce [ zfs ]; # this merges with outer noninteractive module.
|
||||||
|
|
||||||
boot.kernelModules = [ "zfs" ];
|
boot.kernelModules = [ "zfs" ];
|
||||||
boot.extraModulePackages = [ config.boot.kernelPackages.zfs_unstable ];
|
boot.extraModulePackages = [
|
||||||
|
(config.boot.kernelPackages.zfs.override {
|
||||||
|
inherit (config.boot.zfs) removeLinuxDRM;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.kernelPatches = lib.optional (config.boot.zfs.removeLinuxDRM && pkgs.stdenv.hostPlatform.system == "aarch64-linux") {
|
||||||
|
name = "export-neon-symbols-as-gpl";
|
||||||
|
patch = pkgs.fetchpatch {
|
||||||
|
url = "https://github.com/torvalds/linux/commit/aaeca98456431a8d9382ecf48ac4843e252c07b3.patch";
|
||||||
|
hash = "sha256-L2g4G1tlWPIi/QRckMuHDcdWBcKpObSWSRTvbHRIwIk=";
|
||||||
|
revert = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
networking.hostId = lib.mkDefault "8425e349";
|
networking.hostId = lib.mkDefault "8425e349";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue