at 18.03-beta 6.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.virtualisation.libvirtd; 8 vswitch = config.virtualisation.vswitch; 9 configFile = pkgs.writeText "libvirtd.conf" '' 10 unix_sock_group = "libvirtd" 11 unix_sock_rw_perms = "0770" 12 auth_unix_ro = "none" 13 auth_unix_rw = "none" 14 ${cfg.extraConfig} 15 ''; 16 qemuConfigFile = pkgs.writeText "qemu.conf" '' 17 ${optionalString cfg.qemuOvmf '' 18 nvram = ["/run/libvirt/nix-ovmf/OVMF_CODE.fd:/run/libvirt/nix-ovmf/OVMF_VARS.fd"] 19 ''} 20 ${cfg.qemuVerbatimConfig} 21 ''; 22 23in { 24 25 ###### interface 26 27 options = { 28 29 virtualisation.libvirtd.enable = mkOption { 30 type = types.bool; 31 default = false; 32 description = '' 33 This option enables libvirtd, a daemon that manages 34 virtual machines. Users in the "libvirtd" group can interact with 35 the daemon (e.g. to start or stop VMs) using the 36 <command>virsh</command> command line tool, among others. 37 ''; 38 }; 39 40 virtualisation.libvirtd.qemuPackage = mkOption { 41 type = types.package; 42 default = pkgs.qemu; 43 description = '' 44 Qemu package to use with libvirt. 45 `pkgs.qemu` can emulate alien architectures (e.g. aarch64 on x86) 46 `pkgs.qemu_kvm` saves disk space allowing to emulate only host architectures. 47 ''; 48 }; 49 50 virtualisation.libvirtd.extraConfig = mkOption { 51 type = types.lines; 52 default = ""; 53 description = '' 54 Extra contents appended to the libvirtd configuration file, 55 libvirtd.conf. 56 ''; 57 }; 58 59 virtualisation.libvirtd.qemuVerbatimConfig = mkOption { 60 type = types.lines; 61 default = '' 62 namespaces = [] 63 ''; 64 description = '' 65 Contents written to the qemu configuration file, qemu.conf. 66 Make sure to include a proper namespace configuration when 67 supplying custom configuration. 68 ''; 69 }; 70 71 virtualisation.libvirtd.qemuOvmf = mkOption { 72 type = types.bool; 73 default = true; 74 description = '' 75 Allows libvirtd to take advantage of OVMF when creating new 76 QEMU VMs with UEFI boot. 77 ''; 78 }; 79 80 virtualisation.libvirtd.extraOptions = mkOption { 81 type = types.listOf types.str; 82 default = [ ]; 83 example = [ "--verbose" ]; 84 description = '' 85 Extra command line arguments passed to libvirtd on startup. 86 ''; 87 }; 88 89 virtualisation.libvirtd.onShutdown = mkOption { 90 type = types.enum ["shutdown" "suspend" ]; 91 default = "suspend"; 92 description = '' 93 When shutting down / restarting the host what method should 94 be used to gracefully halt the guests. Setting to "shutdown" 95 will cause an ACPI shutdown of each guest. "suspend" will 96 attempt to save the state of the guests ready to restore on boot. 97 ''; 98 }; 99 100 }; 101 102 103 ###### implementation 104 105 config = mkIf cfg.enable { 106 107 environment.systemPackages = with pkgs; [ libvirt netcat-openbsd cfg.qemuPackage ]; 108 109 boot.kernelModules = [ "tun" ]; 110 111 users.extraGroups.libvirtd.gid = config.ids.gids.libvirtd; 112 113 systemd.packages = [ pkgs.libvirt ]; 114 115 systemd.services.libvirtd = { 116 description = "Libvirt Virtual Machine Management Daemon"; 117 118 wantedBy = [ "multi-user.target" ]; 119 after = [ "systemd-udev-settle.service" ] 120 ++ optional vswitch.enable "vswitchd.service"; 121 122 environment = { 123 LIBVIRTD_ARGS = ''--config "${configFile}" ${concatStringsSep " " cfg.extraOptions}''; 124 }; 125 126 path = with pkgs; [ 127 bridge-utils 128 dmidecode 129 dnsmasq 130 ebtables 131 cfg.qemuPackage # libvirtd requires qemu-img to manage disk images 132 ] 133 ++ optional vswitch.enable vswitch.package; 134 135 preStart = '' 136 mkdir -p /var/log/libvirt/qemu -m 755 137 rm -f /var/run/libvirtd.pid 138 139 mkdir -p /var/lib/libvirt 140 mkdir -p /var/lib/libvirt/dnsmasq 141 142 chmod 755 /var/lib/libvirt 143 chmod 755 /var/lib/libvirt/dnsmasq 144 145 # Copy default libvirt network config .xml files to /var/lib 146 # Files modified by the user will not be overwritten 147 for i in $(cd ${pkgs.libvirt}/var/lib && echo \ 148 libvirt/qemu/networks/*.xml libvirt/qemu/networks/autostart/*.xml \ 149 libvirt/nwfilter/*.xml ); 150 do 151 mkdir -p /var/lib/$(dirname $i) -m 755 152 cp -npd ${pkgs.libvirt}/var/lib/$i /var/lib/$i 153 done 154 155 # Copy generated qemu config to libvirt directory 156 cp -f ${qemuConfigFile} /var/lib/libvirt/qemu.conf 157 158 # stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs 159 mkdir -p /run/libvirt/nix-emulators 160 for emulator in ${pkgs.libvirt}/libexec/libvirt_lxc ${cfg.qemuPackage}/bin/qemu-kvm ${cfg.qemuPackage}/bin/qemu-system-*; do 161 ln -s --force "$emulator" /run/libvirt/nix-emulators/ 162 done 163 164 ${optionalString cfg.qemuOvmf '' 165 mkdir -p /run/libvirt/nix-ovmf 166 ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_CODE.fd /run/libvirt/nix-ovmf/ 167 ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd /run/libvirt/nix-ovmf/ 168 ''} 169 ''; 170 171 serviceConfig = { 172 Type = "notify"; 173 KillMode = "process"; # when stopping, leave the VMs alone 174 Restart = "no"; 175 }; 176 restartIfChanged = false; 177 }; 178 179 systemd.services.libvirt-guests = { 180 wantedBy = [ "multi-user.target" ]; 181 path = with pkgs; [ coreutils libvirt gawk ]; 182 restartIfChanged = false; 183 }; 184 185 systemd.sockets.virtlogd = { 186 description = "Virtual machine log manager socket"; 187 wantedBy = [ "sockets.target" ]; 188 listenStreams = [ "/run/libvirt/virtlogd-sock" ]; 189 }; 190 191 systemd.services.virtlogd = { 192 description = "Virtual machine log manager"; 193 serviceConfig.ExecStart = "@${pkgs.libvirt}/sbin/virtlogd virtlogd"; 194 restartIfChanged = false; 195 }; 196 197 systemd.sockets.virtlockd = { 198 description = "Virtual machine lock manager socket"; 199 wantedBy = [ "sockets.target" ]; 200 listenStreams = [ "/run/libvirt/virtlockd-sock" ]; 201 }; 202 203 systemd.services.virtlockd = { 204 description = "Virtual machine lock manager"; 205 serviceConfig.ExecStart = "@${pkgs.libvirt}/sbin/virtlockd virtlockd"; 206 restartIfChanged = false; 207 }; 208 }; 209}