diff --git a/flake.lock b/flake.lock index 075b12a4..c5469bd4 100644 --- a/flake.lock +++ b/flake.lock @@ -21,6 +21,21 @@ "type": "github" } }, + "flake-utils": { + "locked": { + "lastModified": 1649676176, + "narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "heliwatch": { "inputs": { "fenix": [ @@ -86,6 +101,25 @@ "type": "github" } }, + "microvm": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1652316068, + "narHash": "sha256-9vrbO7lnjd9t4xVnrPOBJXrg0pUA7oxuIj99F+Saxsc=", + "owner": "astro", + "repo": "microvm.nix", + "rev": "95bca60048a486d71d0d63f51e66bedabaf6a4c7", + "type": "github" + }, + "original": { + "owner": "astro", + "repo": "microvm.nix", + "type": "github" + } + }, "naersk": { "inputs": { "nixpkgs": [ @@ -234,6 +268,22 @@ } }, "nixpkgs_2": { + "locked": { + "lastModified": 1649986882, + "narHash": "sha256-cNsInUFq1MbuvaEmv8x6jetWnmAU+osMpnwKumtjksI=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "5181d5945eda382ff6a9ca3e072ed6ea9b547fee", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1651368560, "narHash": "sha256-OV6o5j27tnwqGhQd1u8/p5TjQI7+HyOnl6erteId4IE=", @@ -249,7 +299,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { "lastModified": 1651024496, "narHash": "sha256-uKSrrw/neSkxX6TXPSaMyfu7iKzFrK7F6HOt6vQefGY=", @@ -282,7 +332,7 @@ }, "openwrt-imagebuilder": { "inputs": { - "nixpkgs": "nixpkgs_3", + "nixpkgs": "nixpkgs_4", "openwrt": "openwrt_2" }, "locked": { @@ -320,9 +370,10 @@ "fenix": "fenix", "heliwatch": "heliwatch", "hydra": "hydra", + "microvm": "microvm", "naersk": "naersk", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs_3", "nixpkgs-master": "nixpkgs-master", "nixpkgs-mobilizon": "nixpkgs-mobilizon", "nixpkgs-openwebrx": "nixpkgs-openwebrx", diff --git a/flake.nix b/flake.nix index 7763f4ac..952c3a05 100644 --- a/flake.nix +++ b/flake.nix @@ -55,9 +55,10 @@ url = "github:nixos/hydra"; inputs.nixpkgs.follows = "nixpkgs"; }; + microvm.url = "github:astro/microvm.nix"; }; - outputs = inputs@{ self, nixpkgs, secrets, nixos-hardware, zentralwerk, yammat, scrapers, spacemsg, tigger, ticker, heliwatch, sops-nix, naersk, fenix, ... }: + outputs = inputs@{ self, nixpkgs, secrets, nixos-hardware, zentralwerk, yammat, scrapers, spacemsg, tigger, ticker, heliwatch, sops-nix, naersk, fenix, microvm, ... }: let inherit (nixpkgs) lib; forAllSystems = lib.genAttrs [ "aarch64-linux" "x86_64-linux" ]; @@ -542,6 +543,7 @@ server10 = nixosSystem' { modules = [ ./hosts/server10 + microvm.nixosModules.host ]; }; diff --git a/hosts/server10/default.nix b/hosts/server10/default.nix index 92390ec7..3797646a 100644 --- a/hosts/server10/default.nix +++ b/hosts/server10/default.nix @@ -5,6 +5,7 @@ [ # Include the results of the hardware scan. ./hardware-configuration.nix ./network.nix + ./microvm-staging.nix ]; # Use the GRUB 2 boot loader. diff --git a/hosts/server10/microvm-staging.nix b/hosts/server10/microvm-staging.nix new file mode 100644 index 00000000..fba7ffec --- /dev/null +++ b/hosts/server10/microvm-staging.nix @@ -0,0 +1,89 @@ +{ config, pkgs, ... }: +let + microvms = { + staging-data-hoarder = { + flakeref = "github:dump-dvb/nix-config"; + }; + }; +in +{ + microvm.autostart = builtins.attrNames microvms; + + systemd.services = { + "staging-dh-create-data" = { + description = "Create ZFS datasets for staging-data-hoarder shares"; + requiredBy = [ + "microvm@staging-data-hoarder.service" + ]; + before = [ + "microvm@staging-data-hoarder.service" + ]; + after = [ + "microvm-create@staging-data-hoarder.service" + ]; + serviceConfig = { + Type = "oneshot"; + }; + path = [ pkgs.zfs ]; + script = '' + cd /var/lib/microvms/staging-data-hoarder + for MNT in etc var ; do + [ -d $MNT ] || zfs create -o mountpoint=`pwd`/$MNT ${config.networking.hostName}/vm/staging-data-hoarder/$MNT + done + ''; + }; + + "microvm-update@" = { + description = "Update MicroVMs automatically"; + after = [ "network-online.target" ]; + unitConfig.ConditionPathExists = "/var/lib/microvms/%i"; + serviceConfig = { + Type = "oneshot"; + }; + scriptArgs = "%i"; + path = [ pkgs.nixFlakes ]; + script = '' + NAME=$1 + set +e + nix flake update $(cat /var/lib/microvms/$NAME/flake) + set -e + /run/current-system/sw/bin/microvm -Ru $NAME + ''; + }; + + } // builtins.foldl' (services: name: services // { + "microvm-create-${name}" = { + description = "Create MicroVM ${name} automatically"; + wantedBy = [ "microvms.target" ]; + after = [ "network-online.target" ]; + before = [ + "microvm-tap-interfaces@${name}.service" + "microvm-virtiofsd@${name}.service" + ]; + unitConfig.ConditionPathExists = "!/var/lib/microvms/${name}"; + serviceConfig.Type = "oneshot"; + scriptArgs = "${name}"; + script = '' + /run/current-system/sw/bin/microvm -c ${name} -f "${microvms.${name}.flakeref}" + ''; + }; + }) {} (builtins.attrNames microvms); + + systemd.timers = builtins.foldl' (timers: name: timers // { + "microvm-update-${name}" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + Unit = "microvm-update@${name}.service"; + # three times per hour + OnCalendar = "*:0,20,40:00"; + Persistent = true; + }; + }; + }) {} (builtins.attrNames microvms); + + c3d2.server.bridgePorts = { + serv = [ + "staging-dh" + ]; + }; +} diff --git a/hosts/server10/network.nix b/hosts/server10/network.nix index 4bc2ef59..2977c1e4 100644 --- a/hosts/server10/network.nix +++ b/hosts/server10/network.nix @@ -12,106 +12,126 @@ let in { - networking.useDHCP = false; - networking.useNetworkd = true; + options = with lib; { + c3d2.server.bridgePorts = mkOption { + description = "Additional interfaces to attach to bridges"; + type = with types; attrsOf (listOf str); + default = {}; + }; + }; + + config = { + networking.useDHCP = false; + networking.useNetworkd = true; - boot.kernelParams = [ - # Prevents automatic creation of interface bond0 by the kernel - "bonding.max_bonds=0" - ]; + boot.kernelParams = [ + # Prevents automatic creation of interface bond0 by the kernel + "bonding.max_bonds=0" + ]; - systemd.network = { - enable = true; + systemd.network = { + enable = true; - netdevs = { - bond0.netdevConfig = { - Kind = "bond"; - Name = "bond0"; - }; - # LACP - bond0.bondConfig.Mode = "802.3ad"; - } // ( - builtins.foldl' (result: net: result // { - # Bridges are named just like the corresponding net. - "${net}" = { - netdevConfig = { - Kind = "bridge"; - Name = "${net}"; - }; - extraConfig = '' + netdevs = { + bond0.netdevConfig = { + Kind = "bond"; + Name = "bond0"; + }; + # LACP + bond0.bondConfig.Mode = "802.3ad"; + } // ( + builtins.foldl' (result: net: result // { + # Bridges are named just like the corresponding net. + "${net}" = { + netdevConfig = { + Kind = "bridge"; + Name = "${net}"; + }; + extraConfig = '' [Bridge] ForwardDelaySec=2 STP=true ''; - }; - # External VLAN interface - "ext-${net}" = { - netdevConfig = { - Kind = "vlan"; - Name = "ext-${net}"; }; - vlanConfig.Id = zwNets.${net}.vlan; - }; - }) {} zwHostBridges - ); + # External VLAN interface + "ext-${net}" = { + netdevConfig = { + Kind = "vlan"; + Name = "ext-${net}"; + }; + vlanConfig.Id = zwNets.${net}.vlan; + }; + }) {} zwHostBridges + ); - networks = { - en = { - # physical ethernet ports - matchConfig.Name = "en*"; - networkConfig = { - Bond = "bond0"; - LLDP = true; - EmitLLDP = true; + networks = { + en = { + # physical ethernet ports + matchConfig.Name = "en*"; + networkConfig = { + Bond = "bond0"; + LLDP = true; + EmitLLDP = true; + }; }; - }; - bond0 = { - DHCP = "no"; - matchConfig.Name = "bond0"; - networkConfig = { - VLAN = map (net: "ext-${net}") zwHostBridges; - LinkLocalAddressing = "no"; - LLDP = true; - EmitLLDP = true; - }; - }; - } // (builtins.foldl' (result: net: result // { - "${net}" = { - matchConfig.Name = net; - networkConfig = { - LLDP = true; - EmitLLDP = true; + bond0 = { DHCP = "no"; - } // (lib.optionalAttrs (! zwNets.${net}.hosts4 ? ${hostName})) { - # Disable all automatic addressing on bridges. It will delay - # networkd going into operational state. - LinkLocalAddressing = lib.mkDefault "no"; + matchConfig.Name = "bond0"; + networkConfig = { + VLAN = map (net: "ext-${net}") zwHostBridges; + LinkLocalAddressing = "no"; + LLDP = true; + EmitLLDP = true; + }; }; - addresses = - let - netConfig = zwNets.${net}; - address = netConfig.hosts4.${hostName}; - prefixLen = netConfig.subnet4Len; - in - lib.optional (netConfig.hosts4 ? ${hostName}) { - addressConfig.Address = "${address}/${toString prefixLen}"; - } ++ - builtins.concatMap (hosts6: - lib.optional (hosts6 ? ${hostName}) { - addressConfig.Address = "${hosts6.${hostName}}/64"; - } - ) (builtins.attrValues netConfig.hosts6); + } // (builtins.foldl' (result: net: result // { + "${net}" = { + matchConfig.Name = net; + networkConfig = { + LLDP = true; + EmitLLDP = true; + DHCP = "no"; + } // (lib.optionalAttrs (! zwNets.${net}.hosts4 ? ${hostName})) { + # Disable all automatic addressing on bridges. It will delay + # networkd going into operational state. + LinkLocalAddressing = lib.mkDefault "no"; + }; + addresses = + let + netConfig = zwNets.${net}; + address = netConfig.hosts4.${hostName}; + prefixLen = netConfig.subnet4Len; + in + lib.optional (netConfig.hosts4 ? ${hostName}) { + addressConfig.Address = "${address}/${toString prefixLen}"; + } ++ + builtins.concatMap (hosts6: + lib.optional (hosts6 ? ${hostName}) { + addressConfig.Address = "${hosts6.${hostName}}/64"; + } + ) (builtins.attrValues netConfig.hosts6); - gateway = lib.optionals (net == "cluster") [ - zwNets.cluster.hosts4.cls-gw - zwNets.cluster.hosts6.dn42.cls-gw - ]; - }; - "ext-${net}" = { - matchConfig.Name = "ext-${net}"; - # Attach eth*/bond0/VLAN to bridge - networkConfig.Bridge = net; - }; - }) {} zwHostBridges); + gateway = lib.optionals (net == "cluster") [ + zwNets.cluster.hosts4.cls-gw + zwNets.cluster.hosts6.dn42.cls-gw + ]; + }; + "ext-${net}" = { + matchConfig.Name = "ext-${net}"; + # Attach eth*/bond0/VLAN to bridge + networkConfig.Bridge = net; + }; + }) {} zwHostBridges) // + builtins.foldl' (result: net: + builtins.foldl' (result: port: + result // { + "${net}-${port}" = { + matchConfig.Name = port; + networkConfig.Bridge = net; + }; + } + ) result (config.c3d2.server.bridgePorts.${net}) + ) {} (builtins.attrNames config.c3d2.server.bridgePorts); + }; }; }