|
| 1 | +{ lib, options, config, pkgs, ... }: |
| 2 | + |
| 3 | +let |
| 4 | + cfg = config.nixos-shell; |
| 5 | + |
| 6 | + mkVMDefault = lib.mkOverride 900; |
| 7 | +in { |
| 8 | + config = |
| 9 | + let |
| 10 | + user = builtins.getEnv "USER"; |
| 11 | + shell' = builtins.baseNameOf (builtins.getEnv "SHELL"); |
| 12 | + |
| 13 | + # fish seems to do funky stuff: https://github.com/Mic92/nixos-shell/issues/42 |
| 14 | + shell = if shell' == "fish" then "bash" else shell'; |
| 15 | + in |
| 16 | + lib.mkMerge [ |
| 17 | + # Enable the module of the user's shell for some sensible defaults. |
| 18 | + (lib.mkIf (options.programs ? ${shell}.enable && shell != "bash") { |
| 19 | + programs.${shell}.enable = mkVMDefault true; |
| 20 | + }) |
| 21 | + |
| 22 | + (lib.mkIf (pkgs ? ${shell}) { |
| 23 | + users.extraUsers.root.shell = mkVMDefault pkgs.${shell}; |
| 24 | + }) |
| 25 | + |
| 26 | + ( |
| 27 | + let |
| 28 | + home = builtins.getEnv "HOME"; |
| 29 | + in |
| 30 | + lib.mkIf (home != "" && cfg.mounts.mountHome) { |
| 31 | + users.extraUsers.root.home = lib.mkVMOverride home; |
| 32 | + } |
| 33 | + ) |
| 34 | + |
| 35 | + # Allow passwordless ssh login with the user's key if it exists. |
| 36 | + ( |
| 37 | + let |
| 38 | + keys = map (key: "${builtins.getEnv "HOME"}/.ssh/${key}") |
| 39 | + [ "id_rsa.pub" "id_ecdsa.pub" "id_ed25519.pub" ]; |
| 40 | + in |
| 41 | + { |
| 42 | + users.users.root.openssh.authorizedKeys.keyFiles = lib.filter builtins.pathExists keys; |
| 43 | + } |
| 44 | + ) |
| 45 | + |
| 46 | + { |
| 47 | + # Allow the user to login as root without password. |
| 48 | + users.extraUsers.root.initialHashedPassword = ""; |
| 49 | + |
| 50 | + # see https://wiki.qemu.org/Documentation/9psetup#Performance_Considerations |
| 51 | + # == 100M |
| 52 | + # FIXME? currently 500K seems to be the limit? |
| 53 | + virtualisation.msize = mkVMDefault 104857600; |
| 54 | + |
| 55 | + services = |
| 56 | + let |
| 57 | + service = if lib.versionAtLeast (lib.versions.majorMinor lib.version) "20.09" then "getty" else "mingetty"; |
| 58 | + in |
| 59 | + { |
| 60 | + ${service}.helpLine = '' |
| 61 | + Log in as "root" with an empty password. |
| 62 | + If you are connect via serial console: |
| 63 | + Type Ctrl-a c to switch to the qemu console |
| 64 | + and `quit` to stop the VM. |
| 65 | + ''; |
| 66 | + }; |
| 67 | + |
| 68 | + virtualisation = { |
| 69 | + graphics = mkVMDefault false; |
| 70 | + memorySize = mkVMDefault 700; |
| 71 | + |
| 72 | + qemu.consoles = lib.mkIf (!config.virtualisation.graphics) [ "tty0" "hvc0" ]; |
| 73 | + |
| 74 | + qemu.options = |
| 75 | + let |
| 76 | + nixProfile = "/nix/var/nix/profiles/per-user/${user}/profile/"; |
| 77 | + in |
| 78 | + lib.optionals (!config.virtualisation.graphics) [ |
| 79 | + "-serial null" |
| 80 | + "-device virtio-serial" |
| 81 | + "-chardev stdio,mux=on,id=char0,signal=off" |
| 82 | + "-mon chardev=char0,mode=readline" |
| 83 | + "-device virtconsole,chardev=char0,nr=0" |
| 84 | + ] ++ |
| 85 | + lib.optional cfg.mounts.mountHome "-virtfs local,path=/home,security_model=none,mount_tag=home" ++ |
| 86 | + lib.optional (cfg.mounts.mountNixProfile && builtins.pathExists nixProfile) "-virtfs local,path=${nixProfile},security_model=none,mount_tag=nixprofile" ++ |
| 87 | + lib.mapAttrsToList (target: mount: "-virtfs local,path=${builtins.toString mount.target},security_model=none,mount_tag=${mount.tag}") cfg.mounts.extraMounts; |
| 88 | + }; |
| 89 | + |
| 90 | + # build-vm overrides our filesystem settings in nixos-config |
| 91 | + boot.initrd.postMountCommands = |
| 92 | + (lib.optionalString cfg.mounts.mountHome '' |
| 93 | + mkdir -p $targetRoot/home/ |
| 94 | + mount -t 9p home $targetRoot/home/ -o trans=virtio,version=9p2000.L,cache=${cfg.mounts.cache},msize=${toString config.virtualisation.msize} |
| 95 | + '') + |
| 96 | + (lib.optionalString (user != "" && cfg.mounts.mountNixProfile) '' |
| 97 | + mkdir -p $targetRoot/nix/var/nix/profiles/per-user/${user}/profile/ |
| 98 | + mount -t 9p nixprofile $targetRoot/nix/var/nix/profiles/per-user/${user}/profile/ -o trans=virtio,version=9p2000.L,cache=${cfg.mounts.cache},msize=${toString config.virtualisation.msize} |
| 99 | + '') + |
| 100 | + builtins.concatStringsSep " " (lib.mapAttrsToList |
| 101 | + (target: mount: '' |
| 102 | + mkdir -p $targetRoot/${target} |
| 103 | + mount -t 9p ${mount.tag} $targetRoot/${target} -o trans=virtio,version=9p2000.L,cache=${mount.cache},msize=${toString config.virtualisation.msize} |
| 104 | + '') |
| 105 | + cfg.mounts.extraMounts); |
| 106 | + |
| 107 | + environment = { |
| 108 | + systemPackages = with pkgs; [ |
| 109 | + xterm # for resize command |
| 110 | + ]; |
| 111 | + |
| 112 | + loginShellInit = |
| 113 | + let |
| 114 | + pwd = builtins.getEnv "PWD"; |
| 115 | + term = builtins.getEnv "TERM"; |
| 116 | + path = builtins.getEnv "PATH"; |
| 117 | + in |
| 118 | + '' |
| 119 | + # fix terminal size |
| 120 | + eval "$(resize)" |
| 121 | +
|
| 122 | + ${lib.optionalString (pwd != "") "cd '${pwd}' 2>/dev/null"} |
| 123 | + ${lib.optionalString (term != "") "export TERM='${term}'"} |
| 124 | + ${lib.optionalString (path != "") "export PATH=\"${path}:$PATH\""} |
| 125 | + ''; |
| 126 | + }; |
| 127 | + |
| 128 | + networking.firewall.enable = mkVMDefault false; |
| 129 | + } |
| 130 | + ]; |
| 131 | +} |
0 commit comments