From f62239b7a1383f53821e28a47479377dcfa7990d Mon Sep 17 00:00:00 2001 From: root Date: Sun, 7 Jun 2020 14:32:19 -0700 Subject: [PATCH] Working again having folded in france's changes. --- config/fudo/common.nix | 2 +- config/fudo/local-network.nix | 276 ++++++++++++++++++++++++------ config/local.nix | 1 + fudo/profiles/desktop.nix | 2 + fudo/sites/seattle.nix | 304 +++++++++++++++++++++------------- packages/local.nix | 9 +- 6 files changed, 430 insertions(+), 164 deletions(-) diff --git a/config/fudo/common.nix b/config/fudo/common.nix index 93c9823..9cc235a 100644 --- a/config/fudo/common.nix +++ b/config/fudo/common.nix @@ -16,7 +16,7 @@ with lib; domain = mkOption { type = types.str; description = '' - Domain of the + Domain of the local network. ''; }; diff --git a/config/fudo/local-network.nix b/config/fudo/local-network.nix index 29967c2..4cc653a 100644 --- a/config/fudo/local-network.nix +++ b/config/fudo/local-network.nix @@ -1,96 +1,276 @@ -# UNFINISHED! -# -# The plan is to bootstrap a local network config: DNS, DHCP, etc. - { lib, config, pkgs, ... }: with lib; let - hostOpts = { config, ... }: { - options = { - ipv6Address = mkOption { - type = types.str; - description = '' - The V6 IP of a given host, if any. - ''; - }; + cfg = config.fudo.local-network; - ipv4Address = mkOption { + join-lines = concatStringsSep "\n"; + + ip = import ../../lib/ip.nix { lib = lib; }; + + hostOpts = { hostname, ... }: { + options = { + ip-address = mkOption { type = types.str; description = '' The V4 IP of a given host, if any. ''; }; - macAddress = mkOption { + mac-address = mkOption { type = types.str; description = '' The MAC address of a given host, if desired for IP reservation. ''; }; + + ssh-fingerprints = mkOption { + type = with types; listOf str; + description = "A list of DNS SSHFP records for this host."; + default = []; + }; }; }; - localNameServerOpts = { config, ... }: { + traceout = out: builtins.trace out out; + + srvRecordOpts = with types; { options = { - ipv6Address = mkOption { - type = types.str; - description = '' - The V6 IP of this nameserver, if any. - ''; + weight = mkOption { + type = int; + description = "Weight relative to other records."; + default = 1; }; - ipv4Address = mkOption { - type = types.str; - description = '' - The V4 IP of this nameserver, if any. - ''; + priority = mkOption { + type = int; + description = "Priority to give this record."; + default = 0; }; - ipv4ReverseDomain = mkOption { - type = types.str; - description = '' - The domain of the IPv4 address range for which this nameserver is responsible. + port = mkOption { + type = port; + description = "Port to use when connecting."; + }; - Eg: 0.10.in-addr.arpa - ''; + host = mkOption { + type = str; + description = "Host to contact for this service."; + example = "my-host.my-domain.com."; }; }; }; in { - options = { + options.fudo.local-network = { - fudo.localNetwork.hosts = mkOption { - type = types.listOf (submodule hostOpts); + enable = mkEnableOption "Enable local network configuration (DHCP & DNS)."; + + hosts = mkOption { + type = with types; loaOf (submodule hostOpts); default = {}; - description = '' - A map of hostname => { host_attributes }. - ''; + description = "A map of hostname => { host_attributes }."; }; - fudo.localNetwork.domain = mkOption { + domain = mkOption { + type = types.str; + description = "The domain to use for the local network."; + }; + + dns-servers = mkOption { + type = with types; listOf str; + description = "A list of domain name server to use for the local network."; + }; + + dhcp-interfaces = mkOption { + type = with types; listOf str; + description = "A list of interfaces on which to serve DHCP."; + }; + + dns-serve-ips = mkOption { + type = with types; listOf str; + description = "A list of IPs on which to server DNS queries."; + }; + + gateway = mkOption { + type = types.str; + description = "The gateway to use for the local network."; + }; + + aliases = mkOption { + type = with types; loaOf str; + default = {}; + description = "A mapping of host-alias => hostname to use on the local network."; + }; + + network = mkOption { + type = types.str; + description = "Network to treat as local."; + }; + + enable-reverse-mappings = mkOption { + type = types.bool; + description = "Genereate PTR reverse lookup records."; + default = false; + }; + + dhcp-dynamic-network = mkOption { type = types.str; description = '' - The domain to use for the local network. + The network from which to dynamically allocate IPs via DHCP. + + Must be a subnet of . ''; }; - fudo.localNetwork.hostAliases = mkOption { - type = types.attrsOf types.str; + recursive-resolver = mkOption { + type = types.str; + description = "DNS nameserver to use for recursive resolution."; + }; + + server-ip = mkOption { + type = types.str; + description = "IP of the DNS server."; + }; + + extra-dns-records = mkOption { + type = with types; listOf str; + description = "Records to be inserted verbatim into the DNS zone."; + example = ["some-host IN CNAME other-host"]; + default = []; + }; + + srv-records = mkOption { + type = with types; attrsOf (attrsOf (listOf (submodule srvRecordOpts))); + description = "Map of traffic type to srv records."; default = {}; - description = '' - A mapping of hostAlias => hostName to use on the local network. + example = { + tcp = { + kerberos = { + port = 88; + host = "auth-host.my-domain.com"; + }; + }; + }; + }; + + search-domains = mkOption { + type = with types; listOf str; + description = "A list of domains to search for DNS names."; + example = ["my-domain.com" "other-domain.com"]; + default = []; + }; + + # TODO: srv records + }; + + config = mkIf cfg.enable { + services.dhcpd4 = { + enable = true; + + machines = mapAttrsToList (hostname: hostOpts: { + ethernetAddress = hostOpts.mac-address; + hostName = hostname; + ipAddress = hostOpts.ip-address; + }) cfg.hosts; + + interfaces = cfg.dhcp-interfaces; + + extraConfig = '' + subnet ${ip.getNetworkBase cfg.network} netmask ${ip.maskFromV32Network cfg.network} { + authoritative; + option subnet-mask ${ip.maskFromV32Network cfg.network}; + option broadcast-address ${ip.networkMaxIp cfg.network}; + option routers ${cfg.gateway}; + option domain-name-servers ${concatStringsSep " " cfg.dns-servers}; + option domain-name "${cfg.domain}"; + option domain-search ${join-lines (map (dom: "\"${dom}\"") ([cfg.domain] ++ cfg.search-domains))}; + range ${ip.networkMinIp cfg.dhcp-dynamic-network} ${ip.networkMaxButOneIp cfg.dhcp-dynamic-network}; + } ''; }; - fudo.localNetwork.localNameServer = mkOption { - type = (submodule localNameServerOpts); - description = '' - The master nameserver of the local network. - ''; + services.bind = let + blockHostsToZone = block: hosts-data: { + master = true; + name = "${block}.in-addr.arpa"; + file = let + # We should add these...but need a domain to assign them to. + # ip-last-el = ip: toInt (last (splitString "." ip)); + # used-els = map (host-data: ip-last-el host-data.ip-address) hosts-data; + # unused-els = subtractLists used-els (map toString (range 1 255)); + + in pkgs.writeText "db.${block}-zone" '' + $ORIGIN ${block}.in-addr.arpa. + $TTL 1h + + @ IN SOA ns1.${cfg.domain}. hostmaster.${cfg.domain}. ( + ${toString builtins.currentTime} + 1800 + 900 + 604800 + 1800) + + @ IN NS ns1.${cfg.domain}. + + ${join-lines (map hostPtrRecord hosts-data)} + ''; + }; + + ipToBlock = ip: concatStringsSep "." (reverseList (take 3 (splitString "." ip))); + compactHosts = mapAttrsToList (host: data: data // { host = host; }) cfg.hosts; + hostsByBlock = groupBy (host-data: ipToBlock host-data.ip-address) compactHosts; + hostPtrRecord = host-data: + "${last (splitString "." host-data.ip-address)} IN PTR ${host-data.host}.${cfg.domain}."; + + blockZones = mapAttrsToList blockHostsToZone hostsByBlock; + + hostARecord = host: data: "${host} IN A ${data.ip-address}"; + hostSshFpRecords = host: data: join-lines (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints); + cnameRecord = alias: host: "${alias} IN CNAME ${host}"; + + makeSrvRecords = protocol: type: records: + join-lines (map (record: "_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${record.host}.") + records); + + makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types); + + in { + enable = true; + cacheNetworks = [ cfg.network "localhost" "localnets" ]; + forwarders = [ cfg.recursive-resolver ]; + listenOn = cfg.dns-serve-ips; + zones = [ + { + master = true; + name = cfg.domain; + file = pkgs.writeText "${cfg.domain}-zone" '' + @ IN SOA ns1.${cfg.domain}. hostmaster.${cfg.domain}. ( + ${toString builtins.currentTime} + 5m + 2m + 6w + 5m) + + $TTL 1h + + @ IN NS ns1.${cfg.domain}. + + $ORIGIN ${cfg.domain}. + + $TTL 30m + + ns1 IN A ${cfg.server-ip} + ${join-lines (mapAttrsToList hostARecord cfg.hosts)} + ${join-lines (mapAttrsToList hostSshFpRecords cfg.hosts)} + ${join-lines (mapAttrsToList cnameRecord cfg.aliases)} + ${join-lines cfg.extra-dns-records} + ${join-lines (mapAttrsToList makeSrvProtocolRecords cfg.srv-records)} + ''; + } + ] ++ blockZones; }; }; } diff --git a/config/local.nix b/config/local.nix index 397fa3e..975917d 100644 --- a/config/local.nix +++ b/config/local.nix @@ -11,6 +11,7 @@ with lib; ./fudo/grafana.nix ./fudo/kdc.nix ./fudo/ldap.nix + ./fudo/local-network.nix ./fudo/mail.nix ./fudo/mail-container.nix ./fudo/minecraft-server.nix diff --git a/fudo/profiles/desktop.nix b/fudo/profiles/desktop.nix index ea1460f..630dfc5 100644 --- a/fudo/profiles/desktop.nix +++ b/fudo/profiles/desktop.nix @@ -72,6 +72,8 @@ with lib; # Splash screen boot.plymouth.enable = true; + networking.networkmanager.enable = mkForce false; + services.avahi = { enable = true; browseDomains = [config.fudo.common.domain]; diff --git a/fudo/sites/seattle.nix b/fudo/sites/seattle.nix index 12246a2..7cc9e0d 100644 --- a/fudo/sites/seattle.nix +++ b/fudo/sites/seattle.nix @@ -6,12 +6,20 @@ let local-domain = "sea.fudo.org"; + gateway = "10.0.0.1"; + + nameservers = ["10.0.0.1"]; + in { config = mkIf (config.fudo.common.site == "seattle") { time.timeZone = "America/Los_Angeles"; + services.printing = { + enable = true; + }; + services.cron = { mailto = admin; }; @@ -20,7 +28,9 @@ in { domain = local-domain; search = [local-domain "fudo.org"]; firewall.enable = false; - networkmanager.enable = pkgs.lib.mkForce false; + nameservers = nameservers; + + defaultGateway = gateway; # Until Comcast gets it's shit together... :( enableIPv6 = false; @@ -84,118 +94,190 @@ in { fsType = "nfs4"; }; - # Should use this eventually... - # fudo.localNetwork = { - # masterNameServer = { - # ip = "10.0.0.1"; - # ipReverseDomain = "0.10.in-addr.arpa"; - # }; + fudo.common.domain = "sea.fudo.org"; - # domain = "${local-domain}"; + fudo.local-network = { - # hostAliases = { - # kadmin = "slab"; - # kdc = "slab"; - # photo = "doraemon"; - # music = "doraemon"; - # panopticon = "hyperion"; - # hole = "dnshole"; - # ipfs = "nostromo"; - # }; + domain = "${local-domain}"; - # hosts = { - # slab = { - # ipv4Address = "10.0.0.1"; - # }; - # volsung = { - # ipv4Address = "10.0.0.106"; - # macAddress = "ac:bc:32:7b:75:a5"; - # }; - # nest = { - # ipv4Address = "10.0.0.176"; - # macAddress = "18:b4:30:16:7c:5a"; - # }; - # monolith = { - # ipv4Address = "10.0.0.100"; - # macAddress = "6c:62:6d:c8:b0:d8"; - # }; - # brother-wireless = { - # ipv4Address = "10.0.0.160"; - # macAddress = "c0:38:96:64:49:65"; - # }; - # doraemon = { - # ipv4Address = "10.0.0.52"; - # macAddress = "00:11:32:0a:06:c5"; - # }; - # lm = { - # ipv4Address = "10.0.0.21"; - # macAddress = "52:54:00:D8:34:92"; - # }; - # ubiquiti-wifi = { - # ipv4Address = "10.0.0.126"; - # macAddress = "04:18:d6:20:48:fb"; - # }; - # front-light = { - # ipv4Address = "10.0.0.221"; - # macAddress = "94:10:3e:48:94:ed"; - # }; - # ipad = { - # ipv4Address = "10.0.0.202"; - # macAddress = "9c:35:eb:48:6e:71"; - # }; - # chromecast-2 = { - # ipv4Address = "10.0.0.215"; - # macAddress = "a4:77:33:59:a2:ba"; - # }; - # taipan = { - # ipv4Address = "10.0.0.107"; - # macAddress = "52:54:00:34:c4:78"; - # }; - # dns-hole = { - # ipv4Address = "10.0.0.185"; - # macAddress = "b8:27:eb:b2:95:fd"; - # }; - # family-tv = { - # ipv4Address = "10.0.0.205"; - # macAddress = "84:a4:66:3a:b1:f8"; - # }; - # spark = { - # ipv4Address = "10.0.0.108"; - # macAddress = "78:24:af:04:f7:dd"; - # }; - # babycam = { - # ipv4Address = "10.0.0.206"; - # macAddress = "08:ea:40:59:5f:9e"; - # }; - # hyperion = { - # ipv4Address = "10.0.0.109"; - # macAddress = "52:54:00:33:46:de"; - # }; - # cargo = { - # ipv4Address = "10.0.0.50"; - # macAddress = "00:11:32:75:d8:b7"; - # }; - # cam-entrance = { - # ipv4Address = "10.0.0.31"; - # macAddress = "9c:8e:cd:0e:99:7b"; - # }; - # cam-driveway = { - # ipv4Address = "10.0.0.32"; - # macAddress = "9c:8e:cd:0d:3b:09"; - # }; - # cam-deck = { - # ipv4Address = "10.0.0.33"; - # macAddress = "9c:8e:cd:0e:98:c8"; - # }; - # nostromo = { - # ipv4Address = "10.0.0.2"; - # macAddress = "14:fe:b5:ca:a2:c9"; - # }; - # zbox = { - # ipv4Address = "10.0.0.110"; - # macAddress = "18:60:24:91:CC:27"; - # }; - # }; - # }; + aliases = { + kadmin = "slab"; + kdc = "slab"; + photo = "doraemon"; + music = "doraemon"; + panopticon = "hyperion"; + hole = "dnshole"; + ipfs = "nostromo"; + }; + + network = "10.0.0.0/16"; + + dhcp-dynamic-network = "10.0.1.0/24"; + + enable-reverse-mappings = true; + + srv-records = { + tcp = { + domain = [{ + port = 53; + host = "nostromo.sea.fudo.org"; + }]; + kerberos = [{ + port = 88; + host = "france.fudo.org"; + }]; + kerberos-adm = [{ + port = 88; + host = "france.fudo.org"; + }]; + ssh = [{ + port = 22; + host = "nostromo.sea.fudo.org"; + }]; + ldap = [{ + port = 389; + host = "france.fudo.org"; + }]; + }; + + udp = { + domain = [{ + port = 53; + host = "nostromo.sea.fudo.org"; + }]; + kerberos = [{ + port = 88; + host = "france.fudo.org"; + }]; + kerboros-master = [{ + port = 88; + host = "france.fudo.org"; + }]; + kpasswd = [{ + port = 464; + host = "france.fudo.org"; + }]; + }; + }; + + hosts = { + nostromo = { + ip-address = "10.0.0.1"; + mac-address = "46:54:76:06:f1:10"; + }; + lm = { + ip-address = "10.0.0.2"; + mac-address = "00:23:7d:e6:d9:ea"; + }; + # lm = { + # ip-address = "10.0.0.21"; + # mac-address = "52:54:00:D8:34:92"; + # }; + cam-entrance = { + ip-address = "10.0.0.31"; + mac-address = "9c:8e:cd:0e:99:7b"; + }; + cam-driveway = { + ip-address = "10.0.0.32"; + mac-address = "9c:8e:cd:0d:3b:09"; + }; + cam-deck = { + ip-address = "10.0.0.33"; + mac-address = "9c:8e:cd:0e:98:c8"; + }; + cargo = { + ip-address = "10.0.0.50"; + mac-address = "00:11:32:75:d8:b7"; + }; + whitedwarf = { + ip-address = "10.0.0.51"; + mac-address = "00:11:32:12:14:1d"; + }; + doraemon = { + ip-address = "10.0.0.52"; + mac-address = "00:11:32:0a:06:c5"; + }; + monolith = { + ip-address = "10.0.0.100"; + mac-address = "6c:62:6d:c8:b0:d8"; + }; + taipan = { + ip-address = "10.0.0.107"; + mac-address = "52:54:00:34:c4:78"; + }; + spark = { + ip-address = "10.0.0.108"; + mac-address = "78:24:af:04:f7:dd"; + }; + hyperion = { + ip-address = "10.0.0.109"; + mac-address = "52:54:00:33:46:de"; + }; + zbox = { + ip-address = "10.0.0.110"; + mac-address = "18:60:24:91:CC:27"; + }; + ubiquiti-wifi = { + ip-address = "10.0.0.126"; + mac-address = "04:18:d6:20:48:fb"; + }; + brother-wireless = { + ip-address = "10.0.0.160"; + mac-address = "c0:38:96:64:49:65"; + }; + nest = { + ip-address = "10.0.0.176"; + mac-address = "18:b4:30:16:7c:5a"; + }; + dns-hole = { + ip-address = "10.0.0.185"; + mac-address = "b8:27:eb:b2:95:fd"; + }; + xixi-phone = { + ip-address = "10.0.0.193"; + mac-address = "48:43:7c:75:89:42"; + }; + ipad = { + ip-address = "10.0.0.202"; + mac-address = "9c:35:eb:48:6e:71"; + }; + cam-front = { + ip-address = "10.0.0.203"; + mac-address = "c4:d6:55:3e:b4:c3"; + }; + family-tv = { + ip-address = "10.0.0.205"; + mac-address = "84:a4:66:3a:b1:f8"; + }; + babycam = { + ip-address = "10.0.0.206"; + mac-address = "08:ea:40:59:5f:9e"; + }; + workphone = { + ip-address = "10.0.0.211"; + mac-address = "a8:8e:24:5c:12:67"; + }; + chromecast-2 = { + ip-address = "10.0.0.215"; + mac-address = "a4:77:33:59:a2:ba"; + }; + front-light = { + ip-address = "10.0.0.221"; + mac-address = "94:10:3e:48:94:ed"; + }; + node-1 = { + ip-address = "10.0.10.101"; + mac-address = "00:1e:06:36:81:cf"; + }; + node-2 = { + ip-address = "10.0.10.102"; + mac-address = "00:1e:06:36:ec:3e"; + }; + node-3 = { + ip-address = "10.0.10.103"; + mac-address = "00:1e:06:36:ec:4b"; + }; + }; + }; }; } diff --git a/packages/local.nix b/packages/local.nix index fc00911..2e589d1 100644 --- a/packages/local.nix +++ b/packages/local.nix @@ -25,16 +25,17 @@ postgresql_11_gssapi = pkgs.postgresql_11.overrideAttrs (oldAttrs: rec { configureFlags = oldAttrs.configureFlags ++ [ "--with-gssapi" ]; buildInputs = oldAttrs.buildInputs ++ [ pkgs.krb5 ]; - sbcl-with-libs = pkgs.sbcl.overrideAttrs (oldAttrs: rec { - extraLibs = with pkgs; [ - openssl_1_1.dev - ]; }); postgresql_12_gssapi = pkgs.postgresql_12.overrideAttrs (oldAttrs: rec { configureFlags = oldAttrs.configureFlags ++ [ "--with-gssapi" ]; buildInputs = oldAttrs.buildInputs ++ [ pkgs.krb5 ]; }); + sbcl-with-libs = pkgs.sbcl.overrideAttrs (oldAttrs: rec { + extraLibs = with pkgs; [ + openssl_1_1.dev + ]; + }); hll2380dw-cups = import ./hll2380dw-cups.nix { inherit (pkgs) stdenv fetchurl makeWrapper cups dpkg a2ps ghostscript gnugrep gnused coreutils file perl which;