Add c3d2 options to module at lib/default.nix

Options are for assigning deterministic addresses, statistics
collection, MOTD, /etc/hosts, etc.
This commit is contained in:
Ehmry - 2019-12-03 15:01:10 +01:00 committed by Astro
parent 7f138f7b8f
commit 5810750141
7 changed files with 221 additions and 34 deletions

7
host-registry.nix Normal file
View File

@ -0,0 +1,7 @@
# Registry of C3D2 machines.
let hosts = [ "adc" "grafana" "server7" "tox" ];
in {
hqPublic = hosts;
hqPrivate = hosts;
}

View File

@ -2,12 +2,19 @@
{ {
imports = [ imports = [
../../../lib
../../../lib/lxc-container.nix ../../../lib/lxc-container.nix
../../../lib/shared.nix ../../../lib/shared.nix
../../../lib/admins.nix ../../../lib/admins.nix
../../../lib/hail.nix ../../../lib/hail.nix
]; ];
c3d2 = {
isInHq = true;
mapHqHosts = true;
hq.interface = "eth0";
};
networking.hostName = "grafana"; networking.hostName = "grafana";
networking.useNetworkd = true; networking.useNetworkd = true;
# Needs IPv4 for obtaining certs? # Needs IPv4 for obtaining certs?

View File

@ -4,6 +4,7 @@ let yggaddr = import ./yggaddr.nix;
in { in {
imports = [ imports = [
<nixpkgs/nixos/modules/profiles/minimal.nix> <nixpkgs/nixos/modules/profiles/minimal.nix>
../../lib
../../lib/hq.nix ../../lib/hq.nix
../../lib/default-gateway.nix ../../lib/default-gateway.nix
../../lib/emery.nix ../../lib/emery.nix
@ -16,6 +17,15 @@ in {
./nix-serve.nix ./nix-serve.nix
]; ];
c3d2 = {
isInHq = true;
mapHqHosts = true;
hq = {
interface = "br0";
statistics.enable = true;
};
};
# Route IPv6 # Route IPv6
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1; boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1;
# Obtain global IPv6 despite being a router myself # Obtain global IPv6 despite being a router myself
@ -77,36 +87,24 @@ in {
environment.systemPackages = with pkgs; [ tmux htop vim gitMinimal nixfmt ]; environment.systemPackages = with pkgs; [ tmux htop vim gitMinimal nixfmt ];
services.collectd = { services.collectd.extraConfig = ''
enable = true; LoadPlugin sensors
autoLoadPlugin = true; LoadPlugin memory
extraConfig = '' LoadPlugin irq
HostName "${config.networking.hostName}" LoadPlugin thermal
FQDNLookup false LoadPlugin processes
Interval 10 LoadPlugin disk
LoadPlugin hddtemp
LoadPlugin sensors LoadPlugin df
LoadPlugin memory LoadPlugin cpu
LoadPlugin irq LoadPlugin cpufreq
LoadPlugin thermal LoadPlugin entropy
LoadPlugin processes LoadPlugin load
LoadPlugin disk LoadPlugin swap
LoadPlugin hddtemp LoadPlugin cgroups
LoadPlugin df LoadPlugin vmem
LoadPlugin cpu LoadPlugin interface
LoadPlugin cpufreq '';
LoadPlugin entropy
LoadPlugin load
LoadPlugin swap
LoadPlugin cgroups
LoadPlugin vmem
LoadPlugin interface
LoadPlugin network
<Plugin "network">
Server "grafana.hq.c3d2.de" "25826"
</Plugin>
'';
};
boot.tmpOnTmpfs = true; boot.tmpOnTmpfs = true;

View File

@ -15,7 +15,7 @@
plugins.history.enable = true; plugins.history.enable = true;
plugins.welcome = { plugins.welcome = {
enable = true; enable = true;
motd = builtins.readFile ../../../../lib/motd; motd = config.users.motd;
}; };
}; };

View File

@ -21,7 +21,14 @@ let
localAddress6 = "${yggaddr.prefix}:${hextet0}:${hextet1}:c3d2/64"; localAddress6 = "${yggaddr.prefix}:${hextet0}:${hextet1}:c3d2/64";
# Generate a deterministic IPv6 address for the container. # Generate a deterministic IPv6 address for the container.
# This address is accessible within HQ and Yggdrasil but not from ARPANET. # 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";
};
};
}; };
}; };

170
lib/default.nix Normal file
View File

@ -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
<Plugin "network">
Server "grafana.hq" "25826"
</Plugin>
'';
};
};
meta.maintainers = with lib.maintainers; [ ehmry ];
}

View File

@ -5,7 +5,6 @@ let
notServer7 = config.networking.hostName != "server7"; notServer7 = config.networking.hostName != "server7";
port = toString config.services.nix-serve.port; port = toString config.services.nix-serve.port;
in { in {
networking.domain = "hq.c3d2.de";
nix = { nix = {
binaryCaches = [ ] binaryCaches = [ ]
@ -23,5 +22,4 @@ in {
./yggdrasil-hq.nix ./yggdrasil-hq.nix
]; ];
users.motd = builtins.readFile ./motd;
} }