xeus-cling: fix improper linking with LLVM (#351130)
[NixPkgs.git] / nixos / modules / virtualisation / virtualbox-host.nix
blob29e2d4340f3c2a43807b611a713cab729d3b9912
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
8   cfg = config.virtualisation.virtualbox.host;
10   virtualbox = cfg.package.override {
11     inherit (cfg)
12       enableHardening
13       headless
14       enableWebService
15       enableKvm
16       ;
17     extensionPack = if cfg.enableExtensionPack then pkgs.virtualboxExtpack else null;
18   };
20   kernelModules = config.boot.kernelPackages.virtualbox.override {
21     inherit virtualbox;
22   };
27   options.virtualisation.virtualbox.host = {
28     enable = lib.mkEnableOption "VirtualBox" // {
29       description = ''
30         Whether to enable VirtualBox.
32         ::: {.note}
33         In order to pass USB devices from the host to the guests, the user
34         needs to be in the `vboxusers` group.
35         :::
36       '';
37     };
39     enableExtensionPack = lib.mkEnableOption "VirtualBox extension pack" // {
40       description = ''
41         Whether to install the Oracle Extension Pack for VirtualBox.
43         ::: {.important}
44         You must set `nixpkgs.config.allowUnfree = true` in
45         order to use this.  This requires you accept the VirtualBox PUEL.
46         :::
47       '';
48     };
50     package = lib.mkPackageOption pkgs "virtualbox" { };
52     addNetworkInterface = lib.mkOption {
53       type = lib.types.bool;
54       default = true;
55       description = ''
56         Automatically set up a vboxnet0 host-only network interface.
57       '';
58     };
60     enableHardening = lib.mkOption {
61       type = lib.types.bool;
62       default = true;
63       description = ''
64         Enable hardened VirtualBox, which ensures that only the binaries in the
65         system path get access to the devices exposed by the kernel modules
66         instead of all users in the vboxusers group.
68         ::: {.important}
69         Disabling this can put your system's security at risk, as local users
70         in the vboxusers group can tamper with the VirtualBox device files.
71         :::
72       '';
73     };
75     headless = lib.mkOption {
76       type = lib.types.bool;
77       default = false;
78       description = ''
79         Use VirtualBox installation without GUI and Qt dependency. Useful to enable on servers
80         and when virtual machines are controlled only via SSH.
81       '';
82     };
84     enableWebService = lib.mkOption {
85       type = lib.types.bool;
86       default = false;
87       description = ''
88         Build VirtualBox web service tool (vboxwebsrv) to allow managing VMs via other webpage frontend tools. Useful for headless servers.
89       '';
90     };
92     enableKvm = lib.mkOption {
93       type = lib.types.bool;
94       default = false;
95       description = ''
96         Enable KVM support for VirtualBox. This increases compatibility with Linux kernel versions, because the VirtualBox kernel modules
97         are not required.
99         This option is incompatible with `addNetworkInterface`.
101         Note: This is experimental. Please check https://github.com/cyberus-technology/virtualbox-kvm/issues.
102       '';
103     };
104   };
106   config = lib.mkIf cfg.enable (
107     lib.mkMerge [
108       {
109         warnings = lib.mkIf (pkgs.config.virtualbox.enableExtensionPack or false) [
110           "'nixpkgs.virtualbox.enableExtensionPack' has no effect, please use 'virtualisation.virtualbox.host.enableExtensionPack'"
111         ];
112         environment.systemPackages = [ virtualbox ];
114         security.wrappers =
115           let
116             mkSuid = program: {
117               source = "${virtualbox}/libexec/virtualbox/${program}";
118               owner = "root";
119               group = "vboxusers";
120               setuid = true;
121             };
122             executables =
123               [
124                 "VBoxHeadless"
125                 "VBoxNetAdpCtl"
126                 "VBoxNetDHCP"
127                 "VBoxNetNAT"
128                 "VBoxVolInfo"
129               ]
130               ++ (lib.optionals (!cfg.headless) [
131                 "VBoxSDL"
132                 "VirtualBoxVM"
133               ]);
134           in
135           lib.mkIf cfg.enableHardening (
136             builtins.listToAttrs (
137               map (x: {
138                 name = x;
139                 value = mkSuid x;
140               }) executables
141             )
142           );
144         users.groups.vboxusers.gid = config.ids.gids.vboxusers;
146         services.udev.extraRules = ''
147           SUBSYSTEM=="usb_device", ACTION=="add", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
148           SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh $major $minor $attr{bDeviceClass}"
149           SUBSYSTEM=="usb_device", ACTION=="remove", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
150           SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="${virtualbox}/libexec/virtualbox/VBoxCreateUSBNode.sh --remove $major $minor"
151         '';
152       }
153       (lib.mkIf cfg.enableKvm {
154         assertions = [
155           {
156             assertion = !cfg.addNetworkInterface;
157             message = "VirtualBox KVM only supports standard NAT networking for VMs. Please turn off virtualisation.virtualbox.host.addNetworkInterface.";
158           }
159         ];
160       })
161       (lib.mkIf (!cfg.enableKvm) {
162         boot.kernelModules = [
163           "vboxdrv"
164           "vboxnetadp"
165           "vboxnetflt"
166         ];
167         boot.extraModulePackages = [ kernelModules ];
169         services.udev.extraRules = ''
170           KERNEL=="vboxdrv",    OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
171           KERNEL=="vboxdrvu",   OWNER="root", GROUP="root",      MODE="0666", TAG+="systemd"
172           KERNEL=="vboxnetctl", OWNER="root", GROUP="vboxusers", MODE="0660", TAG+="systemd"
173         '';
175         # Since we lack the right setuid/setcap binaries, set up a host-only network by default.
176       })
177       (lib.mkIf cfg.addNetworkInterface {
178         systemd.services.vboxnet0 = {
179           description = "VirtualBox vboxnet0 Interface";
180           requires = [ "dev-vboxnetctl.device" ];
181           after = [ "dev-vboxnetctl.device" ];
182           wantedBy = [
183             "network.target"
184             "sys-subsystem-net-devices-vboxnet0.device"
185           ];
186           path = [ virtualbox ];
187           serviceConfig.RemainAfterExit = true;
188           serviceConfig.Type = "oneshot";
189           serviceConfig.PrivateTmp = true;
190           environment.VBOX_USER_HOME = "/tmp";
191           script = ''
192             if ! [ -e /sys/class/net/vboxnet0 ]; then
193               VBoxManage hostonlyif create
194               cat /tmp/VBoxSVC.log >&2
195             fi
196           '';
197           postStop = ''
198             VBoxManage hostonlyif remove vboxnet0
199           '';
200         };
202         networking.interfaces.vboxnet0.ipv4.addresses = [
203           {
204             address = "192.168.56.1";
205             prefixLength = 24;
206           }
207         ];
208         # Make sure NetworkManager won't assume this interface being up
209         # means we have internet access.
210         networking.networkmanager.unmanaged = [ "vboxnet0" ];
211       })
212       (lib.mkIf config.networking.useNetworkd {
213         systemd.network.networks."40-vboxnet0".extraConfig = ''
214           [Link]
215           RequiredForOnline=no
216         '';
217       })
219     ]
220   );