Browse Source

Installer works

main
Dustin Frisch 1 week ago
parent
commit
33e6c423b8
No known key found for this signature in database GPG Key ID: B4C3BF012D9B26BE
  1. 6
      TODO.md
  2. 16
      client/default.nix
  3. 4
      client/hardware.nix
  4. 5
      flake.nix
  5. 86
      installer/default.nix
  6. 19
      installer/installer.nix
  7. 28
      machines/installer/default.nix
  8. 65
      machines/installer/hardware.nix
  9. 59
      machines/installer/installer/default.nix
  10. 38
      machines/installer/netinstall.nix
  11. 1
      machines/installer/secrets/cache.crt
  12. 24
      machines/installer/secrets/cache.key
  13. 3
      machines/ldap/default.nix
  14. 2
      machines/nfs/cache.nix
  15. 2
      machines/nfs/default.nix
  16. 27
      machines/nfs/dhcp.nix
  17. 85
      machines/nfs/netinstaller.nix
  18. 24
      machines/nfs/secrets/cache.key
  19. 1
      machines/nfs/secrets/cache.pub
  20. 13
      shared/cache.nix
  21. 5
      shared/default.nix
  22. 3
      shared/network.nix
  23. 4
      shared/users.nix
  24. 1
      sops-config.nix

6
TODO.md

@ -1,6 +1,5 @@
# Tasks
- Configure user env on client (using envfs?)
- Configure docker on client
- Make installer work
- Move ldap to subdomain
- Check external SSH access
@ -8,6 +7,11 @@
- Quota per user on homedir
- Exim recovery
- A fancy background image?
- Client Requirements:
- docker + docker-compose [name=könig]
- rstudio [name=james]
- quarto [name=james]
- miniconda [name=james]
# Issuse
- Cleartext password in sssd/ldap config

16
client/default.nix

