diff --git a/.gitignore b/.gitignore index c921b6a..6f2bad1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ result* -*.qcow2 +/.vms/* +!/.vms/.gitkeep diff --git a/.vms/.gitkeep b/.vms/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/boxes/colony.nix b/boxes/colony.nix index 707cd7c..e7fecfb 100644 --- a/boxes/colony.nix +++ b/boxes/colony.nix @@ -1,5 +1,13 @@ { lib, pkgs, inputs, ... }: { + fileSystems = { + "/persist" = { + device = "/dev/disk/by-label/persist"; + fsType = "ext4"; + neededForBoot = true; + }; + }; + my = { server.enable = true; }; diff --git a/flake.lock b/flake.lock index e9a08e1..80f215c 100644 --- a/flake.lock +++ b/flake.lock @@ -60,11 +60,11 @@ }, "flake-utils": { "locked": { - "lastModified": 1642700792, - "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", "owner": "numtide", "repo": "flake-utils", - "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", "type": "github" }, "original": { @@ -80,11 +80,11 @@ ] }, "locked": { - "lastModified": 1643933104, - "narHash": "sha256-NZPuFxRsZKN8pjRuHPpzlMyt6JQhcjiduBG8bMghSjE=", + "lastModified": 1644534280, + "narHash": "sha256-Gzf/Jq/F1vvTp6XkzPU+pBCj3OSAFLiR7f0ptwRseiI=", "owner": "nix-community", "repo": "home-manager", - "rev": "63dccc4e60422c1db2c3929b2fd1541f36b7e664", + "rev": "6d9d9294d09b5e88df65f8c6651efb8a4d7d2476", "type": "github" }, "original": { @@ -93,6 +93,22 @@ "type": "github" } }, + "impermanence": { + "locked": { + "lastModified": 1644541943, + "narHash": "sha256-bMiRtPs3xh8S3duX7JiWLZdUZi7RwktpXGhykCdCroE=", + "owner": "devplayer0", + "repo": "impermanence", + "rev": "4bfa7f8b6844be7172264c1f7c11ac0c89027f79", + "type": "github" + }, + "original": { + "owner": "devplayer0", + "ref": "qemu-vm-dirs", + "repo": "impermanence", + "type": "github" + } + }, "lowdown-src": { "flake": false, "locked": { @@ -161,11 +177,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1643788601, - "narHash": "sha256-6l5Ax44pC/Oo/Muj5Y/NA27Pd38Wty/7GtGSSmYNug4=", + "lastModified": 1644193793, + "narHash": "sha256-ggCI5LCXwkUJQwjpkr9qDFbQMiK3JvAfeNR4Uy0ny5Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f6ddd55d5f9d5eca08df138c248008c1ba73ecec", + "rev": "521e4d7d13b09bc0a21976b9d19abd197d4e3b1e", "type": "github" }, "original": { @@ -176,11 +192,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1643805626, - "narHash": "sha256-AXLDVMG+UaAGsGSpOtQHPIKB+IZ0KSd9WS77aanGzgc=", + "lastModified": 1644420267, + "narHash": "sha256-rFJuctggkjM412OC6OGPdXogFp7czGDW05ueWqpJbj8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "554d2d8aa25b6e583575459c297ec23750adb6cb", + "rev": "98bb5b77c8c6666824a4c13d23befa1e07210ef1", "type": "github" }, "original": { @@ -195,6 +211,7 @@ "deploy-rs": "deploy-rs", "flake-utils": "flake-utils", "home-manager": "home-manager", + "impermanence": "impermanence", "nix": "nix", "nixpkgs-stable": "nixpkgs-stable", "nixpkgs-unstable": "nixpkgs-unstable" diff --git a/flake.nix b/flake.nix index 7d82834..0a69c03 100644 --- a/flake.nix +++ b/flake.nix @@ -8,14 +8,18 @@ # For extra-stable systems nixpkgs-stable.url = "nixpkgs/nixos-21.11"; - nix.url = "nix/latest-release"; + # Stuff used by the flake for build / deployment agenix.url = "github:ryantm/agenix"; agenix.inputs.nixpkgs.follows = "nixpkgs-unstable"; deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable"; - home-manager.url = "github:nix-community/home-manager"; home-manager.inputs.nixpkgs.follows = "nixpkgs-unstable"; + + # Stuff used by systems + nix.url = "nix/latest-release"; + #impermanence.url = "github:nix-community/impermanence"; + impermanence.url = "github:devplayer0/impermanence/qemu-vm-dirs"; }; outputs = @@ -26,7 +30,6 @@ nixpkgs-unstable, nixpkgs-stable, - nix, agenix, deploy-rs, @@ -51,7 +54,7 @@ lib = pkgsFlakes.unstable.lib; - pkgs' = mapAttrs (_: path: lib.my.mkPkgs path { overlays = [libOverlay]; }) pkgsFlakes; + pkgs' = mapAttrs (_: path: lib.my.mkPkgs path { overlays = [ libOverlay ]; }) pkgsFlakes; in { inherit lib; @@ -60,12 +63,14 @@ imports = [ (import path') ]; }) { common = "common.nix"; + build = "build.nix"; tmproot = "tmproot.nix"; server = "server.nix"; }; nixosConfigurations = import ./systems.nix { inherit lib pkgsFlakes inputs; modules = self.nixosModules; }; - vms = mapAttrs (_: system: system.config.system.build.vm) self.nixosConfigurations; + systems = mapAttrs (_: system: system.config.system.build.toplevel) self.nixosConfigurations; + vms = mapAttrs (_: system: system.config.my.build.devVM) self.nixosConfigurations; apps = let apps' = {} diff --git a/modules/build.nix b/modules/build.nix new file mode 100644 index 0000000..cb9889e --- /dev/null +++ b/modules/build.nix @@ -0,0 +1,31 @@ +{ lib, extendModules, modulesPath, options, config, ... }: + let + inherit (lib) mkOption; + inherit (lib.my) mkBoolOpt; + + cfg = config.my.build; + + # TODO: This is broken on 21.11 (https://github.com/NixOS/nixpkgs/issues/148343) + asDevVM = extendModules { + modules = [ + (import "${modulesPath}/virtualisation/qemu-vm.nix") + ({ config, ... }: { + my.boot.isDevVM = true; + }) + ]; + }; + in { + options.my = with lib.types; { + boot.isDevVM = mkBoolOpt false; + build = options.system.build; + asDevVM = mkOption { + inherit (asDevVM) type; + default = {}; + visible = "shallow"; + }; + }; + + config.my.build = { + devVM = config.my.asDevVM.system.build.vm; + }; + } diff --git a/modules/common.nix b/modules/common.nix index 73468db..514032a 100644 --- a/modules/common.nix +++ b/modules/common.nix @@ -44,6 +44,29 @@ experimental-features = nix-command flakes ca-derivations ''; }; + nixpkgs = { + config = { + allowUnfree = true; + }; + }; + + boot = { + # Use latest LTS release by default + kernelPackages = mkDefault pkgs.linuxKernel.packages.linux_5_15; + loader = { + efi = { + efiSysMountPoint = mkDefault "/boot"; + canTouchEfiVariables = mkDefault false; + }; + systemd-boot = { + enable = mkDefault true; + editor = mkDefault true; + consoleMode = mkDefault "max"; + configurationLimit = mkDefault 10; + memtest86.enable = mkDefault true; + }; + }; + }; environment.systemPackages = with pkgs; [ bash-completion diff --git a/modules/tmproot.nix b/modules/tmproot.nix index 9574208..017d13f 100644 --- a/modules/tmproot.nix +++ b/modules/tmproot.nix @@ -1,7 +1,7 @@ -{ lib, pkgs, inputs, config, ... }: +{ lib, pkgs, inputs, config, ... }@args: let - inherit (lib) concatStringsSep mkIf mkDefault mkAliasDefinitions; - inherit (lib.my) mkOpt mkBoolOpt; + inherit (lib) any concatStringsSep mkIf mkDefault mkMerge mkVMOverride; + inherit (lib.my) mkOpt mkBoolOpt mkVMOverride'; cfg = config.my.tmproot; @@ -45,17 +45,63 @@ recurse(base) ''; + + rootDef = { + device = "yeet"; + fsType = "tmpfs"; + options = [ "size=${cfg.size}" ]; + }; in { + imports = [ inputs.impermanence.nixosModules.impermanence ]; + options.my.tmproot = with lib.types; { enable = mkBoolOpt true; + persistDir = mkOpt str "/persist"; + size = mkOpt str "2G"; ignoreUnsaved = mkOpt (listOf str) [ "/tmp" ]; }; - config = mkIf cfg.enable { - environment.systemPackages = [ - (pkgs.writeScriptBin "tmproot-unsaved" showUnsaved) - ]; - }; + config = mkMerge [ + (mkIf cfg.enable { + assertions = [ + { + assertion = config.fileSystems ? "${cfg.persistDir}"; + message = "The 'fileSystems' option does not specify your persistence file system (${cfg.persistDir})."; + } + ]; + + environment.systemPackages = [ + (pkgs.writeScriptBin "tmproot-unsaved" showUnsaved) + ]; + + environment.persistence."${cfg.persistDir}" = { + hideMounts = mkDefault true; + directories = [ + "/var/log" + ]; + files = [ + "/etc/machine-id" + ]; + }; + + fileSystems."/" = rootDef; + + # If we need to override any VM-specific options that the modules system won't know about this early + my.asDevVM.config.virtualisation = { + diskImage = "./.vms/${config.system.name}-persist.qcow2"; + }; + }) + (mkIf (cfg.enable && config.my.boot.isDevVM) { + fileSystems = mkVMOverride { + "/" = mkVMOverride' rootDef; + # Hijack the "root" device for persistence in the VM + "${cfg.persistDir}" = { + device = config.virtualisation.bootDevice; + neededForBoot = true; + }; + }; + }) + ]; } diff --git a/systems.nix b/systems.nix index 320df48..907c80b 100644 --- a/systems.nix +++ b/systems.nix @@ -18,7 +18,7 @@ in mapAttrs mkSystem { colony = { system = "x86_64-linux"; - nixpkgs = "stable"; + nixpkgs = "unstable"; config = boxes/colony.nix; }; } diff --git a/util.nix b/util.nix index 1879e1a..36a3492 100644 --- a/util.nix +++ b/util.nix @@ -1,6 +1,6 @@ { lib }: let - inherit (lib) genAttrs mapAttrs' types mkOption; + inherit (lib) genAttrs mapAttrs' types mkOption mkOverride; inherit (lib.flake) defaultSystems; in { addPrefix = prefix: mapAttrs' (n: v: { name = "${prefix}${n}"; value = v; }); @@ -12,4 +12,5 @@ type = types.bool; example = true; }; + mkVMOverride' = mkOverride 9; }