From 3e810b171189ba34a6955a2c621829279eb0b8ca Mon Sep 17 00:00:00 2001 From: oddlama Date: Wed, 26 Apr 2023 23:52:25 +0200 Subject: [PATCH] feat: add generation of installer image for each host --- README.md | 8 ++++- flake.lock | 70 ++++++++++++++++++++++++++++++++++---- flake.nix | 24 ++++++++++++- hosts/ward/fs.nix | 69 +++++++++++++++++++++++++++++++------ nix/generate-installer.nix | 46 +++++++++++++++++++++++++ nix/generate-node.nix | 2 ++ nix/lib.nix | 45 ++++++++++++++++++++++++ 7 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 nix/generate-installer.nix diff --git a/README.md b/README.md index 9061037..c603d9e 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ This is my personal nix config. - `format-secrets.nix` Runs the code formatter on the secret .nix files - `generate-initrd-keys.nix` Generates initrd hostkeys for each host if they don't exist yet (for setup) - `generate-wireguard-keys.nix` Generates wireguard keys for each server-and-peer pair + - `show-wireguard-qr.nix` Generates a QR code for external wireguard participants - `checks.nix` pre-commit-hooks for this repository - `colmena.nix` Setup for distributed deployment using colmena (actually defines all NixOS hosts) - `dev-shell.nix` Environment setup for `nix develop` for using this flake @@ -49,7 +50,7 @@ This is my personal nix config. ## How-To -#### Add and deploy new machine +#### Add new machine ... @@ -60,6 +61,11 @@ This is my personal nix config. - generate-initrd-keys - generate-wireguard-keys +#### Initial deploy + +- Boot from some nixos-minimal.iso +- + #### Show QR for external wireguard client nix run show-wireguard-qr diff --git a/flake.lock b/flake.lock index 4a853cf..de31bf7 100644 --- a/flake.lock +++ b/flake.lock @@ -109,6 +109,26 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1682299489, + "narHash": "sha256-bqHo0/82KB+IyBMyjBd6QdyZWJl/YZeGggjBsAgRFlY=", + "owner": "nix-community", + "repo": "disko", + "rev": "8ab9e5609929379ab15f03fd3bdc1f85419e5a3a", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -187,11 +207,11 @@ ] }, "locked": { - "lastModified": 1682273416, - "narHash": "sha256-YvRc5TOyf92Fcvt6cYfsqxfjqalAUME3Klv4IbdhkBE=", + "lastModified": 1682419509, + "narHash": "sha256-+/HI3RbJcEKQ5+55dECzh8geginsbabsA0R3ORKi2Us=", "owner": "nix-community", "repo": "home-manager", - "rev": "a5a294a622a7d3a837aaa145334e4d813c1bc5b1", + "rev": "6142193635ecdafb9a231bd7d1880b9b7b210d19", "type": "github" }, "original": { @@ -250,6 +270,42 @@ "type": "github" } }, + "nixlib": { + "locked": { + "lastModified": 1681001314, + "narHash": "sha256-5sDnCLdrKZqxLPK4KA8+f4A3YKO/u6ElpMILvX0g72c=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "367c0e1086a4eb4502b24d872cea2c7acdd557f4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1682332772, + "narHash": "sha256-GMoWhChQdeNM2FFqVbEZgBABSdi/+JgSP6v+jUz5b24=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "d774aeedc0685e5871be1e1ee0511900deeb21c2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, "nixos-hardware": { "locked": { "lastModified": 1680876084, @@ -288,11 +344,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1682181988, - "narHash": "sha256-CYWhlNi16cjGzMby9h57gpYE59quBcsHPXiFgX4Sw5k=", + "lastModified": 1682453498, + "narHash": "sha256-WoWiAd7KZt5Eh6n+qojcivaVpnXKqBsVgpixpV2L9CE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6c43a3495a11e261e5f41e5d7eda2d71dae1b2fe", + "rev": "c8018361fa1d1650ee8d4b96294783cf564e8a7f", "type": "github" }, "original": { @@ -349,11 +405,13 @@ "agenix": "agenix", "agenix-rekey": "agenix-rekey", "colmena": "colmena", + "disko": "disko", "flake-utils": "flake-utils", "home-manager": "home-manager", "impermanence": "impermanence", "lib-net": "lib-net", "microvm": "microvm", + "nixos-generators": "nixos-generators", "nixos-hardware": "nixos-hardware", "nixos-nftables-firewall": "nixos-nftables-firewall", "nixpkgs": "nixpkgs", diff --git a/flake.nix b/flake.nix index e4156b3..c1cfd0e 100644 --- a/flake.nix +++ b/flake.nix @@ -8,6 +8,11 @@ inputs.flake-utils.follows = "flake-utils"; }; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; @@ -22,6 +27,11 @@ nixos-hardware.url = "github:NixOS/nixos-hardware"; + nixos-generators = { + url = "github:nix-community/nixos-generators"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + nixos-nftables-firewall = { url = "github:thelegy/nixos-nftables-firewall"; inputs.nixpkgs.follows = "nixpkgs"; @@ -57,11 +67,14 @@ outputs = { self, colmena, + nixos-generators, nixpkgs, flake-utils, agenix-rekey, ... - } @ inputs: + } @ inputs: let + recursiveMergeAttrs = nixpkgs.lib.foldl' nixpkgs.lib.recursiveUpdate {}; + in { extraLib = import ./nix/lib.nix inputs; @@ -80,6 +93,15 @@ # All nixos based hosts collected together nodes = self.colmenaNodes // self.microvmNodes; + + # Collect installer packages + inherit + (recursiveMergeAttrs + (nixpkgs.lib.mapAttrsToList + (import ./nix/generate-installer.nix inputs) + self.colmenaNodes)) + packages + ; } // flake-utils.lib.eachDefaultSystem (system: rec { pkgs = import nixpkgs { diff --git a/hosts/ward/fs.nix b/hosts/ward/fs.nix index 8453acf..0a8fb59 100644 --- a/hosts/ward/fs.nix +++ b/hosts/ward/fs.nix @@ -1,16 +1,63 @@ { - fileSystems = { - "/" = { - device = "rpool/root/nixos"; - fsType = "zfs"; - options = ["zfsutil" "X-mount.mkdir"]; - }; - - "/boot" = { - device = "/dev/disk/by-uuid/10E6-553F"; - fsType = "vfat"; + extraLib, + pkgs, + ... +}: { + disko.devices = { + disk = { + m2-ssd = { + type = "disk"; + device = "/dev/disk/by-id/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + content = { + type = "table"; + format = "gpt"; + partitions = [ + { + name = "efi"; + start = "2048"; + end = "1GiB"; + fs-type = "fat32"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + } + { + name = "swap"; + start = "1GiB"; + end = "17GiB"; + content = { + type = "swap"; + randomEncryption = true; + }; + } + { + name = "rpool"; + start = "17GiB"; + end = "100%"; + content = { + type = "zfs"; + pool = "rpool"; + }; + } + ]; + }; + }; }; + zpool = extraLib.disko.defineEncryptedZpool "rpool" {}; }; - swapDevices = []; + boot.initrd.systemd.services = { + impermanence-root = { + wantedBy = ["initrd.target"]; + after = ["zfs-import-rpool.service"]; + before = ["sysroot.mount"]; + unitConfig.DefaultDependencies = "no"; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${pkgs.zfs}/bin/zfs rollback -r rpool/local/root@blank"; + }; + }; + }; } diff --git a/nix/generate-installer.nix b/nix/generate-installer.nix new file mode 100644 index 0000000..7236f80 --- /dev/null +++ b/nix/generate-installer.nix @@ -0,0 +1,46 @@ +{ + self, + nixos-generators, + ... +}: nodeName: nodeAttrs: let + inherit (self.hosts.${nodeName}) system; + configuration = {pkgs, ...}: { + system.stateVersion = "23.05"; + nix.extraOptions = '' + experimental-features = nix-command flakes recursive-nix + ''; + + services.openssh = { + enable = true; + settings.PermitRootLogin = "yes"; + }; + + users.users.root.password = "nixos"; + + environment = { + variables.EDITOR = "nvim"; + systemPackages = with pkgs; [ + neovim + git + tmux + parted + ripgrep + fzf + wget + curl + # TODO nodeAttrs.config.boot.system. + ]; + }; + }; +in { + packages.${system}."installer-image-${nodeName}" = nixos-generators.nixosGenerate { + pkgs = self.pkgs.${system}; + modules = [configuration]; + format = + { + x86_64-linux = "install-iso"; + aarch64-linux = "sd-aarch64-installer"; + } + .${system}; + }; +} diff --git a/nix/generate-node.nix b/nix/generate-node.nix index f8620f6..95d9bab 100644 --- a/nix/generate-node.nix +++ b/nix/generate-node.nix @@ -1,6 +1,7 @@ { self, colmena, + disko, home-manager, #impermanence, nixos-hardware, @@ -34,6 +35,7 @@ in #impermanence.nixosModules.default agenix.nixosModules.default agenix-rekey.nixosModules.default + disko.nixosModules.disko nixos-nftables-firewall.nixosModules.default ] ++ optionals nodeMeta.microVmHost [ diff --git a/nix/lib.nix b/nix/lib.nix index 73228a7..88c9945 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -20,6 +20,7 @@ mergeAttrs nameValuePair partition + recursiveUpdate removeSuffix splitString substring @@ -47,6 +48,50 @@ in rec { # True if the path or string starts with / isAbsolutePath = x: substring 0 1 x == "/"; + # Defines a simple encrypted and compressed pool + # with datasets necessary datasets for use with impermanence + disko.defineEncryptedZpool = name: + recursiveUpdate { + ${name} = { + type = "zpool"; + mode = "mirror"; + rootFsOptions = { + compression = "zstd"; + acltype = "posix"; + atime = "off"; + xattr = "sa"; + dnodesize = "auto"; + mountpoint = "none"; + canmount = "off"; + devices = "off"; + encryption = "aes-256-gcm"; + keyformat = "passphrase"; + keylocation = "prompt"; + }; + options.ashift = "12"; + datasets = { + "local".type = "zfs_fs"; + "local/root" = { + type = "zfs_fs"; + postCreateHook = "zfs snapshot ${name}/local/root@blank"; + options.canmount = "on"; + mountpoint = "/"; + }; + "local/nix" = { + type = "zfs_fs"; + options.canmount = "on"; + mountpoint = "/nix"; + }; + "safe".type = "zfs_fs"; + "safe/persist" = { + type = "zfs_fs"; + options.canmount = "on"; + mountpoint = "/persist"; + }; + }; + }; + }; + rageMasterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities; rageExtraEncryptionPubkeys = concatMapStrings (