@ -5,7 +5,11 @@ id:
with lib;
let
client = (import ../clients.nix).${id};
client =
if id != null
then (import ../clients.nix).${id}
else null;
in
{
imports = [
@ -17,8 +21,9 @@ in
./programs.nix
];
deployment = {
targetHost = "10.32.45.150";
deployment = optionalAttrs (client != null) {
inherit (client) targetHost;
tags = [ "client" ];
};
@ -27,7 +32,10 @@ in
};
networking = {
hostName = mkForce "client-${id}";
hostName = mkForce (if id != null
then "client-${id}"
else "client");
useDHCP = mkForce true;
};

4
client/hardware.nix

@ -1,4 +1,4 @@
{ modulesPath, ... }:
{ modulesPath, ... }:
{
imports = [
@ -48,7 +48,7 @@
disk = {
root = {
type = "disk";
device = "/dev/sda";
device = "/dev/disk/by-path/pci-0000:04:00.0-nvme-1";
imageSize = "32G";
content = {
type = "gpt";

5
flake.nix

@ -53,6 +53,7 @@
# List of all machine names as defined in the machines directory
machines = builtins.attrNames (builtins.readDir ./machines);
# List of all client names
clients = builtins.attrNames (import ./clients.nix);
in
@ -78,6 +79,8 @@
deployment.replaceUnknownProfiles = false;
};
"client" = (import ./client) null;
}
# Machines
@ -92,7 +95,7 @@
// (builtins.listToAttrs (builtins.map
(id: {
name = "client-${id}";
value = (import ./client) id;
value = ./client;
})
clients))
;

86
installer/default.nix

@ -0,0 +1,86 @@
{ pkgs, lib, modulesPath, config, target, ... }:
with lib;
let
installer = pkgs.callPackage ./installer.nix { inherit target; };
auto-installer =
let
# This removes the direct dependency from the installer to the target image.
# The install script is realized later during runtime using the cache.
# To make this work, the cache must provide the real installer script.
installer-path = builtins.unsafeDiscardStringContext (toString installer);
in
pkgs.writers.writeBash "auto-installer" ''
set -o errexit
set -o nounset
set -o pipefail
set -x
${pkgs.retry}/bin/retry \
--times 10 \
--delay 15 \
-- ${pkgs.nix}/bin/nix-store \
--realize \
--add-root /tmp/installer \
"${installer-path}"
/tmp/installer
reboot
'';
in
{
imports = [
"${modulesPath}/installer/netboot/netboot-minimal.nix"
../shared/users.nix
../shared/network.nix
../shared/cache.nix
];
_module.args = {
name = "installer";
};
networking.useDHCP = mkForce true;
services.getty.autologinUser = lib.mkForce "root";
systemd.services."auto-install" = {
description = "Automated NixOS installer";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
conflicts = [ "getty@tty1.service" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ bash nix ];
unitConfig = {
FailureAction = "force-reboot";
};
serviceConfig = {
Type = "oneshot";
ExecStart = auto-installer;
StandardInput = "none";
StandardOutput = "journal+console";
StandardError = "journal+console";
};
};
# Expose the installer script
system.build.installer = installer;
system.stateVersion = config.system.nixos.release;
}

19
installer/installer.nix

@ -0,0 +1,19 @@
{ writers, target, ... }:
writers.writeBash "installer" ''
set -o errexit
set -o nounset
set -o pipefail
set -x
"${target.config.system.build.diskoScript}"
"${target.config.system.build.nixos-install}/bin/nixos-install" \
--root /mnt \
--system "${target.config.system.build.toplevel}" \
--no-channel-copy \
--no-root-password \
--verbose
''

28
machines/installer/default.nix

@ -1,28 +0,0 @@
{
imports = [
./hardware.nix
# TODO: ./cache.nix
# ./netinstall.nix
];
deployment = {
targetHost = "10.33.64.21";
};
networking = {
interfaces."eth0" = {
ipv4.addresses = [{
address = "10.33.64.21";
prefixLength = 20;
}];
};
defaultGateway = {
interface = "eth0";
address = "10.33.64.1";
};
};
system.stateVersion = "24.05";
}

65
machines/installer/hardware.nix

@ -1,65 +0,0 @@
{ modulesPath, ... }:
{
imports = [
"${modulesPath}/installer/scan/not-detected.nix"
];
nixpkgs.hostPlatform = "x86_64-linux";
boot.initrd.availableKernelModules = [
"uhci_hcd"
"ehci_pci"
"ata_piix"
"mptsas"
"usb_storage"
"usbhid"
"sd_mod"
"sr_mod"
];
boot.loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
hardware.enableRedistributableFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
disko.devices = {
disk = {
root = {
type = "disk";
device = "/dev/disk/by-path/pci-0000:01:00.0-scsi-0:1:0:0";
imageSize = "64G";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02";
};
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
};
};
}

59
machines/installer/installer/default.nix

@ -1,59 +0,0 @@
{ pkgs, lib, modulesPath, config, target, ... }:
with lib;
let
installer = pkgs.writers.writeBash "installer" ''
set -euo pipefail
"${target.config.system.build.diskoScript}"
"${target.config.system.build.nixos-install}" \
--root /mnt \
--system "${target.config.system.build.toplevel}" \
--no-channel-copy \
--no-root-password \
--verbose
reboot
'';
in {
imports = [
"${modulesPath}/installer/netboot/netboot-minimal.nix"
];
networking.hostName = "installer";
services.getty.autologinUser = lib.mkForce "root";
systemd.services."auto-install" = {
description = "Automated NixOS installer";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
conflicts = [ "getty@tty1.service" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ bash nix ];
unitConfig = {
FailureAction = "force-reboot";
};
serviceConfig = {
Type = "oneshot";
ExecStart = installer;
StandardInput = "none";
StandardOutput = "journal+console";
StandardError = "journal+console";
};
};
system.stateVersion = config.system.nixos.release;
}

38
machines/installer/netinstall.nix

@ -1,38 +0,0 @@
{ pkgs, lib, nodes, ... }:
with lib;
let
installer = pkgs.nixos [
./installer
{
_module.args = {
target = nodes."client";
};
}
];
in
{
services.pixiecore = {
enable = true;
dhcpNoBind = true;
port = 5080;
mode = "boot";
kernel = "file://${installer.config.system.build.kernel}/bzImage";
initrd = "file://${installer.config.system.build.netbootRamdisk}/initrd";
cmdLine = concatStringsSep " " [
"init=${installer.config.system.build.toplevel}/init"
"loglevel=4"
"console=tty0"
"console=ttyS1,57600n8"
];
openFirewall = true;
};
}

1
machines/installer/secrets/cache.crt

@ -1 +0,0 @@
cache.linuxlab.informatik.hs-fulda.de:jrTFzlS3uRzOOteHmynLmSIvFMWgb4+YH+ShcrczdEY=

24
machines/installer/secrets/cache.key

@ -1,24 +0,0 @@
{
"data": "ENC[AES256_GCM,data:u2f84L2XIPqNBPKtkAU7LAwUj0wwxemsOuUB/qk/SSjutA8RLi5TmBQHnnBY/5l3u154JN9RzHsHQyMp7NHiT1gsmvrmNhdWRzLTxG7MfIJW0SVpjD7X6GLmH5vnVSLJZScRfHgdRcYl9sFO7HlT/vRAtb57ZYM+QZS5b1ZB,iv:yzwOKZA5iwrn/CkhtwF7tUytsy0lseJcBqm4UqVAsqA=,tag:WhxIH/K314fvOm81lfK6EQ==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1gsv9h0faztlavyw8ydl3t8p39u737jj48qvg8lrnsdkamthqaepsqegr08",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLVDhNSjF0amNnSWJ2ZEhq\ndnRoOXZpYk5oN09abFozK1Y0WVhDSVJ2U0RzCkw0OXhScjQwRGlDcDdnUHh2cDd3\nclBDd2RwQzRIMy9CVjZXbGFNSUdjU2cKLS0tIHBzSXdCMElkclJMU2I0WWtHbTJP\nWW5TQ2syRk9Obm5qYUtZVGZYbmtzTkEKkMiRInW2OuY6FhXTfueqokehWNxwO905\ntk5jVzyS0kVDt2Mi29Ny+HUhTpLWn2mJii8HMz698ElAxvXrHBZurQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age14lgxmyw860py9yyjz3cxkr6u0x30qra2e27c9my0sycqyfankf2sjrsse6",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvSHBOUUhqcHlPeTNXOE8z\nWDlNZkhSbnY5SEV5MFplWmhNVXpTaXlycHd3Ck9hY1F6LzNpWjhFdWN0SnpaT0M0\nR2R5TmRNek0wYTJUREp4YklTaVJzdXMKLS0tIDdOTWN6b2kwR1R3bzNTT2s1UFMr\nUm0yWHNkSXg5ZFR1dWhUdHRmSm13eG8Kcprh4nvmUDgI6/nntD+FTY4SsqpEAs3U\n44tvzXSNjEMp9dHIkVu45+NyKOGjZoNUAA7dEvFYAAgZqHPbLMJ0aw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2024-11-11T21:50:59Z",
"mac": "ENC[AES256_GCM,data:n6TfbZmYcV2ER7n4fXanVJ9ekbytU07NdHVDO/VoTkERvstb1NuTeo7LjA+KVVKxM3ZUvAtMfjpAXvgP1exL4WkOzQHk5RV3odfZhGsvMOUaHp7cfww6/JrO8I+EzJWhDh2tO+xFpuD2sprvNiWT60PFG6kDQKn7XYy63+ECCyo=,iv:7ytrvXtk3Mz3ioeuv0hc80y2FLSyUWdtFyVEhidUeAI=,tag:BS8am9kxloRP+AbavEmfPA==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.8.1"
}
}

3
machines/ldap/default.nix

@ -2,9 +2,6 @@
imports = [
./hardware.nix
./ldap.nix
# TODO:
# ../installer/netinstall.nix
];
deployment = {

2
machines/installer/cache.nix → machines/nfs/cache.nix

@ -10,7 +10,7 @@
enable = true;
virtualHosts."cache.${config.networking.domain}" = {
locations."/".proxyPass = with config.services.nix-serve;
"http://${bindAddress}:${port}";
"http://${bindAddress}:${toString port}";
};
};

2
machines/nfs/default.nix

@ -3,6 +3,8 @@
./hardware.nix
./dhcp.nix
./nfs.nix
./cache.nix
./netinstaller.nix
];
deployment = {

27
machines/nfs/dhcp.nix

@ -24,7 +24,7 @@
subnet4 = [
{
subnet = "10.33.64.0/20";
interface = "enp4s0f1";
interface = "enp4s0f0";
pools = [
{
@ -96,30 +96,5 @@
67
68 # DHCP
];
services.pixiecore =
let
script = pkgs.writeText "boot-local.ipxe" ''
#!ipxe
sleep 2
sanboot -n -d 0x80
shell
'';
in
{
enable = true;
dhcpNoBind = true;
port = 5080;
mode = "boot";
kernel = toString script;
openFirewall = true;
};
}

85
machines/nfs/netinstaller.nix

@ -0,0 +1,85 @@
{ pkgs, lib, config, nodes, ... }:
with lib;
let
installer = pkgs.nixos [
../../installer
{
_module.args = {
target = nodes."client";
};
}
];
ipxe-script = pkgs.writeText "boot-local.ipxe" ''
#!ipxe
sleep 2
prompt --key 0x18 --timeout 5000 Press Ctrl-X to re-deploy system... || goto local
echo "Starting installer..."
sleep 2
kernel --name kernel http://''${next-server:ipv4}/bzImage || goto err
initrd --name initrd http://''${next-server:ipv4}/initrd || goto err
boot kernel initrd=initrd init=${installer.config.system.build.toplevel}/init loglevel=4 || goto err
:err
shell
:local
echo "Booting local disk..."
sleep 2
sanboot -n -d 0x80
'';
in
{
services.nginx = {
enable = true;
virtualHosts."boot.${config.networking.domain}" = {
locations."/" = {
root = pkgs.linkFarm "root" {
"bzImage" = installer.config.system.build.kernel + "/bzImage";
"initrd" = installer.config.system.build.netbootRamdisk + "/initrd";
};
};
};
};
services.pixiecore =
{
enable = true;
debug = true;
dhcpNoBind = true;
port = 5080;
mode = "boot";
kernel = toString ipxe-script;
openFirewall = true;
};
# Ensure the intaller script and therefore the client system is part of the
# store so it can be fetched by the installer.
boot.postBootCommands = ''
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/installer --set "${installer.installer}"
'';
networking.extraHosts = ''
127.0.0.1 boot.${config.networking.domain}
'';
networking.firewall.allowedTCPPorts = [
80 # HTTP
];
}

24
machines/nfs/secrets/cache.key

@ -0,0 +1,24 @@
{
"data": "ENC[AES256_GCM,data:BNxKj72aiPMNMsiZf8GjGG1L1TLMHoENAfnaic1LqyYZa2zZq7eWm7BNps2Iz9sP4voQbp9GB7/kvZ1iS3g8B8xb6r4QrylAgPHGcb/nXQb7xvUVM5glRCtC0mgyPSqbnzWz3bObgVR+fTlDGX5Ckt3lt4WWK6Pg90TG1FUK,iv:LFL8p6vAzgS8KyAu0LVX+op72UdhXyLMbU98PZ+fSus=,tag:5LWxdkS9d0kCFXJfZJ5tRw==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1gsv9h0faztlavyw8ydl3t8p39u737jj48qvg8lrnsdkamthqaepsqegr08",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2NUNFQWc3Z1NON3hRaW5B\nYlhkbllSTVlRUi9jS1lGTDZmVkRsYjJqMXpBCjZYak1OQ3ltT1hVMWp2Tis4Rklv\nK2E1MVN2OU9wUFp4c2RpdkZsMjVybUEKLS0tIFdidWp0TUE0RzBXd2l1L1lQYTVw\nWEJES29mRk1aSmtqeHJEWWNDV0d4L00K4nW0rBP4Rl+uDj+E0bq7MyuyDzKSsGRB\n0dtzqaEu+HHbRqne6MOU0+oh0bpln5vJhkSKdlD7bBIEOX3/AWwHdg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1kjjve9m33a5fads6ttc0kznmv0mn0cxladrk7nv8huhp8u2pw4vqyzuf2p",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzZi9maENnTjFhU2k1S3RJ\nUGFpbkc1d3BNNFEyQWlPdW9SK0VjR1ZYaG4wCnJvamNZL3p2MWFQOGlqVTgvbXRw\nMHdGU3V0SmE5NkQydGVaYzVEMmxyUGcKLS0tIGkyTWVpd2xFYmJKVGRzNk1KV3BU\ndVFza01xTnBXYnF2dnhUekN4QWpZaWcKcuBiZAZPXjxUgnRGGWz9FMhODMaNwlV+\nwVP5j7gL8VX1HvTLUU0lGyNA/st+KoAnugMKabW5TYRiyQyACIlO/w==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2024-11-14T18:01:59Z",
"mac": "ENC[AES256_GCM,data:TanGp5W9pmtO0x7yjKiyqPPIetoxrEldVSi0h/0JD6liZ/9G1gTU0miDYhOn0j2C8n/QoXVxjWWFfX/JNVC+Lt4rUrGCJDCo1gpMRHxym4VyCYiiEGgCh0D5IiNYSKLkIs/3JPYDAm+CrOcX4XjbcLMYiZkvWVcV+gh2s8vtXcE=,iv:XO8/adw+hQ3Z/8icJTvv4ct78qPsxS0mJQC2veLtDvk=,tag:e2DS3nieE+BsUUTx9C3Xmw==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.8.1"
}
}

1
machines/nfs/secrets/cache.pub

@ -0,0 +1 @@
cache.linuxlab.informatik.hs-fulda.de:ugWyeMyNqHvSEXDVgcPZ5NCniqq0wqKQCb3rjqXb/jU=

13
shared/cache.nix

@ -0,0 +1,13 @@
{ config, ... }:
{
nix.settings = {
substituters = [
"http://cache.${config.networking.domain}"
];
trusted-public-keys = [
"cache.${config.networking.domain}:ugWyeMyNqHvSEXDVgcPZ5NCniqq0wqKQCb3rjqXb/jU="
];
};
}

5
shared/default.nix

@ -1,4 +1,4 @@
{ name, ...}:
{ name, ... }:
{
imports = [
@ -6,6 +6,7 @@
./network.nix
./users.nix
./system.nix
./cache.nix
];
time.timeZone = "Europe/Berlin";
@ -15,7 +16,5 @@
_module.args = {
machinePath = ../machines/${name};
};
disko.imageBuilder.imageFormat = "qcow2";
}

3
shared/network.nix

@ -16,9 +16,8 @@
useDHCP = false;
extraHosts = ''
10.33.64.20 nfs.${config.networking.domain}
10.33.64.20 nfs.${config.networking.domain} cache.${config.networking.domain}
10.33.64.19 ldap.${config.networking.domain}
10.33.64.19 install.${config.networking.domain}
10.33.64.19 ldap-linuxlab.informatik.hs-fulda.de
'';

4
shared/users.nix

@ -1,10 +1,10 @@
{ pkgs, config, ...}:
{ pkgs, ... }:
{
users.mutableUsers = false;
users.users."root" = {
#hashedPassword = "$y$j9T$5ZEv2RROIXAqdFjFEXEst0$5HA63fmwjGXw1id4n94TRgY1gTuXsQGKXmzlcWXyE07";
#TODO: hashedPassword = "$y$j9T$5ZEv2RROIXAqdFjFEXEst0$5HA63fmwjGXw1id4n94TRgY1gTuXsQGKXmzlcWXyE07";
hashedPassword = "$y$j9T$IqOVsS6/ACfhDXzA3LqsZ1$J/16UDhw44bHWJqIoCdjms6IEwT4tk4ghq2WpThOlMA";
openssh.authorizedKeys.keys = [

1
sops-config.nix

@ -16,7 +16,6 @@ let
hosts = {
"nfs" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMA+Q4wLe0AuZ8OC5BKJLrvmpKcy+6a8Iez9hCSVgtX8";
"ldap" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFhkh5L4jYl/i4E+lBVDppHcoiohR/gDricyV2wY/3Np";
"installer" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrc58WlxYKaPNO1J8j8KQxOLJooc9fIxp6gZZoB4Y7o";
};
sshToAge = ssh-key:

Loading…
Cancel
Save