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