at 25.11-pre 4.6 kB view raw
1# Module for VirtualBox guests. 2{ 3 config, 4 lib, 5 pkgs, 6 ... 7}: 8let 9 cfg = config.virtualisation.virtualbox.guest; 10 kernel = config.boot.kernelPackages; 11 12 mkVirtualBoxUserService = serviceArgs: verbose: { 13 description = "VirtualBox Guest User Services ${serviceArgs}"; 14 15 wantedBy = [ "graphical-session.target" ]; 16 partOf = [ "graphical-session.target" ]; 17 18 # The graphical session may not be ready when starting the service 19 # Hence, check if the DISPLAY env var is set, otherwise fail, wait and retry again 20 startLimitBurst = 20; 21 22 unitConfig.ConditionVirtualization = "oracle"; 23 24 # Check if the display environment is ready, otherwise fail 25 preStart = "${pkgs.bash}/bin/bash -c \"if [ -z $DISPLAY ]; then exit 1; fi\""; 26 serviceConfig = { 27 ExecStart = 28 "@${kernel.virtualboxGuestAdditions}/bin/VBoxClient" 29 + (lib.strings.optionalString verbose " --verbose") 30 + " --foreground ${serviceArgs}"; 31 # Wait after a failure, hoping that the display environment is ready after waiting 32 RestartSec = 2; 33 Restart = "always"; 34 }; 35 }; 36 37 mkVirtualBoxUserX11OnlyService = 38 serviceArgs: verbose: 39 (mkVirtualBoxUserService serviceArgs verbose) 40 // { 41 unitConfig.ConditionEnvironment = "XDG_SESSION_TYPE=x11"; 42 }; 43in 44{ 45 imports = [ 46 (lib.mkRenamedOptionModule 47 [ 48 "virtualisation" 49 "virtualbox" 50 "guest" 51 "draganddrop" 52 ] 53 [ 54 "virtualisation" 55 "virtualbox" 56 "guest" 57 "dragAndDrop" 58 ] 59 ) 60 ]; 61 62 options.virtualisation.virtualbox.guest = { 63 enable = lib.mkOption { 64 default = false; 65 type = lib.types.bool; 66 description = "Whether to enable the VirtualBox service and other guest additions."; 67 }; 68 69 clipboard = lib.mkOption { 70 default = true; 71 type = lib.types.bool; 72 description = "Whether to enable clipboard support."; 73 }; 74 75 seamless = lib.mkOption { 76 default = true; 77 type = lib.types.bool; 78 description = "Whether to enable seamless mode. When activated windows from the guest appear next to the windows of the host."; 79 }; 80 81 dragAndDrop = lib.mkOption { 82 default = true; 83 type = lib.types.bool; 84 description = "Whether to enable drag and drop support."; 85 }; 86 87 verbose = lib.mkOption { 88 default = false; 89 type = lib.types.bool; 90 description = "Whether to verbose logging for guest services."; 91 }; 92 93 vboxsf = lib.mkOption { 94 default = true; 95 type = lib.types.bool; 96 description = "Whether to load vboxsf"; 97 }; 98 }; 99 100 ###### implementation 101 102 config = lib.mkIf cfg.enable ( 103 lib.mkMerge [ 104 { 105 assertions = [ 106 { 107 assertion = pkgs.stdenv.hostPlatform.isx86; 108 message = "Virtualbox not currently supported on ${pkgs.stdenv.hostPlatform.system}"; 109 } 110 ]; 111 112 environment.systemPackages = [ kernel.virtualboxGuestAdditions ]; 113 114 boot.extraModulePackages = [ kernel.virtualboxGuestAdditions ]; 115 116 systemd.services.virtualbox = { 117 description = "VirtualBox Guest Services"; 118 119 wantedBy = [ "multi-user.target" ]; 120 requires = [ "dev-vboxguest.device" ]; 121 after = [ "dev-vboxguest.device" ]; 122 123 unitConfig.ConditionVirtualization = "oracle"; 124 125 serviceConfig.ExecStart = "@${kernel.virtualboxGuestAdditions}/bin/VBoxService VBoxService --foreground"; 126 }; 127 128 services.udev.extraRules = '' 129 # /dev/vboxuser is necessary for VBoxClient to work. Maybe we 130 # should restrict this to logged-in users. 131 KERNEL=="vboxuser", OWNER="root", GROUP="root", MODE="0666" 132 133 # Allow systemd dependencies on vboxguest. 134 SUBSYSTEM=="misc", KERNEL=="vboxguest", TAG+="systemd" 135 ''; 136 137 systemd.user.services.virtualboxClientVmsvga = mkVirtualBoxUserService "--vmsvga-session" cfg.verbose; 138 } 139 (lib.mkIf cfg.vboxsf { 140 boot.supportedFilesystems = [ "vboxsf" ]; 141 boot.initrd.supportedFilesystems = [ "vboxsf" ]; 142 143 users.groups.vboxsf.gid = config.ids.gids.vboxsf; 144 }) 145 (lib.mkIf cfg.clipboard { 146 systemd.user.services.virtualboxClientClipboard = mkVirtualBoxUserService "--clipboard" cfg.verbose; 147 }) 148 (lib.mkIf cfg.seamless { 149 systemd.user.services.virtualboxClientSeamless = mkVirtualBoxUserX11OnlyService "--seamless" cfg.verbose; 150 }) 151 (lib.mkIf cfg.dragAndDrop { 152 systemd.user.services.virtualboxClientDragAndDrop = mkVirtualBoxUserService "--draganddrop" cfg.verbose; 153 }) 154 ] 155 ); 156}