at master 6.2 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".source = 79 let 80 packageConfig = "${cfg.package}/etc/vmware/config"; 81 in 82 if cfg.extraConfig == "" then 83 packageConfig 84 else 85 pkgs.runCommandLocal "etc-vmware-config" 86 { 87 inherit packageConfig; 88 inherit (cfg) extraConfig; 89 } 90 '' 91 ( 92 cat "$packageConfig" 93 printf "\n" 94 echo "$extraConfig" 95 ) >"$out" 96 ''; 97 98 environment.etc."vmware/bootstrap".source = "${cfg.package}/etc/vmware/bootstrap"; 99 environment.etc."vmware/icu".source = "${cfg.package}/etc/vmware/icu"; 100 environment.etc."vmware-installer".source = "${cfg.package}/etc/vmware-installer"; 101 102 # SUID wrappers 103 104 security.wrappers = { 105 vmware-vmx = { 106 setuid = true; 107 owner = "root"; 108 group = "root"; 109 source = "${cfg.package}/lib/vmware/bin/.vmware-vmx-wrapped"; 110 }; 111 }; 112 113 # Services 114 115 systemd.services."vmware-wrappers" = { 116 description = "Create VMVare Wrappers"; 117 wantedBy = [ "multi-user.target" ]; 118 before = [ 119 "vmware-authdlauncher.service" 120 "vmware-networks-configuration.service" 121 "vmware-networks.service" 122 "vmware-usbarbitrator.service" 123 ]; 124 after = [ "systemd-sysusers.service" ]; 125 serviceConfig.Type = "oneshot"; 126 serviceConfig.RemainAfterExit = true; 127 script = '' 128 mkdir -p "${parentWrapperDir}" 129 chmod 755 "${parentWrapperDir}" 130 # We want to place the tmpdirs for the wrappers to the parent dir. 131 wrapperDir=$(mktemp --directory --tmpdir="${parentWrapperDir}" wrappers.XXXXXXXXXX) 132 chmod a+rx "$wrapperDir" 133 ${lib.concatStringsSep "\n" (vmwareWrappers)} 134 if [ -L ${wrapperDir} ]; then 135 # Atomically replace the symlink 136 # See https://axialcorps.com/2013/07/03/atomically-replacing-files-and-directories/ 137 old=$(readlink -f ${wrapperDir}) 138 if [ -e "${wrapperDir}-tmp" ]; then 139 rm --force --recursive "${wrapperDir}-tmp" 140 fi 141 ln --symbolic --force --no-dereference "$wrapperDir" "${wrapperDir}-tmp" 142 mv --no-target-directory "${wrapperDir}-tmp" "${wrapperDir}" 143 rm --force --recursive "$old" 144 else 145 # For initial setup 146 ln --symbolic "$wrapperDir" "${wrapperDir}" 147 fi 148 ''; 149 }; 150 151 systemd.services."vmware-authdlauncher" = { 152 description = "VMware Authentication Daemon"; 153 serviceConfig = { 154 Type = "forking"; 155 ExecStart = [ "${cfg.package}/bin/vmware-authdlauncher" ]; 156 }; 157 wantedBy = [ "multi-user.target" ]; 158 }; 159 160 systemd.services."vmware-networks-configuration" = { 161 description = "VMware Networks Configuration Generation"; 162 unitConfig.ConditionPathExists = "!/etc/vmware/networking"; 163 serviceConfig = { 164 UMask = "0077"; 165 ExecStart = [ 166 "${cfg.package}/bin/vmware-networks --postinstall vmware-player,0,1" 167 ]; 168 Type = "oneshot"; 169 RemainAfterExit = "yes"; 170 }; 171 wantedBy = [ "multi-user.target" ]; 172 }; 173 174 systemd.services."vmware-networks" = { 175 description = "VMware Networks"; 176 after = [ "vmware-networks-configuration.service" ]; 177 requires = [ "vmware-networks-configuration.service" ]; 178 serviceConfig = { 179 Type = "forking"; 180 ExecCondition = [ "${pkgs.kmod}/bin/modprobe vmnet" ]; 181 ExecStart = [ "${cfg.package}/bin/vmware-networks --start" ]; 182 ExecStop = [ "${cfg.package}/bin/vmware-networks --stop" ]; 183 }; 184 wantedBy = [ "multi-user.target" ]; 185 }; 186 187 systemd.services."vmware-usbarbitrator" = { 188 description = "VMware USB Arbitrator"; 189 serviceConfig = { 190 ExecStart = [ "${cfg.package}/bin/vmware-usbarbitrator -f" ]; 191 }; 192 wantedBy = [ "multi-user.target" ]; 193 }; 194 }; 195}