at 25.11-pre 5.8 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7 8let 9 cfg = config.virtualisation.vmware.host; 10 wrapperDir = "/run/vmware/bin"; # Perfectly fits as /usr/local/bin 11 parentWrapperDir = dirOf wrapperDir; 12 vmwareWrappers = # Needed as hardcoded paths workaround 13 let 14 mkVmwareSymlink = program: '' 15 ln -s "${config.security.wrapperDir}/${program}" $wrapperDir/${program} 16 ''; 17 in 18 [ 19 (mkVmwareSymlink "pkexec") 20 (mkVmwareSymlink "mount") 21 (mkVmwareSymlink "umount") 22 ]; 23in 24{ 25 options = with lib; { 26 virtualisation.vmware.host = { 27 enable = mkEnableOption "VMware" // { 28 description = '' 29 This enables VMware host virtualisation for running VMs. 30 31 ::: {.important} 32 `vmware-vmx` will cause kcompactd0 due to 33 `Transparent Hugepages` feature in kernel. 34 Apply `[ "transparent_hugepage=never" ]` in 35 option {option}`boot.kernelParams` to disable them. 36 ::: 37 38 ::: {.note} 39 If that didn't work disable `TRANSPARENT_HUGEPAGE`, 40 `COMPACTION` configs and recompile kernel. 41 ::: 42 ''; 43 }; 44 package = mkPackageOption pkgs "vmware-workstation" { }; 45 extraPackages = mkOption { 46 type = with types; listOf package; 47 default = with pkgs; [ ]; 48 description = "Extra packages to be used with VMware host."; 49 example = "with pkgs; [ ntfs3g ]"; 50 }; 51 extraConfig = mkOption { 52 type = types.lines; 53 default = ""; 54 description = "Add extra config to /etc/vmware/config"; 55 example = '' 56 # Allow unsupported device's OpenGL and Vulkan acceleration for guest vGPU 57 mks.gl.allowUnsupportedDrivers = "TRUE" 58 mks.vk.allowUnsupportedDevices = "TRUE" 59 ''; 60 }; 61 }; 62 }; 63 64 config = lib.mkIf cfg.enable { 65 boot.extraModulePackages = [ config.boot.kernelPackages.vmware ]; 66 boot.extraModprobeConfig = "alias char-major-10-229 fuse"; 67 boot.kernelModules = [ 68 "vmw_pvscsi" 69 "vmw_vmci" 70 "vmmon" 71 "vmnet" 72 "fuse" 73 ]; 74 75 environment.systemPackages = [ cfg.package ] ++ cfg.extraPackages; 76 services.printing.drivers = [ cfg.package ]; 77 78 environment.etc."vmware/config".text = '' 79 ${builtins.readFile "${cfg.package}/etc/vmware/config"} 80 ${cfg.extraConfig} 81 ''; 82 83 environment.etc."vmware/bootstrap".source = "${cfg.package}/etc/vmware/bootstrap"; 84 environment.etc."vmware/icu".source = "${cfg.package}/etc/vmware/icu"; 85 environment.etc."vmware-installer".source = "${cfg.package}/etc/vmware-installer"; 86 87 # SUID wrappers 88 89 security.wrappers = { 90 vmware-vmx = { 91 setuid = true; 92 owner = "root"; 93 group = "root"; 94 source = "${cfg.package}/lib/vmware/bin/.vmware-vmx-wrapped"; 95 }; 96 }; 97 98 # Services 99 100 systemd.services."vmware-wrappers" = { 101 description = "Create VMVare Wrappers"; 102 wantedBy = [ "multi-user.target" ]; 103 before = [ 104 "vmware-authdlauncher.service" 105 "vmware-networks-configuration.service" 106 "vmware-networks.service" 107 "vmware-usbarbitrator.service" 108 ]; 109 after = [ "systemd-sysusers.service" ]; 110 serviceConfig.Type = "oneshot"; 111 serviceConfig.RemainAfterExit = true; 112 script = '' 113 mkdir -p "${parentWrapperDir}" 114 chmod 755 "${parentWrapperDir}" 115 # We want to place the tmpdirs for the wrappers to the parent dir. 116 wrapperDir=$(mktemp --directory --tmpdir="${parentWrapperDir}" wrappers.XXXXXXXXXX) 117 chmod a+rx "$wrapperDir" 118 ${lib.concatStringsSep "\n" (vmwareWrappers)} 119 if [ -L ${wrapperDir} ]; then 120 # Atomically replace the symlink 121 # See https://axialcorps.com/2013/07/03/atomically-replacing-files-and-directories/ 122 old=$(readlink -f ${wrapperDir}) 123 if [ -e "${wrapperDir}-tmp" ]; then 124 rm --force --recursive "${wrapperDir}-tmp" 125 fi 126 ln --symbolic --force --no-dereference "$wrapperDir" "${wrapperDir}-tmp" 127 mv --no-target-directory "${wrapperDir}-tmp" "${wrapperDir}" 128 rm --force --recursive "$old" 129 else 130 # For initial setup 131 ln --symbolic "$wrapperDir" "${wrapperDir}" 132 fi 133 ''; 134 }; 135 136 systemd.services."vmware-authdlauncher" = { 137 description = "VMware Authentication Daemon"; 138 serviceConfig = { 139 Type = "forking"; 140 ExecStart = [ "${cfg.package}/bin/vmware-authdlauncher" ]; 141 }; 142 wantedBy = [ "multi-user.target" ]; 143 }; 144 145 systemd.services."vmware-networks-configuration" = { 146 description = "VMware Networks Configuration Generation"; 147 unitConfig.ConditionPathExists = "!/etc/vmware/networking"; 148 serviceConfig = { 149 UMask = "0077"; 150 ExecStart = [ 151 "${cfg.package}/bin/vmware-networks --postinstall vmware-player,0,1" 152 ]; 153 Type = "oneshot"; 154 RemainAfterExit = "yes"; 155 }; 156 wantedBy = [ "multi-user.target" ]; 157 }; 158 159 systemd.services."vmware-networks" = { 160 description = "VMware Networks"; 161 after = [ "vmware-networks-configuration.service" ]; 162 requires = [ "vmware-networks-configuration.service" ]; 163 serviceConfig = { 164 Type = "forking"; 165 ExecCondition = [ "${pkgs.kmod}/bin/modprobe vmnet" ]; 166 ExecStart = [ "${cfg.package}/bin/vmware-networks --start" ]; 167 ExecStop = [ "${cfg.package}/bin/vmware-networks --stop" ]; 168 }; 169 wantedBy = [ "multi-user.target" ]; 170 }; 171 172 systemd.services."vmware-usbarbitrator" = { 173 description = "VMware USB Arbitrator"; 174 serviceConfig = { 175 ExecStart = [ "${cfg.package}/bin/vmware-usbarbitrator -f" ]; 176 }; 177 wantedBy = [ "multi-user.target" ]; 178 }; 179 }; 180}