diff options
Diffstat (limited to 'nixos/modules/virtualisation')
19 files changed, 638 insertions, 161 deletions
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 9015200beead..d67790702f1f 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -8,7 +8,13 @@ with lib; -let cfg = config.ec2; in +let + cfg = config.ec2; + metadataFetcher = import ./ec2-metadata-fetcher.nix { + targetRoot = "$targetRoot/"; + wgetExtraOptions = "-q"; + }; +in { imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-init.nix ]; @@ -25,6 +31,7 @@ let cfg = config.ec2; in fileSystems."/" = { device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; autoResize = true; }; @@ -61,26 +68,7 @@ let cfg = config.ec2; in # Nix operations. boot.initrd.postMountCommands = '' - metaDir=$targetRoot/etc/ec2-metadata - mkdir -m 0755 -p "$metaDir" - - echo "getting EC2 instance metadata..." - - if ! [ -e "$metaDir/ami-manifest-path" ]; then - wget -q -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path - fi - - if ! [ -e "$metaDir/user-data" ]; then - wget -q -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" - fi - - if ! [ -e "$metaDir/hostname" ]; then - wget -q -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname - fi - - if ! [ -e "$metaDir/public-keys-0-openssh-key" ]; then - wget -q -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key - fi + ${metadataFetcher} diskNr=0 diskForUnionfs= diff --git a/nixos/modules/virtualisation/anbox.nix b/nixos/modules/virtualisation/anbox.nix new file mode 100644 index 000000000000..c63b971ead02 --- /dev/null +++ b/nixos/modules/virtualisation/anbox.nix @@ -0,0 +1,139 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.virtualisation.anbox; + kernelPackages = config.boot.kernelPackages; + addrOpts = v: addr: pref: name: { + address = mkOption { + default = addr; + type = types.str; + description = '' + IPv${toString v} ${name} address. + ''; + }; + + prefixLength = mkOption { + default = pref; + type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128)); + description = '' + Subnet mask of the ${name} address, specified as the number of + bits in the prefix (<literal>${if v == 4 then "24" else "64"}</literal>). + ''; + }; + }; + +in + +{ + + options.virtualisation.anbox = { + + enable = mkEnableOption "Anbox"; + + image = mkOption { + default = pkgs.anbox.image; + example = literalExample "pkgs.anbox.image"; + type = types.package; + description = '' + Base android image for Anbox. + ''; + }; + + extraInit = mkOption { + type = types.lines; + default = ""; + description = '' + Extra shell commands to be run inside the container image during init. + ''; + }; + + ipv4 = { + container = addrOpts 4 "192.168.250.2" 24 "Container"; + gateway = addrOpts 4 "192.168.250.1" 24 "Host"; + + dns = mkOption { + default = "1.1.1.1"; + type = types.string; + description = '' + Container DNS server. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + + assertions = singleton { + assertion = versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.18"; + message = "Anbox needs user namespace support to work properly"; + }; + + environment.systemPackages = with pkgs; [ anbox ]; + + boot.kernelModules = [ "ashmem_linux" "binder_linux" ]; + boot.extraModulePackages = [ kernelPackages.anbox ]; + + services.udev.extraRules = '' + KERNEL=="ashmem", NAME="%k", MODE="0666" + KERNEL=="binder*", NAME="%k", MODE="0666" + ''; + + virtualisation.lxc.enable = true; + networking.bridges.anbox0.interfaces = []; + networking.interfaces.anbox0.ipv4.addresses = [ cfg.ipv4.gateway ]; + + networking.nat = { + enable = true; + internalInterfaces = [ "anbox0" ]; + }; + + systemd.services.anbox-container-manager = let + anboxloc = "/var/lib/anbox"; + in { + description = "Anbox Container Management Daemon"; + + environment.XDG_RUNTIME_DIR="${anboxloc}"; + + wantedBy = [ "multi-user.target" ]; + after = [ "systemd-udev-settle.service" ]; + preStart = let + initsh = pkgs.writeText "nixos-init" ('' + #!/system/bin/sh + setprop nixos.version ${config.system.nixos.version} + + # we don't have radio + setprop ro.radio.noril yes + stop ril-daemon + + # speed up boot + setprop debug.sf.nobootanimation 1 + '' + cfg.extraInit); + initshloc = "${anboxloc}/rootfs-overlay/system/etc/init.goldfish.sh"; + in '' + mkdir -p ${anboxloc} + mkdir -p $(dirname ${initshloc}) + [ -f ${initshloc} ] && rm ${initshloc} + cp ${initsh} ${initshloc} + chown 100000:100000 ${initshloc} + chmod +x ${initshloc} + ''; + + serviceConfig = { + ExecStart = '' + ${pkgs.anbox}/bin/anbox container-manager \ + --data-path=${anboxloc} \ + --android-image=${cfg.image} \ + --container-network-address=${cfg.ipv4.container.address} \ + --container-network-gateway=${cfg.ipv4.gateway.address} \ + --container-network-dns-servers=${cfg.ipv4.dns} \ + --use-rootfs-overlay \ + --privileged + ''; + }; + }; + }; + +} diff --git a/nixos/modules/virtualisation/cloudstack-config.nix b/nixos/modules/virtualisation/cloudstack-config.nix new file mode 100644 index 000000000000..78afebdc5dd3 --- /dev/null +++ b/nixos/modules/virtualisation/cloudstack-config.nix @@ -0,0 +1,40 @@ +{ lib, pkgs, ... }: + +with lib; + +{ + imports = [ + ../profiles/qemu-guest.nix + ]; + + config = { + fileSystems."/" = { + device = "/dev/disk/by-label/nixos"; + autoResize = true; + }; + + boot.growPartition = true; + boot.kernelParams = [ "console=tty0" ]; + boot.loader.grub.device = "/dev/vda"; + boot.loader.timeout = 0; + + # Allow root logins + services.openssh = { + enable = true; + permitRootLogin = "prohibit-password"; + }; + + # Cloud-init configuration. + services.cloud-init.enable = true; + # Wget is needed for setting password. This is of little use as + # root password login is disabled above. + environment.systemPackages = [ pkgs.wget ]; + # Only enable CloudStack datasource for faster boot speed. + environment.etc."cloud/cloud.cfg.d/99_cloudstack.cfg".text = '' + datasource: + CloudStack: {} + None: {} + datasource_list: ["CloudStack"] + ''; + }; +} diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix index 78c59d98a5eb..604fb8a75932 100644 --- a/nixos/modules/virtualisation/container-config.nix +++ b/nixos/modules/virtualisation/container-config.nix @@ -7,7 +7,6 @@ with lib; config = mkIf config.boot.isContainer { # Disable some features that are not useful in a container. - sound.enable = mkDefault false; services.udisks2.enable = mkDefault false; powerManagement.enable = mkDefault false; diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index 3dd36f9b12e1..c10e2b162ccc 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -36,8 +36,9 @@ let #! ${pkgs.runtimeShell} -e # Initialise the container side of the veth pair. - if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ]; then - + if [ -n "$HOST_ADDRESS" ] || [ -n "$HOST_ADDRESS6" ] || + [ -n "$LOCAL_ADDRESS" ] || [ -n "$LOCAL_ADDRESS6" ] || + [ -n "$HOST_BRIDGE" ]; then ip link set host0 name eth0 ip link set dev eth0 up @@ -88,20 +89,23 @@ let extraFlags+=" --private-network" fi - if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ]; then + if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ] || + [ -n "$HOST_ADDRESS6" ] || [ -n "$LOCAL_ADDRESS6" ]; then extraFlags+=" --network-veth" - if [ -n "$HOST_BRIDGE" ]; then - extraFlags+=" --network-bridge=$HOST_BRIDGE" - fi - if [ -n "$HOST_PORT" ]; then - OIFS=$IFS - IFS="," - for i in $HOST_PORT - do - extraFlags+=" --port=$i" - done - IFS=$OIFS - fi + fi + + if [ -n "$HOST_PORT" ]; then + OIFS=$IFS + IFS="," + for i in $HOST_PORT + do + extraFlags+=" --port=$i" + done + IFS=$OIFS + fi + + if [ -n "$HOST_BRIDGE" ]; then + extraFlags+=" --network-bridge=$HOST_BRIDGE" fi extraFlags+=" ${concatStringsSep " " (mapAttrsToList nspawnExtraVethArgs cfg.extraVeths)}" @@ -157,7 +161,8 @@ let # Clean up existing machined registration and interfaces. machinectl terminate "$INSTANCE" 2> /dev/null || true - if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ]; then + if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ] || + [ -n "$HOST_ADDRESS6" ] || [ -n "$LOCAL_ADDRESS6" ]; then ip link del dev "ve-$INSTANCE" 2> /dev/null || true ip link del dev "vb-$INSTANCE" 2> /dev/null || true fi @@ -188,6 +193,8 @@ let '' else '' + echo "Bring ${name} up" + ip link set dev ${name} up # Set IPs and routes for ${name} ${optionalString (cfg.hostAddress != null) '' ip addr add ${cfg.hostAddress} dev ${name} @@ -204,7 +211,8 @@ let ''; in '' - if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ]; then + if [ -n "$HOST_ADDRESS" ] || [ -n "$LOCAL_ADDRESS" ] || + [ -n "$HOST_ADDRESS6" ] || [ -n "$LOCAL_ADDRESS6" ]; then if [ -z "$HOST_BRIDGE" ]; then ifaceHost=ve-$INSTANCE ip link set dev $ifaceHost up @@ -437,7 +445,7 @@ in type = types.bool; default = !config.boot.isContainer; description = '' - Whether to enable support for nixos containers. + Whether to enable support for NixOS containers. ''; }; @@ -457,20 +465,24 @@ in merge = loc: defs: (import ../../lib/eval-config.nix { inherit system; modules = - let extraConfig = - { boot.isContainer = true; - networking.hostName = mkDefault name; - networking.useDHCP = false; - assertions = [ - { - assertion = config.privateNetwork -> stringLength name < 12; - message = '' - Container name `${name}` is too long: When `privateNetwork` is enabled, container names can - not be longer than 11 characters, because the container's interface name is derived from it. - This might be fixed in the future. See https://github.com/NixOS/nixpkgs/issues/38509 - ''; - } - ]; + let + extraConfig = { + _file = "module at ${__curPos.file}:${toString __curPos.line}"; + config = { + boot.isContainer = true; + networking.hostName = mkDefault name; + networking.useDHCP = false; + assertions = [ + { + assertion = config.privateNetwork -> stringLength name < 12; + message = '' + Container name `${name}` is too long: When `privateNetwork` is enabled, container names can + not be longer than 11 characters, because the container's interface name is derived from it. + This might be fixed in the future. See https://github.com/NixOS/nixpkgs/issues/38509 + ''; + } + ]; + }; }; in [ extraConfig ] ++ (map (x: x.value) defs); prefix = [ "containers" name ]; @@ -681,7 +693,7 @@ in [{ name = "container@"; value = unit; }] # declarative containers ++ (mapAttrsToList (name: cfg: nameValuePair "container@${name}" (let - config = cfg // ( + containerConfig = cfg // ( if cfg.enableTun then { allowedDevices = cfg.allowedDevices @@ -692,18 +704,21 @@ in else {}); in unit // { - preStart = preStartScript config; - script = startScript config; - postStart = postStartScript config; - serviceConfig = serviceDirectives config; + preStart = preStartScript containerConfig; + script = startScript containerConfig; + postStart = postStartScript containerConfig; + serviceConfig = serviceDirectives containerConfig; } // ( - if config.autoStart then + if containerConfig.autoStart then { wantedBy = [ "machines.target" ]; wants = [ "network.target" ]; after = [ "network.target" ]; - restartTriggers = [ config.path ]; - reloadIfChanged = true; + restartTriggers = [ + containerConfig.path + config.environment.etc."containers/${name}.conf".source + ]; + restartIfChanged = true; } else {}) )) config.containers) diff --git a/nixos/modules/virtualisation/docker-containers.nix b/nixos/modules/virtualisation/docker-containers.nix new file mode 100644 index 000000000000..59b0943f591f --- /dev/null +++ b/nixos/modules/virtualisation/docker-containers.nix @@ -0,0 +1,230 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.docker-containers; + + dockerContainer = + { ... }: { + + options = { + + image = mkOption { + type = types.str; + description = "Docker image to run."; + example = "library/hello-world"; + }; + + cmd = mkOption { + type = with types; listOf str; + default = []; + description = "Commandline arguments to pass to the image's entrypoint."; + example = literalExample '' + ["--port=9000"] + ''; + }; + + entrypoint = mkOption { + type = with types; nullOr str; + description = "Overwrite the default entrypoint of the image."; + default = null; + example = "/bin/my-app"; + }; + + environment = mkOption { + type = with types; attrsOf str; + default = {}; + description = "Environment variables to set for this container."; + example = literalExample '' + { + DATABASE_HOST = "db.example.com"; + DATABASE_PORT = "3306"; + } + ''; + }; + + log-driver = mkOption { + type = types.str; + default = "none"; + description = '' + Logging driver for the container. The default of + <literal>"none"</literal> means that the container's logs will be + handled as part of the systemd unit. Setting this to + <literal>"journald"</literal> will result in duplicate logging, but + the container's logs will be visible to the <command>docker + logs</command> command. + + For more details and a full list of logging drivers, refer to the + <link xlink:href="https://docs.docker.com/engine/reference/run/#logging-drivers---log-driver"> + Docker engine documentation</link> + ''; + }; + + ports = mkOption { + type = with types; listOf str; + default = []; + description = '' + Network ports to publish from the container to the outer host. + + Valid formats: + + <itemizedlist> + <listitem> + <para> + <literal><ip>:<hostPort>:<containerPort></literal> + </para> + </listitem> + <listitem> + <para> + <literal><ip>::<containerPort></literal> + </para> + </listitem> + <listitem> + <para> + <literal><hostPort>:<containerPort></literal> + </para> + </listitem> + <listitem> + <para> + <literal><containerPort></literal> + </para> + </listitem> + </itemizedlist> + + Both <literal>hostPort</literal> and + <literal>containerPort</literal> can be specified as a range of + ports. When specifying ranges for both, the number of container + ports in the range must match the number of host ports in the + range. Example: <literal>1234-1236:1234-1236/tcp</literal> + + When specifying a range for <literal>hostPort</literal> only, the + <literal>containerPort</literal> must <emphasis>not</emphasis> be a + range. In this case, the container port is published somewhere + within the specified <literal>hostPort</literal> range. Example: + <literal>1234-1236:1234/tcp</literal> + + Refer to the + <link xlink:href="https://docs.docker.com/engine/reference/run/#expose-incoming-ports"> + Docker engine documentation</link> for full details. + ''; + example = literalExample '' + [ + "8080:9000" + ] + ''; + }; + + user = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Override the username or UID (and optionally groupname or GID) used + in the container. + ''; + example = "nobody:nogroup"; + }; + + volumes = mkOption { + type = with types; listOf str; + default = []; + description = '' + List of volumes to attach to this container. + + Note that this is a list of <literal>"src:dst"</literal> strings to + allow for <literal>src</literal> to refer to + <literal>/nix/store</literal> paths, which would difficult with an + attribute set. There are also a variety of mount options available + as a third field; please refer to the + <link xlink:href="https://docs.docker.com/engine/reference/run/#volume-shared-filesystems"> + docker engine documentation</link> for details. + ''; + example = literalExample '' + [ + "volume_name:/path/inside/container" + "/path/on/host:/path/inside/container" + ] + ''; + }; + + workdir = mkOption { + type = with types; nullOr str; + default = null; + description = "Override the default working directory for the container."; + example = "/var/lib/hello_world"; + }; + + extraDockerOptions = mkOption { + type = with types; listOf str; + default = []; + description = "Extra options for <command>docker run</command>."; + example = literalExample '' + ["--network=host"] + ''; + }; + }; + }; + + mkService = name: container: { + wantedBy = [ "multi-user.target" ]; + after = [ "docker.service" "docker.socket" ]; + requires = [ "docker.service" "docker.socket" ]; + serviceConfig = { + ExecStart = concatStringsSep " \\\n " ([ + "${pkgs.docker}/bin/docker run" + "--rm" + "--name=%n" + "--log-driver=${container.log-driver}" + ] ++ optional (container.entrypoint != null) + "--entrypoint=${escapeShellArg container.entrypoint}" + ++ (mapAttrsToList (k: v: "-e ${escapeShellArg k}=${escapeShellArg v}") container.environment) + ++ map (p: "-p ${escapeShellArg p}") container.ports + ++ optional (container.user != null) "-u ${escapeShellArg container.user}" + ++ map (v: "-v ${escapeShellArg v}") container.volumes + ++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}" + ++ map escapeShellArg container.extraDockerOptions + ++ [container.image] + ++ map escapeShellArg container.cmd + ); + ExecStartPre = "-${pkgs.docker}/bin/docker rm -f %n"; + ExecStop = "${pkgs.docker}/bin/docker stop %n"; + ExecStopPost = "-${pkgs.docker}/bin/docker rm -f %n"; + + ### There is no generalized way of supporting `reload` for docker + ### containers. Some containers may respond well to SIGHUP sent to their + ### init process, but it is not guaranteed; some apps have other reload + ### mechanisms, some don't have a reload signal at all, and some docker + ### images just have broken signal handling. The best compromise in this + ### case is probably to leave ExecReload undefined, so `systemctl reload` + ### will at least result in an error instead of potentially undefined + ### behaviour. + ### + ### Advanced users can still override this part of the unit to implement + ### a custom reload handler, since the result of all this is a normal + ### systemd service from the perspective of the NixOS module system. + ### + # ExecReload = ...; + ### + + TimeoutStartSec = 0; + TimeoutStopSec = 120; + Restart = "always"; + }; + }; + +in { + + options.docker-containers = mkOption { + default = {}; + type = types.attrsOf (types.submodule dockerContainer); + description = "Docker containers to run as systemd services."; + }; + + config = mkIf (cfg != {}) { + + systemd.services = mapAttrs' (n: v: nameValuePair "docker-${n}" (mkService n v)) cfg; + + virtualisation.docker.enable = true; + + }; + +} diff --git a/nixos/modules/virtualisation/docker-preloader.nix b/nixos/modules/virtualisation/docker-preloader.nix index faa94f53d98f..6ab83058dee1 100644 --- a/nixos/modules/virtualisation/docker-preloader.nix +++ b/nixos/modules/virtualisation/docker-preloader.nix @@ -78,12 +78,11 @@ in }; }; - config = { + config = mkIf (cfg.dockerPreloader.images != []) { assertions = [{ # If docker.storageDriver is null, Docker choose the storage # driver. So, in this case, we cannot be sure overlay2 is used. - assertion = cfg.dockerPreloader.images == [] - || cfg.docker.storageDriver == "overlay2" + assertion = cfg.docker.storageDriver == "overlay2" || cfg.docker.storageDriver == "overlay" || cfg.docker.storageDriver == null; message = "The Docker image Preloader only works with overlay2 storage driver!"; diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix index a1a32c1c59a1..7d196a46276a 100644 --- a/nixos/modules/virtualisation/docker.nix +++ b/nixos/modules/virtualisation/docker.nix @@ -31,7 +31,7 @@ in listenOptions = mkOption { type = types.listOf types.str; - default = ["/var/run/docker.sock"]; + default = ["/run/docker.sock"]; description = '' A list of unix and tcp docker should listen to. The format follows @@ -46,12 +46,21 @@ in description = '' When enabled dockerd is started on boot. This is required for - container, which are created with the - <literal>--restart=always</literal> flag, to work. If this option is + containers which are created with the + <literal>--restart=always</literal> flag to work. If this option is disabled, docker might be started on demand by socket activation. ''; }; + enableNvidia = + mkOption { + type = types.bool; + default = false; + description = '' + Enable nvidia-docker wrapper, supporting NVIDIA GPUs inside docker containers. + ''; + }; + liveRestore = mkOption { type = types.bool; @@ -140,7 +149,8 @@ in ###### implementation config = mkIf cfg.enable (mkMerge [{ - environment.systemPackages = [ cfg.package ]; + environment.systemPackages = [ cfg.package ] + ++ optional cfg.enableNvidia pkgs.nvidia-docker; users.groups.docker.gid = config.ids.gids.docker; systemd.packages = [ cfg.package ]; @@ -157,6 +167,7 @@ in --log-driver=${cfg.logDriver} \ ${optionalString (cfg.storageDriver != null) "--storage-driver=${cfg.storageDriver}"} \ ${optionalString cfg.liveRestore "--live-restore" } \ + ${optionalString cfg.enableNvidia "--add-runtime nvidia=${pkgs.nvidia-docker}/bin/nvidia-container-runtime" } \ ${cfg.extraOptions} '']; ExecReload=[ @@ -165,7 +176,8 @@ in ]; }; - path = [ pkgs.kmod ] ++ (optional (cfg.storageDriver == "zfs") pkgs.zfs); + path = [ pkgs.kmod ] ++ optional (cfg.storageDriver == "zfs") pkgs.zfs + ++ optional cfg.enableNvidia pkgs.nvidia-docker; }; systemd.sockets.docker = { @@ -179,7 +191,6 @@ in }; }; - systemd.services.docker-prune = { description = "Prune docker resources"; @@ -194,7 +205,15 @@ in startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates; }; + + assertions = [ + { assertion = cfg.enableNvidia -> config.hardware.opengl.driSupport32Bit or false; + message = "Option enableNvidia requires 32bit support libraries"; + }]; } + (mkIf cfg.enableNvidia { + environment.etc."nvidia-container-runtime/config.toml".source = "${pkgs.nvidia-docker}/etc/config.toml"; + }) ]); imports = [ diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix index aaea06bb9a63..f640bb21b133 100644 --- a/nixos/modules/virtualisation/ec2-amis.nix +++ b/nixos/modules/virtualisation/ec2-amis.nix @@ -274,5 +274,22 @@ let self = { "18.09".sa-east-1.hvm-ebs = "ami-0e4a8a47fd6db6112"; "18.09".ap-south-1.hvm-ebs = "ami-0880a678d3f555313"; - latest = self."18.09"; + # 19.03.172286.8ea36d73256 + "19.03".eu-west-1.hvm-ebs = "ami-0fe40176548ff0940"; + "19.03".eu-west-2.hvm-ebs = "ami-03a40fd3a02fe95ba"; + "19.03".eu-west-3.hvm-ebs = "ami-0436f9da0f20a638e"; + "19.03".eu-central-1.hvm-ebs = "ami-0022b8ea9efde5de4"; + "19.03".us-east-1.hvm-ebs = "ami-0efc58fb70ae9a217"; + "19.03".us-east-2.hvm-ebs = "ami-0abf711b1b34da1af"; + "19.03".us-west-1.hvm-ebs = "ami-07d126e8838c40ec5"; + "19.03".us-west-2.hvm-ebs = "ami-03f8a737546e47fb0"; + "19.03".ca-central-1.hvm-ebs = "ami-03f9fd0ef2e035ede"; + "19.03".ap-southeast-1.hvm-ebs = "ami-0cff66114c652c262"; + "19.03".ap-southeast-2.hvm-ebs = "ami-054c73a7f8d773ea9"; + "19.03".ap-northeast-1.hvm-ebs = "ami-00db62688900456a4"; + "19.03".ap-northeast-2.hvm-ebs = "ami-0485cdd1a5fdd2117"; + "19.03".sa-east-1.hvm-ebs = "ami-0c6a43c6e0ad1f4e2"; + "19.03".ap-south-1.hvm-ebs = "ami-0303deb1b5890f878"; + + latest = self."19.03"; }; in self diff --git a/nixos/modules/virtualisation/ec2-metadata-fetcher.nix b/nixos/modules/virtualisation/ec2-metadata-fetcher.nix new file mode 100644 index 000000000000..b531787c31a2 --- /dev/null +++ b/nixos/modules/virtualisation/ec2-metadata-fetcher.nix @@ -0,0 +1,23 @@ +{ targetRoot, wgetExtraOptions }: +'' + metaDir=${targetRoot}etc/ec2-metadata + mkdir -m 0755 -p "$metaDir" + + echo "getting EC2 instance metadata..." + + if ! [ -e "$metaDir/ami-manifest-path" ]; then + wget ${wgetExtraOptions} -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path + fi + + if ! [ -e "$metaDir/user-data" ]; then + wget ${wgetExtraOptions} -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" + fi + + if ! [ -e "$metaDir/hostname" ]; then + wget ${wgetExtraOptions} -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname + fi + + if ! [ -e "$metaDir/public-keys-0-openssh-key" ]; then + wget ${wgetExtraOptions} -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key + fi +'' diff --git a/nixos/modules/virtualisation/google-compute-config.nix b/nixos/modules/virtualisation/google-compute-config.nix index 8c7331fe4d2b..5c59188b68b2 100644 --- a/nixos/modules/virtualisation/google-compute-config.nix +++ b/nixos/modules/virtualisation/google-compute-config.nix @@ -2,7 +2,6 @@ with lib; let gce = pkgs.google-compute-engine; - cfg = config.virtualisation.googleComputeImage; in { imports = [ @@ -12,6 +11,7 @@ in fileSystems."/" = { + fsType = "ext4"; device = "/dev/disk/by-label/nixos"; autoResize = true; }; diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index 0d2d25d30752..d172ae38fdcf 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -51,7 +51,7 @@ in popd ''; format = "raw"; - configFile = if isNull cfg.configFile then defaultConfigFile else cfg.configFile; + configFile = if cfg.configFile == null then defaultConfigFile else cfg.configFile; inherit (cfg) diskSize; inherit config lib pkgs; }; diff --git a/nixos/modules/virtualisation/kvmgt.nix b/nixos/modules/virtualisation/kvmgt.nix index 132815a0ad63..bfcf51d09c45 100644 --- a/nixos/modules/virtualisation/kvmgt.nix +++ b/nixos/modules/virtualisation/kvmgt.nix @@ -46,22 +46,24 @@ in { message = "KVMGT is not properly supported for kernels older than 4.16"; }; boot.kernelParams = [ "i915.enable_gvt=1" ]; + systemd.paths = mapAttrs' (name: value: + nameValuePair "kvmgt-${name}" { + description = "KVMGT VGPU ${name} path"; + wantedBy = [ "multi-user.target" ]; + pathConfig = { + PathExists = "/sys/bus/pci/devices/${cfg.device}/mdev_supported_types/${name}/create"; + }; + } + ) cfg.vgpus; systemd.services = mapAttrs' (name: value: nameValuePair "kvmgt-${name}" { description = "KVMGT VGPU ${name}"; serviceConfig = { - Type = "forking"; + Type = "oneshot"; RemainAfterExit = true; - Restart = "on-failure"; - RestartSec = 5; ExecStart = "${pkgs.runtimeShell} -c 'echo ${value.uuid} > /sys/bus/pci/devices/${cfg.device}/mdev_supported_types/${name}/create'"; ExecStop = "${pkgs.runtimeShell} -c 'echo 1 > /sys/bus/pci/devices/${cfg.device}/${value.uuid}/remove'"; }; - unitConfig = { - StartLimitBurst = 5; - StartLimitIntervalSec = 30; - }; - wantedBy = [ "multi-user.target" ]; } ) cfg.vgpus; }; diff --git a/nixos/modules/virtualisation/nova-config.nix b/nixos/modules/virtualisation/nova-config.nix deleted file mode 100644 index cecf2a3f144c..000000000000 --- a/nixos/modules/virtualisation/nova-config.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ lib, ... }: - -with lib; - -{ - imports = [ - ../profiles/qemu-guest.nix - ../profiles/headless.nix - ]; - - config = { - fileSystems."/" = { - device = "/dev/disk/by-label/nixos"; - autoResize = true; - }; - - boot.growPartition = true; - boot.kernelParams = [ "console=ttyS0" ]; - boot.loader.grub.device = "/dev/vda"; - boot.loader.timeout = 0; - - # Allow root logins - services.openssh = { - enable = true; - permitRootLogin = "prohibit-password"; - passwordAuthentication = mkDefault false; - }; - - services.cloud-init.enable = true; - - # Put /tmp and /var on /ephemeral0, which has a lot more space. - # Unfortunately we can't do this with the `fileSystems' option - # because it has no support for creating the source of a bind - # mount. Also, "move" /nix to /ephemeral0 by layering a unionfs-fuse - # mount on top of it so we have a lot more space for Nix operations. - - /* - boot.initrd.postMountCommands = - '' - mkdir -m 1777 -p $targetRoot/ephemeral0/tmp - mkdir -m 1777 -p $targetRoot/tmp - mount --bind $targetRoot/ephemeral0/tmp $targetRoot/tmp - - mkdir -m 755 -p $targetRoot/ephemeral0/var - mkdir -m 755 -p $targetRoot/var - mount --bind $targetRoot/ephemeral0/var $targetRoot/var - - mkdir -p /unionfs-chroot/ro-nix - mount --rbind $targetRoot/nix /unionfs-chroot/ro-nix - - mkdir -p /unionfs-chroot/rw-nix - mkdir -m 755 -p $targetRoot/ephemeral0/nix - mount --rbind $targetRoot/ephemeral0/nix /unionfs-chroot/rw-nix - unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot,max_files=32768 /rw-nix=RW:/ro-nix=RO $targetRoot/nix - ''; - - boot.initrd.supportedFilesystems = [ "unionfs-fuse" ]; - */ - }; -} diff --git a/nixos/modules/virtualisation/openstack-config.nix b/nixos/modules/virtualisation/openstack-config.nix new file mode 100644 index 000000000000..c2da5d0d2301 --- /dev/null +++ b/nixos/modules/virtualisation/openstack-config.nix @@ -0,0 +1,58 @@ +{ pkgs, lib, ... }: + +with lib; + +let + metadataFetcher = import ./ec2-metadata-fetcher.nix { + targetRoot = "/"; + wgetExtraOptions = "--retry-connrefused"; + }; +in +{ + imports = [ + ../profiles/qemu-guest.nix + ../profiles/headless.nix + # The Openstack Metadata service exposes data on an EC2 API also. + ./ec2-data.nix + ./amazon-init.nix + ]; + + config = { + fileSystems."/" = { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + autoResize = true; + }; + + boot.growPartition = true; + boot.kernelParams = [ "console=ttyS0" ]; + boot.loader.grub.device = "/dev/vda"; + boot.loader.timeout = 0; + + # Allow root logins + services.openssh = { + enable = true; + permitRootLogin = "prohibit-password"; + passwordAuthentication = mkDefault false; + }; + + # Force getting the hostname from Openstack metadata. + networking.hostName = mkDefault ""; + + systemd.services.openstack-init = { + path = [ pkgs.wget ]; + description = "Fetch Metadata on startup"; + wantedBy = [ "multi-user.target" ]; + before = [ "apply-ec2-data.service" "amazon-init.service"]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + script = metadataFetcher; + restartIfChanged = false; + unitConfig.X-StopOnRemoval = false; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + }; + }; +} diff --git a/nixos/modules/virtualisation/openvswitch.nix b/nixos/modules/virtualisation/openvswitch.nix index bb8b9172f23f..47e07e7432cb 100644 --- a/nixos/modules/virtualisation/openvswitch.nix +++ b/nixos/modules/virtualisation/openvswitch.nix @@ -49,7 +49,7 @@ in { config = mkIf cfg.enable (let # Where the communication sockets live - runDir = "/var/run/openvswitch"; + runDir = "/run/openvswitch"; # The path to the an initialized version of the database db = pkgs.stdenv.mkDerivation { @@ -99,13 +99,13 @@ in { --certificate=db:Open_vSwitch,SSL,certificate \ --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \ --unixctl=ovsdb.ctl.sock \ - --pidfile=/var/run/openvswitch/ovsdb.pid \ + --pidfile=/run/openvswitch/ovsdb.pid \ --detach \ /var/db/openvswitch/conf.db ''; Restart = "always"; RestartSec = 3; - PIDFile = "/var/run/openvswitch/ovsdb.pid"; + PIDFile = "/run/openvswitch/ovsdb.pid"; # Use service type 'forking' to correctly determine when ovsdb-server is ready. Type = "forking"; }; @@ -123,10 +123,10 @@ in { serviceConfig = { ExecStart = '' ${cfg.package}/bin/ovs-vswitchd \ - --pidfile=/var/run/openvswitch/ovs-vswitchd.pid \ + --pidfile=/run/openvswitch/ovs-vswitchd.pid \ --detach ''; - PIDFile = "/var/run/openvswitch/ovs-vswitchd.pid"; + PIDFile = "/run/openvswitch/ovs-vswitchd.pid"; # Use service type 'forking' to correctly determine when vswitchd is ready. Type = "forking"; }; @@ -152,11 +152,11 @@ in { ExecStart = '' ${cfg.package}/bin/ovs-monitor-ipsec \ --root-prefix ${runDir}/ipsec \ - --pidfile /var/run/openvswitch/ovs-monitor-ipsec.pid \ + --pidfile /run/openvswitch/ovs-monitor-ipsec.pid \ --monitor --detach \ - unix:/var/run/openvswitch/db.sock + unix:/run/openvswitch/db.sock ''; - PIDFile = "/var/run/openvswitch/ovs-monitor-ipsec.pid"; + PIDFile = "/run/openvswitch/ovs-monitor-ipsec.pid"; # Use service type 'forking' to correctly determine when ovs-monitor-ipsec is ready. Type = "forking"; }; @@ -167,7 +167,7 @@ in { ln -fs ${pkgs.ipsecTools}/bin/setkey ${runDir}/ipsec/usr/sbin/setkey ln -fs ${pkgs.writeScript "racoon-restart" '' #!${pkgs.runtimeShell} - /var/run/current-system/sw/bin/systemctl $1 racoon + /run/current-system/sw/bin/systemctl $1 racoon ''} ${runDir}/ipsec/etc/init.d/racoon ''; }; diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix index 60779579402c..41bcb909fb5c 100644 --- a/nixos/modules/virtualisation/virtualbox-host.nix +++ b/nixos/modules/virtualisation/virtualbox-host.nix @@ -83,6 +83,8 @@ in }; config = mkIf cfg.enable (mkMerge [{ + warnings = mkIf (config.nixpkgs.config.virtualbox.enableExtensionPack or false) + ["'nixpkgs.virtualbox.enableExtensionPack' has no effect, please use 'virtualisation.virtualbox.host.enableExtensionPack'"]; boot.kernelModules = [ "vboxdrv" "vboxnetadp" "vboxnetflt" ]; boot.extraModulePackages = [ kernelModules ]; environment.systemPackages = [ virtualbox ]; @@ -102,7 +104,7 @@ in "VBoxNetNAT" "VBoxSDL" "VBoxVolInfo" - "VirtualBox" + "VirtualBoxVM" ])); users.groups.vboxusers.gid = config.ids.gids.vboxusers; diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index 037c0d2f0d82..ab65523592d7 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -94,11 +94,17 @@ in { fileSystems."/" = { device = "/dev/disk/by-label/nixos"; autoResize = true; + fsType = "ext4"; }; boot.growPartition = true; boot.loader.grub.device = "/dev/sda"; + swapDevices = [{ + device = "/var/swap"; + size = 2048; + }]; + virtualisation.virtualbox.guest.enable = true; }; diff --git a/nixos/modules/virtualisation/vmware-guest.nix b/nixos/modules/virtualisation/vmware-guest.nix index 15c78f14c524..d18778f81588 100644 --- a/nixos/modules/virtualisation/vmware-guest.nix +++ b/nixos/modules/virtualisation/vmware-guest.nix @@ -3,19 +3,17 @@ with lib; let - cfg = config.services.vmwareGuest; + cfg = config.virtualisation.vmware.guest; open-vm-tools = if cfg.headless then pkgs.open-vm-tools-headless else pkgs.open-vm-tools; xf86inputvmmouse = pkgs.xorg.xf86inputvmmouse; in { - options = { - services.vmwareGuest = { - enable = mkEnableOption "VMWare Guest Support"; - headless = mkOption { - type = types.bool; - default = false; - description = "Whether to disable X11-related features."; - }; + options.virtualisation.vmware.guest = { + enable = mkEnableOption "VMWare Guest Support"; + headless = mkOption { + type = types.bool; + default = false; + description = "Whether to disable X11-related features."; }; }; @@ -25,6 +23,8 @@ in message = "VMWare guest is not currently supported on ${pkgs.stdenv.hostPlatform.system}"; } ]; + boot.initrd.kernelModules = [ "vmw_pvscsi" ]; + environment.systemPackages = [ open-vm-tools ]; systemd.services.vmware = |