{ zentralwerk, options, config, lib, pkgs, ... }: let defaultGateways = { serv = "serv-gw"; c3d2 = "c3d2-gw3"; pub = "pub-gw"; flpk = "flpk-gw"; }; inherit (config.networking) hostName; inherit (config.c3d2.deployment) server; serverFQDN = "${server}.cluster.zentralwerk.org"; generateMacAddress = net: let hash = builtins.hashString "md5" "1-${net}-${hostName}"; c = off: builtins.substring off 2 hash; in "${builtins.substring 0 1 hash}2:${c 2}:${c 4}:${c 6}:${c 8}:${c 10}"; nets = builtins.attrNames ( lib.filterAttrs (_: { hosts4, hosts6, ... }: hosts4 ? ${hostName} || lib.filterAttrs (_: hosts6: hosts6 ? ${hostName} ) hosts6 != {} ) zentralwerk.lib.config.site.net ); arch-to-host = rec { server9 = "westmere"; server10 = "ivybridge"; nomad = server9; }; in { options.c3d2.deployment = with lib; { server = mkOption { type = types.enum [ "server9" "server10" ]; default = null; description = '' Server that is supposed to host this MicroVM. ''; }; autoNetSetup = mkOption { type = types.bool; default = true; description = '' Automatically configure MicroVM network interfaces and systemd-networkd according to Zentralwerk network data. ''; }; mounts = mkOption { description = "Persistent filesystems to create, without leading /."; type = with types; listOf str; default = [ "etc" "home" "var" ]; }; mountBase = mkOption { description = '' Location (ZFS dataset, ...) where all the shares live. ''; type = types.path; default = "/var/lib/microvms/${hostName}"; }; }; config = { microvm = { hypervisor = lib.mkDefault "cloud-hypervisor"; mem = lib.mkDefault 512; vcpu = lib.mkDefault 4; interfaces = lib.mkIf config.c3d2.deployment.autoNetSetup ( map (net: { type = "tap"; id = builtins.substring 0 15 "${net}-${hostName}"; mac = generateMacAddress net; }) nets ); shares = [ { source = "/nix/store"; mountPoint = "/nix/.ro-store"; tag = "store"; proto = "virtiofs"; socket = "store.socket"; } ] ++ map (dir: if lib.hasPrefix "/" dir then throw "${dir} starts with a leading /. Just don't!" else let tag = builtins.replaceStrings ["/"] ["_"] dir; in { source = "${config.c3d2.deployment.mountBase}/${dir}"; mountPoint = "/${dir}"; inherit tag; proto = "virtiofs"; socket = "${tag}.socket"; }) config.c3d2.deployment.mounts; }; networking = lib.mkIf config.c3d2.deployment.autoNetSetup { useDHCP = false; dhcpcd.enable = false; useNetworkd = true; }; systemd.network = lib.mkIf config.c3d2.deployment.autoNetSetup { links = builtins.foldl' (links: net: links // { "30-${net}" = { # enable = true; matchConfig.MACAddress = generateMacAddress net; # rename interface to net name linkConfig.Name = net; }; }) {} nets; networks = builtins.foldl' (networks: net: networks // { "30-${net}" = let zwNet = zentralwerk.lib.config.site.net.${net}; addresses = lib.optional (zwNet.hosts4 ? ${hostName}) "${zwNet.hosts4.${hostName}}/${toString zwNet.subnet4Len}" ++ map (hosts6: "${hosts6.${hostName}}/64") ( builtins.filter (hosts6: hosts6 ? ${hostName}) ( builtins.attrValues zwNet.hosts6 ) ); in { matchConfig.MACAddress = generateMacAddress net; addresses = map (Address: { addressConfig = { inherit Address; }; }) addresses; gateway = lib.mkIf (defaultGateways ? ${net}) ( let gw = defaultGateways.${net}; in [ zwNet.hosts4.${gw} ] ++ map (hosts6: hosts6.${gw}) ( builtins.filter (hosts6: hosts6 ? ${gw}) ( builtins.attrValues zwNet.hosts6 ) ) ); }; }) {} nets; }; simd.arch = arch-to-host.${config.c3d2.deployment.server}; system.build = { copyToServer = pkgs.writeShellScript "copy-to-${server}" '' nix copy --no-check-sigs --to ssh-ng://root@${serverFQDN} $@ ''; runOnServer = pkgs.writeShellScript "run-on-${server}" '' ssh root@${serverFQDN} -- $@ ''; }; }; }