From 5810750141604ca9715beda5bbe0d4f90fa5143e Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Tue, 3 Dec 2019 15:01:10 +0100 Subject: [PATCH] Add c3d2 options to module at lib/default.nix Options are for assigning deterministic addresses, statistics collection, MOTD, /etc/hosts, etc. --- host-registry.nix | 7 + hosts/containers/grafana/configuration.nix | 7 + hosts/server7/configuration.nix | 58 ++++--- hosts/server7/containers/adc/default.nix | 2 +- hosts/server7/containers/default.nix | 9 +- lib/default.nix | 170 +++++++++++++++++++++ lib/hq.nix | 2 - 7 files changed, 221 insertions(+), 34 deletions(-) create mode 100644 host-registry.nix create mode 100644 lib/default.nix diff --git a/host-registry.nix b/host-registry.nix new file mode 100644 index 00000000..4bd1b092 --- /dev/null +++ b/host-registry.nix @@ -0,0 +1,7 @@ +# Registry of C3D2 machines. + +let hosts = [ "adc" "grafana" "server7" "tox" ]; +in { + hqPublic = hosts; + hqPrivate = hosts; +} diff --git a/hosts/containers/grafana/configuration.nix b/hosts/containers/grafana/configuration.nix index c21f3cf3..57f69ced 100644 --- a/hosts/containers/grafana/configuration.nix +++ b/hosts/containers/grafana/configuration.nix @@ -2,12 +2,19 @@ { imports = [ + ../../../lib ../../../lib/lxc-container.nix ../../../lib/shared.nix ../../../lib/admins.nix ../../../lib/hail.nix ]; + c3d2 = { + isInHq = true; + mapHqHosts = true; + hq.interface = "eth0"; + }; + networking.hostName = "grafana"; networking.useNetworkd = true; # Needs IPv4 for obtaining certs? diff --git a/hosts/server7/configuration.nix b/hosts/server7/configuration.nix index 9a3b4966..e7960553 100644 --- a/hosts/server7/configuration.nix +++ b/hosts/server7/configuration.nix @@ -4,6 +4,7 @@ let yggaddr = import ./yggaddr.nix; in { imports = [ + ../../lib ../../lib/hq.nix ../../lib/default-gateway.nix ../../lib/emery.nix @@ -16,6 +17,15 @@ in { ./nix-serve.nix ]; + c3d2 = { + isInHq = true; + mapHqHosts = true; + hq = { + interface = "br0"; + statistics.enable = true; + }; + }; + # Route IPv6 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1; # Obtain global IPv6 despite being a router myself @@ -77,36 +87,24 @@ in { environment.systemPackages = with pkgs; [ tmux htop vim gitMinimal nixfmt ]; - services.collectd = { - enable = true; - autoLoadPlugin = true; - extraConfig = '' - HostName "${config.networking.hostName}" - FQDNLookup false - Interval 10 - - LoadPlugin sensors - LoadPlugin memory - LoadPlugin irq - LoadPlugin thermal - LoadPlugin processes - LoadPlugin disk - LoadPlugin hddtemp - LoadPlugin df - LoadPlugin cpu - LoadPlugin cpufreq - LoadPlugin entropy - LoadPlugin load - LoadPlugin swap - LoadPlugin cgroups - LoadPlugin vmem - LoadPlugin interface - LoadPlugin network - - Server "grafana.hq.c3d2.de" "25826" - - ''; - }; + services.collectd.extraConfig = '' + LoadPlugin sensors + LoadPlugin memory + LoadPlugin irq + LoadPlugin thermal + LoadPlugin processes + LoadPlugin disk + LoadPlugin hddtemp + LoadPlugin df + LoadPlugin cpu + LoadPlugin cpufreq + LoadPlugin entropy + LoadPlugin load + LoadPlugin swap + LoadPlugin cgroups + LoadPlugin vmem + LoadPlugin interface + ''; boot.tmpOnTmpfs = true; diff --git a/hosts/server7/containers/adc/default.nix b/hosts/server7/containers/adc/default.nix index cc77d974..110f4647 100644 --- a/hosts/server7/containers/adc/default.nix +++ b/hosts/server7/containers/adc/default.nix @@ -15,7 +15,7 @@ plugins.history.enable = true; plugins.welcome = { enable = true; - motd = builtins.readFile ../../../../lib/motd; + motd = config.users.motd; }; }; diff --git a/hosts/server7/containers/default.nix b/hosts/server7/containers/default.nix index 976b8a10..6403e5af 100644 --- a/hosts/server7/containers/default.nix +++ b/hosts/server7/containers/default.nix @@ -21,7 +21,14 @@ let localAddress6 = "${yggaddr.prefix}:${hextet0}:${hextet1}:c3d2/64"; # Generate a deterministic IPv6 address for the container. # This address is accessible within HQ and Yggdrasil but not from ARPANET. - config = import (./. + "/${name}"); + config = { ... }: { + imports = [ ../../../lib (./. + "/${name}") ]; + c3d2 = { + isInHq = true; + mapHqHosts = true; + hq.interface = "eth0"; + }; + }; }; }; diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 00000000..702d6e91 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,170 @@ +# This module is for use by all C3D2 machines. +# That includes physical servers, VMs, containers, and personal machines. +# + +{ config, lib, ... }: + +let + hqPrefix64 = "fd23:42:c3d2:523"; + # TODO: Is this stable? Is there a better place to specifiy this? + + # Generate a deterministic IPv6 address for a 64 bit prefix + # and seed string. Prefix must not contain trailing ':'. + toIpv6Address = prefix64: seed: + with builtins; + let + digest = builtins.hashString "sha256" seed; + hextets = map (i: substring (4 * i) 4 digest) [ 0 1 2 3 ]; + in concatStringsSep ":" ([ prefix64 ] ++ hextets); + + # Generate a deterministic public IPv6 addresses + # for the HQ networking using a seed string. + toHqPrivateAddress = toIpv6Address hqPrefix64; + + /* # Generate a deterministic public IPv6 addresses + # for the HQ networking using a seed string. + toHqPublicAddress = toIpv6Address publicPrefix64; + + # Generate a deterministic public IPv6 addresses + # for the HQ networking using a seed string. + toserver7YggdrasilAddress = toIpv6Address server7YggrasilPrefix64; + */ + + cfg = config.c3d2; + +in { + + options.c3d2 = with lib; + with lib.types; { + + isInHq = mkEnableOption "HQ presence"; + + enableMotd = mkOption { + type = bool; + default = cfg.isInHq; + defaultText = literalExample "config.c3d2.isInHq"; + }; + + mapPublicHosts = mkOption { + type = bool; + default = false; + description = '' + Whether to add all external HQ host mappings to /etc/hosts. + ''; + }; + + mapHqHosts = mkOption { + type = bool; + default = false; + description = '' + Whether to add all internal HQ host mappings to /etc/hosts. + ''; + }; + + hq = { + + /* externalInterface = mkOption { + type = nullOr str; + default = null; + example = "eth0"; + description = '' + Configure the given interface name with an external IP address. + ''; + }; + */ + + interface = mkOption { + type = nullOr str; + default = null; + example = "eth0"; + description = '' + Configure the given interface name with an internal IP address. + ''; + }; + + statistics = { enable = mkEnableOption "statistics collection"; }; + + }; + + }; + + config = let + cfg = config.c3d2; + hostRegistry = import ../host-registry.nix; + mkIfIsInHq = lib.mkIf cfg.isInHq; + in { + + assertions = [{ + assertion = let + check = hostName: hostName == config.networking.hostName; + checkRegistry = list: builtins.any check list; + in cfg.isInHq -> checkRegistry hostRegistry.hqPrivate; + message = "${config.networking.hostName} is not registered in ${ + toString ../host-registry.nix + }"; + }]; + + networking.defaultGateway = mkIfIsInHq "172.22.99.4"; + + networking.domain = mkIfIsInHq "hq.c3d2.de"; + + users.motd = lib.mkIf cfg.enableMotd (builtins.readFile ./motd); + + networking.hosts = let + mapHostsNamesToAttrs = f: list: builtins.listToAttrs (map f list); + + /* hqPublicHosts = mapHostsNamesToAttrs (hostName: { + name = toHqPublicAddress hostName; + value = [ "${hostName}.hq.c3d2.de" hostName ]; + }) hostRegistry.hqPublic; + */ + + hqPrivateHosts = mapHostsNamesToAttrs (hostName: { + name = toHqPrivateAddress hostName; + value = [ "${hostName}.hq" hostName ]; + }) hostRegistry.hqPrivate; + + in if cfg.mapHqHosts then hqPrivateHosts else { }; + + networking.interfaces = + /* (if cfg.hq.externalInterface == null then + { } + else { + "${cfg.hq.externalInterface}" = { + ipv6.addresses = [{ + address = toHqPublicAddress config.networking.hostName; + prefixLength = 64; + }]; + }; + }) // + */ + (if cfg.hq.interface == null then + { } + else { + "${cfg.hq.interface}" = { + ipv6.addresses = [{ + address = toHqPrivateAddress config.networking.hostName; + prefixLength = 64; + }]; + }; + }); + + services.collectd = lib.mkIf cfg.hq.statistics.enable { + enable = true; + autoLoadPlugin = true; + extraConfig = '' + HostName "${config.networking.hostName}" + FQDNLookup false + Interval 10 + + LoadPlugin network + + Server "grafana.hq" "25826" + + ''; + }; + + }; + + meta.maintainers = with lib.maintainers; [ ehmry ]; +} diff --git a/lib/hq.nix b/lib/hq.nix index 4182a7da..98edb2f1 100644 --- a/lib/hq.nix +++ b/lib/hq.nix @@ -5,7 +5,6 @@ let notServer7 = config.networking.hostName != "server7"; port = toString config.services.nix-serve.port; in { - networking.domain = "hq.c3d2.de"; nix = { binaryCaches = [ ] @@ -23,5 +22,4 @@ in { ./yggdrasil-hq.nix ]; - users.motd = builtins.readFile ./motd; }