forked from tangled.org/core
this repo has no description

nix/vm: store service data in a shared folder on the host

This also switches away from `nixos-shell` in the process as by this
point it wasn't really adding much to our setup except inflexibility.

Signed-off-by: Winter <winter@winter.cafe>

authored by winter.bsky.social and committed by Tangled cc04dc01 ecd7277d

Changed files
+82 -50
docs
nix
+2 -1
.gitignore
··· 16 16 *.rdb 17 17 .envrc 18 18 # Created if following hacking.md 19 - genjwks.out 19 + genjwks.out 20 + /nix/vm-data
+4 -6
docs/hacking.md
··· 64 64 You will also need to set the `$TANGLED_VM_SPINDLE_OWNER` 65 65 variable to some value. If you don't want to [set up a 66 66 spindle](#running-a-spindle), you can use any placeholder 67 - value. 67 + value. 68 68 69 - You can now start a lightweight NixOS VM using 70 - `nixos-shell` like so: 69 + You can now start a lightweight NixOS VM like so: 71 70 72 71 ```bash 73 - nix run .#vm 74 - # or nixos-shell --flake .#vm 72 + nix run --impure .#vm 75 73 76 - # hit Ctrl-a + c + q to exit the VM 74 + # type `poweroff` at the shell to exit the VM 77 75 ``` 78 76 79 77 This starts a knot on port 6000, a spindle on port 6555
+22 -27
flake.nix
··· 175 175 program = ''${tailwind-watcher}/bin/run''; 176 176 }; 177 177 vm = let 178 - system = 178 + guestSystem = 179 179 if pkgs.stdenv.hostPlatform.isAarch64 180 - then "aarch64" 181 - else "x86_64"; 182 - 183 - nixos-shell = pkgs.nixos-shell.overrideAttrs (old: { 184 - patches = 185 - (old.patches or []) 186 - ++ [ 187 - # https://github.com/Mic92/nixos-shell/pull/94 188 - (pkgs.fetchpatch { 189 - name = "fix-foreign-vm.patch"; 190 - url = "https://github.com/Mic92/nixos-shell/commit/113e4cc55ae236b5b0b1fbd8b321e9b67c77580e.patch"; 191 - hash = "sha256-eauetBK0wXAOcd9PYbExokNCiwz2QyFnZ4FnwGi9VCo="; 192 - }) 193 - ]; 194 - }); 180 + then "aarch64-linux" 181 + else "x86_64-linux"; 195 182 in { 196 183 type = "app"; 197 - program = toString (pkgs.writeShellScript "vm" '' 198 - ${nixos-shell}/bin/nixos-shell --flake .#vm-${system} --guest-system ${system}-linux 199 - ''); 184 + program = 185 + (pkgs.writeShellApplication { 186 + name = "launch-vm"; 187 + text = '' 188 + rootDir=$(jj --ignore-working-copy root || git rev-parse --show-toplevel) || (echo "error: can't find repo root?"; exit 1) 189 + cd "$rootDir" 190 + 191 + mkdir -p nix/vm-data/{knot,repos,spindle,spindle-logs} 192 + 193 + export TANGLED_VM_DATA_DIR="$rootDir/nix/vm-data" 194 + exec ${pkgs.lib.getExe 195 + (import ./nix/vm.nix { 196 + inherit nixpkgs self; 197 + system = guestSystem; 198 + hostSystem = system; 199 + }).config.system.build.vm} 200 + ''; 201 + }) 202 + + /bin/launch-vm; 200 203 }; 201 204 gomod2nix = { 202 205 type = "app"; ··· 257 260 imports = [./nix/modules/spindle.nix]; 258 261 259 262 services.tangled-spindle.package = lib.mkDefault self.packages.${pkgs.system}.spindle; 260 - }; 261 - nixosConfigurations.vm-x86_64 = import ./nix/vm.nix { 262 - inherit self nixpkgs; 263 - system = "x86_64-linux"; 264 - }; 265 - nixosConfigurations.vm-aarch64 = import ./nix/vm.nix { 266 - inherit self nixpkgs; 267 - system = "aarch64-linux"; 268 263 }; 269 264 }; 270 265 }
+54 -16
nix/vm.nix
··· 1 1 { 2 2 nixpkgs, 3 3 system, 4 + hostSystem, 4 5 self, 5 6 }: let 6 7 envVar = name: let ··· 16 17 self.nixosModules.knot 17 18 self.nixosModules.spindle 18 19 ({ 20 + lib, 19 21 config, 20 22 pkgs, 21 23 ... 22 24 }: { 23 - nixos-shell = { 24 - inheritPath = false; 25 - mounts = { 26 - mountHome = false; 27 - mountNixProfile = false; 28 - }; 29 - }; 30 - virtualisation = { 25 + virtualisation.vmVariant.virtualisation = { 26 + host.pkgs = import nixpkgs {system = hostSystem;}; 27 + 28 + graphics = false; 31 29 memorySize = 2048; 32 30 diskSize = 10 * 1024; 33 31 cores = 2; ··· 51 49 guest.port = 6555; 52 50 } 53 51 ]; 52 + sharedDirectories = { 53 + # We can't use the 9p mounts directly for most of these 54 + # as SQLite is incompatible with them. So instead we 55 + # mount the shared directories to a different location 56 + # and copy the contents around on service start/stop. 57 + knotData = { 58 + source = "$TANGLED_VM_DATA_DIR/knot"; 59 + target = "/mnt/knot-data"; 60 + }; 61 + spindleData = { 62 + source = "$TANGLED_VM_DATA_DIR/spindle"; 63 + target = "/mnt/spindle-data"; 64 + }; 65 + spindleLogs = { 66 + source = "$TANGLED_VM_DATA_DIR/spindle-logs"; 67 + target = "/var/log/spindle"; 68 + }; 69 + }; 54 70 }; 71 + # This is fine because any and all ports that are forwarded to host are explicitly marked above, we don't need a separate guest firewall 72 + networking.firewall.enable = false; 55 73 services.getty.autologinUser = "root"; 56 74 environment.systemPackages = with pkgs; [curl vim git sqlite litecli]; 57 - systemd.tmpfiles.rules = let 58 - u = config.services.tangled-knot.gitUser; 59 - g = config.services.tangled-knot.gitUser; 60 - in [ 61 - "d /var/lib/knot 0770 ${u} ${g} - -" # Create the directory first 62 - "f+ /var/lib/knot/secret 0660 ${u} ${g} - KNOT_SERVER_SECRET=${envVar "TANGLED_VM_KNOT_SECRET"}" 63 - ]; 64 75 services.tangled-knot = { 65 76 enable = true; 66 77 motd = "Welcome to the development knot!\n"; 67 78 server = { 68 - secretFile = "/var/lib/knot/secret"; 79 + secretFile = builtins.toFile "knot-secret" ("KNOT_SERVER_SECRET=" + (envVar "TANGLED_VM_KNOT_SECRET")); 69 80 hostname = "localhost:6000"; 70 81 listenAddr = "0.0.0.0:6000"; 71 82 }; ··· 81 92 provider = "sqlite"; 82 93 }; 83 94 }; 95 + }; 96 + users = { 97 + # So we don't have to deal with permission clashing between 98 + # blank disk VMs and existing state 99 + users.${config.services.tangled-knot.gitUser}.uid = 666; 100 + groups.${config.services.tangled-knot.gitUser}.gid = 666; 101 + 102 + # TODO: separate spindle user 103 + }; 104 + systemd.services = let 105 + mkDataSyncScripts = source: target: { 106 + enableStrictShellChecks = true; 107 + 108 + preStart = lib.mkBefore '' 109 + mkdir -p ${target} 110 + ${lib.getExe pkgs.rsync} -a ${source}/ ${target} 111 + ''; 112 + 113 + postStop = lib.mkAfter '' 114 + ${lib.getExe pkgs.rsync} -a ${target}/ ${source} 115 + ''; 116 + 117 + serviceConfig.PermissionsStartOnly = true; 118 + }; 119 + in { 120 + knot = mkDataSyncScripts "/mnt/knot-data" config.services.tangled-knot.stateDir; 121 + spindle = mkDataSyncScripts "/mnt/spindle-data" (builtins.dirOf config.services.tangled-spindle.server.dbPath); 84 122 }; 85 123 }) 86 124 ];